From 6d67295cc95e77cb4cd3e2d870634b8be0141504 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Sun, 12 Jan 2025 23:44:38 +0100 Subject: [PATCH 1/9] fix scripts --- scripts/create_perf_table.py | 2 +- scripts/run.bat | 2 ++ scripts/run_mpi.sh | 2 ++ scripts/run_perf_collector.bat | 1 + scripts/run_perf_collector.sh | 2 ++ scripts/run_perf_count_checker.sh | 1 + 6 files changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/create_perf_table.py b/scripts/create_perf_table.py index bd9b84283..d33b26aff 100644 --- a/scripts/create_perf_table.py +++ b/scripts/create_perf_table.py @@ -11,7 +11,7 @@ logs_path = os.path.abspath(args.input) xlsx_path = os.path.abspath(args.output) -list_of_type_of_tasks = ["mpi", "omp", "seq", "stl", "tbb"] +list_of_type_of_tasks = ["all", "mpi", "omp", "seq", "stl", "tbb"] result_tables = {"pipeline": {}, "task_run": {}} set_of_task_name = [] diff --git a/scripts/run.bat b/scripts/run.bat index 9c82be453..bc20417e3 100644 --- a/scripts/run.bat +++ b/scripts/run.bat @@ -9,7 +9,9 @@ if "%CLANG_BUILD%" NEQ "1" build\bin\sample_omp.exe build\bin\sample_stl.exe build\bin\sample_tbb.exe +if "%CLANG_BUILD%" NEQ "1" mpiexec.exe -np 4 build\bin\all_func_tests.exe --gtest_repeat=10 || exit 1 if "%CLANG_BUILD%" NEQ "1" mpiexec.exe -np 4 build\bin\mpi_func_tests.exe --gtest_repeat=10 || exit 1 +if "%CLANG_BUILD%" NEQ "1" build\bin\all_func_tests.exe || exit 1 if "%CLANG_BUILD%" NEQ "1" build\bin\mpi_func_tests.exe || exit 1 if "%CLANG_BUILD%" NEQ "1" build\bin\omp_func_tests.exe --gtest_also_run_disabled_tests --gtest_repeat=10 --gtest_recreate_environments_when_repeating || exit 1 build\bin\seq_func_tests.exe --gtest_also_run_disabled_tests --gtest_repeat=10 --gtest_recreate_environments_when_repeating || exit 1 diff --git a/scripts/run_mpi.sh b/scripts/run_mpi.sh index b2fd19792..b6ab4a3f8 100644 --- a/scripts/run_mpi.sh +++ b/scripts/run_mpi.sh @@ -14,10 +14,12 @@ if [[ -z "$ASAN_RUN" ]]; then if [[ $OSTYPE == "linux-gnu" ]]; then mpirun --oversubscribe -np $PROC_COUNT ./build/bin/sample_mpi mpirun --oversubscribe -np $PROC_COUNT ./build/bin/sample_mpi_boost + mpirun --oversubscribe -np $PROC_COUNT ./build/bin/all_func_tests --gtest_also_run_disabled_tests --gtest_repeat=10 --gtest_recreate_environments_when_repeating mpirun --oversubscribe -np $PROC_COUNT ./build/bin/mpi_func_tests --gtest_also_run_disabled_tests --gtest_repeat=10 --gtest_recreate_environments_when_repeating elif [[ $OSTYPE == "darwin"* ]]; then mpirun -np $PROC_COUNT ./build/bin/sample_mpi mpirun -np $PROC_COUNT ./build/bin/sample_mpi_boost + mpirun -np $PROC_COUNT ./build/bin/all_func_tests --gtest_also_run_disabled_tests --gtest_repeat=10 --gtest_recreate_environments_when_repeating mpirun -np $PROC_COUNT ./build/bin/mpi_func_tests --gtest_also_run_disabled_tests --gtest_repeat=10 --gtest_recreate_environments_when_repeating fi fi diff --git a/scripts/run_perf_collector.bat b/scripts/run_perf_collector.bat index 7beb05df4..b7260972f 100644 --- a/scripts/run_perf_collector.bat +++ b/scripts/run_perf_collector.bat @@ -1,4 +1,5 @@ REM mpiexec -np 4 build\bin\mpi_perf_tests.exe +REM mpiexec -np 4 build\bin\all_perf_tests.exe build\bin\omp_perf_tests.exe build\bin\seq_perf_tests.exe build\bin\stl_perf_tests.exe diff --git a/scripts/run_perf_collector.sh b/scripts/run_perf_collector.sh index 124620faf..a27c18bca 100644 --- a/scripts/run_perf_collector.sh +++ b/scripts/run_perf_collector.sh @@ -2,8 +2,10 @@ if [[ -z "$ASAN_RUN" ]]; then if [[ $OSTYPE == "linux-gnu" ]]; then + mpirun --oversubscribe -np 4 ./build/bin/all_perf_tests mpirun --oversubscribe -np 4 ./build/bin/mpi_perf_tests elif [[ $OSTYPE == "darwin"* ]]; then + mpirun -np 2 ./build/bin/all_perf_tests mpirun -np 2 ./build/bin/mpi_perf_tests fi fi diff --git a/scripts/run_perf_count_checker.sh b/scripts/run_perf_count_checker.sh index 180b1d695..b470a4bf4 100644 --- a/scripts/run_perf_count_checker.sh +++ b/scripts/run_perf_count_checker.sh @@ -40,6 +40,7 @@ run_check() { fi } +run_check "all" run_check "mpi" run_check "omp" run_check "seq" From cb5a849ed96ad2ddfb939bde015cca39d41d5ee3 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Thu, 16 Jan 2025 12:20:21 +0100 Subject: [PATCH 2/9] add ocv --- .gitmodules | 3 +++ 3rdparty/opencv | 1 + 2 files changed, 4 insertions(+) create mode 160000 3rdparty/opencv diff --git a/.gitmodules b/.gitmodules index ec1da98db..9f0c5e6c3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "3rdparty/onetbb"] path = 3rdparty/onetbb url = https://github.com/uxlfoundation/oneTBB +[submodule "3rdparty/opencv"] + path = 3rdparty/opencv + url = https://github.com/opencv/opencv diff --git a/3rdparty/opencv b/3rdparty/opencv new file mode 160000 index 000000000..31b0eeea0 --- /dev/null +++ b/3rdparty/opencv @@ -0,0 +1 @@ +Subproject commit 31b0eeea0b44b370fd0712312df4214d4ae1b158 From e321a54eb15ce4c2495e93866f57a8e181288dc4 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Thu, 16 Jan 2025 12:39:54 +0100 Subject: [PATCH 3/9] link opencv --- CMakeLists.txt | 1 + cmake/boost.cmake | 1 + cmake/gtest.cmake | 2 +- cmake/onetbb.cmake | 6 ++++-- cmake/opencv.cmake | 16 ++++++++++++++++ scripts/run_perf_collector.bat | 1 - tasks/CMakeLists.txt | 3 +++ 7 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 cmake/opencv.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index e0e7fba65..2d567ab7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,7 @@ project(parallel_programming_course) message( STATUS "Parallel Programming Course" ) include(cmake/configure.cmake) +include(cmake/opencv.cmake) include(cmake/gtest.cmake) option(ENABLE_ADDRESS_SANITIZER OFF) diff --git a/cmake/boost.cmake b/cmake/boost.cmake index 9fccb2a4f..9bd1b0dad 100644 --- a/cmake/boost.cmake +++ b/cmake/boost.cmake @@ -13,6 +13,7 @@ ExternalProject_Add(ppc_boost CONFIGURE_COMMAND "${CMAKE_COMMAND}" -S "${CMAKE_SOURCE_DIR}/3rdparty/boost/" -B "${CMAKE_CURRENT_BINARY_DIR}/ppc_boost/build/" -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -G${CMAKE_GENERATOR} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DBOOST_ENABLE_MPI=ON -D MPI_INCLUDE_PATH=${MPI_INCLUDE_PATH} -D MPI_LIBRARIES=${MPI_LIBRARIES} -D MPI_COMPILE_FLAGS=${MPI_COMPILE_FLAGS} -D MPI_LINK_FLAGS=${MPI_LINK_FLAGS} + -D CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} -D CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} BUILD_COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_boost/build" --config ${CMAKE_BUILD_TYPE} --parallel INSTALL_COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_CURRENT_BINARY_DIR}/ppc_boost/build" --prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_boost/install" TEST_COMMAND "") diff --git a/cmake/gtest.cmake b/cmake/gtest.cmake index 63d0b68b8..b574bd83a 100644 --- a/cmake/gtest.cmake +++ b/cmake/gtest.cmake @@ -8,6 +8,6 @@ ExternalProject_Add(ppc_googletest INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_googletest/install" CONFIGURE_COMMAND "${CMAKE_COMMAND}" -S "${CMAKE_SOURCE_DIR}/3rdparty/googletest/" -B "${CMAKE_CURRENT_BINARY_DIR}/ppc_googletest/build/" -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -G${CMAKE_GENERATOR} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - -Dgtest_force_shared_crt=ON -DCMAKE_CXX_FLAGS="-w" -DCMAKE_C_FLAGS="-w" + -D CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} -D CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} -Dgtest_force_shared_crt=ON -DCMAKE_CXX_FLAGS="-w" -DCMAKE_C_FLAGS="-w" BUILD_COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_googletest/build" --config ${CMAKE_BUILD_TYPE} --parallel INSTALL_COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_CURRENT_BINARY_DIR}/ppc_googletest/build" --prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_googletest/install") diff --git a/cmake/onetbb.cmake b/cmake/onetbb.cmake index 096b6b5a9..76523ed87 100644 --- a/cmake/onetbb.cmake +++ b/cmake/onetbb.cmake @@ -9,7 +9,8 @@ if(MSVC) BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install" CONFIGURE_COMMAND "${CMAKE_COMMAND}" -S "${CMAKE_SOURCE_DIR}/3rdparty/onetbb/" -B "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build/" -DCMAKE_CXX_FLAGS="-w" -DCMAKE_C_FLAGS="-w" - -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -G${CMAKE_GENERATOR} -DTBB_TEST=OFF -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -D CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} -D CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} + -G${CMAKE_GENERATOR} -DTBB_TEST=OFF -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} BUILD_COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" --config ${CMAKE_BUILD_TYPE} --parallel INSTALL_COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" --prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install" TEST_COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install/bin" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") @@ -20,7 +21,8 @@ else(MSVC) BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install" CONFIGURE_COMMAND "${CMAKE_COMMAND}" -S "${CMAKE_SOURCE_DIR}/3rdparty/onetbb/" -B "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build/" -DCMAKE_CXX_FLAGS="-w" -DCMAKE_C_FLAGS="-w" - -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -G${CMAKE_GENERATOR} -DTBB_TEST=OFF -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -D CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} -D CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} + -G${CMAKE_GENERATOR} -DTBB_TEST=OFF -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} BUILD_COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" --config ${CMAKE_BUILD_TYPE} --parallel INSTALL_COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" --prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install") endif(MSVC) diff --git a/cmake/opencv.cmake b/cmake/opencv.cmake new file mode 100644 index 000000000..77aa5d515 --- /dev/null +++ b/cmake/opencv.cmake @@ -0,0 +1,16 @@ +# Build googletest components +include_directories(${CMAKE_SOURCE_DIR}/3rdparty/opencv/include) + +include(ExternalProject) +ExternalProject_Add(ppc_opencv + SOURCE_DIR "${CMAKE_SOURCE_DIR}/3rdparty/opencv" + PREFIX "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv" + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" + INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/install" + CONFIGURE_COMMAND "${CMAKE_COMMAND}" -S "${CMAKE_SOURCE_DIR}/3rdparty/opencv/" -B "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build/" + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -D CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} + -D CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} -DCMAKE_CXX_FLAGS="-w" -DCMAKE_C_FLAGS="-w" -DENABLE_CCACHE=ON -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF + -DBUILD_EXAMPLES=OFF -DBUILD_DOCS=OFF -DWITH_CUDA=OFF -DWITH_OPENCL=OFF -DBUILD_opencv_calib3d=OFF -DBUILD_opencv_dnn=OFF -DBUILD_opencv_ml=OFF -DBUILD_opencv_objdetect=OFF + -DBUILD_opencv_video=OFF -DBUILD_opencv_world=OFF + BUILD_COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" --config ${CMAKE_BUILD_TYPE} --parallel + INSTALL_COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" --prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/install") diff --git a/scripts/run_perf_collector.bat b/scripts/run_perf_collector.bat index 9db5e6a2f..e5ac46cca 100644 --- a/scripts/run_perf_collector.bat +++ b/scripts/run_perf_collector.bat @@ -1,6 +1,5 @@ REM mpiexec -np 4 build\bin\all_perf_tests.exe REM mpiexec -np 4 build\bin\mpi_perf_tests.exe -REM mpiexec -np 4 build\bin\all_perf_tests.exe build\bin\omp_perf_tests.exe build\bin\seq_perf_tests.exe build\bin\stl_perf_tests.exe diff --git a/tasks/CMakeLists.txt b/tasks/CMakeLists.txt index 0253dbfb2..38989af9e 100644 --- a/tasks/CMakeLists.txt +++ b/tasks/CMakeLists.txt @@ -137,6 +137,9 @@ foreach(TASK_TYPE ${LIST_OF_TASKS}) endif() endif () + add_dependencies(${EXEC_FUNC} ppc_opencv) + target_link_directories(${EXEC_FUNC} PUBLIC "${CMAKE_BINARY_DIR}/ppc_opencv/install/lib") + add_dependencies(${EXEC_FUNC} ppc_googletest) target_link_directories(${EXEC_FUNC} PUBLIC "${CMAKE_BINARY_DIR}/ppc_googletest/install/lib") target_link_libraries(${EXEC_FUNC} PUBLIC gtest gtest_main) From abc1e3cd0962c9fd178eb175866d9bc8bf3671c5 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Thu, 16 Jan 2025 16:07:05 +0100 Subject: [PATCH 4/9] fix win clang-cl for ocv --- .github/workflows/main.yml | 4 ++-- cmake/opencv.cmake | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dfa73fea5..9ef1d343a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -766,7 +766,7 @@ jobs: uses: ilammy/msvc-dev-cmd@v1 - name: CMake configure run: > - cmake -S . -B build -GNinja -D CMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl + cmake -S . -B build -D CMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -D USE_SEQ=ON -D USE_MPI=OFF -D USE_OMP=OFF -D USE_TBB=ON -D USE_STL=ON -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -D CMAKE_BUILD_TYPE=RELEASE @@ -820,7 +820,7 @@ jobs: uses: ilammy/msvc-dev-cmd@v1 - name: CMake configure run: > - cmake -S . -B build -GNinja -D CMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl + cmake -S . -B build -D CMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -D USE_SEQ=ON -D USE_MPI=OFF -D USE_OMP=OFF -D USE_TBB=ON -D USE_STL=ON -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -D CMAKE_BUILD_TYPE=RELEASE diff --git a/cmake/opencv.cmake b/cmake/opencv.cmake index 77aa5d515..6ec1b6417 100644 --- a/cmake/opencv.cmake +++ b/cmake/opencv.cmake @@ -8,7 +8,7 @@ ExternalProject_Add(ppc_opencv BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/install" CONFIGURE_COMMAND "${CMAKE_COMMAND}" -S "${CMAKE_SOURCE_DIR}/3rdparty/opencv/" -B "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build/" - -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -D CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -G${CMAKE_GENERATOR} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -D CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} -D CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} -DCMAKE_CXX_FLAGS="-w" -DCMAKE_C_FLAGS="-w" -DENABLE_CCACHE=ON -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_DOCS=OFF -DWITH_CUDA=OFF -DWITH_OPENCL=OFF -DBUILD_opencv_calib3d=OFF -DBUILD_opencv_dnn=OFF -DBUILD_opencv_ml=OFF -DBUILD_opencv_objdetect=OFF -DBUILD_opencv_video=OFF -DBUILD_opencv_world=OFF From c93eaad91acdf9e115fb8df84a688530926c59d3 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Thu, 16 Jan 2025 18:54:51 +0100 Subject: [PATCH 5/9] add ocv funcs --- cmake/opencv.cmake | 5 ++--- tasks/CMakeLists.txt | 5 +++++ tasks/all/example/data/pic_mpi.jpg | Bin 0 -> 14731 bytes tasks/all/example/data/pic_omp.jpg | Bin 0 -> 20580 bytes tasks/all/example/data/pic_seq.jpg | Bin 0 -> 15356 bytes tasks/all/example/data/pic_stl.jpg | Bin 0 -> 51600 bytes tasks/all/example/data/pic_tbb.jpg | Bin 0 -> 14229 bytes tasks/all/example/data/test_mpi.txt | 1 - tasks/all/example/data/test_omp.txt | 1 - tasks/all/example/data/test_seq.txt | 1 - tasks/all/example/data/test_stl.txt | 1 - tasks/all/example/data/test_tbb.txt | 1 - tasks/all/example/func_tests/func_mpi.cpp | 15 +++++---------- tasks/all/example/func_tests/func_omp.cpp | 13 +++++-------- tasks/all/example/func_tests/func_seq.cpp | 13 ++++--------- tasks/all/example/func_tests/func_stl.cpp | 13 +++++-------- tasks/all/example/func_tests/func_tbb.cpp | 13 +++++-------- 17 files changed, 31 insertions(+), 51 deletions(-) create mode 100644 tasks/all/example/data/pic_mpi.jpg create mode 100644 tasks/all/example/data/pic_omp.jpg create mode 100644 tasks/all/example/data/pic_seq.jpg create mode 100644 tasks/all/example/data/pic_stl.jpg create mode 100644 tasks/all/example/data/pic_tbb.jpg delete mode 100644 tasks/all/example/data/test_mpi.txt delete mode 100644 tasks/all/example/data/test_omp.txt delete mode 100644 tasks/all/example/data/test_seq.txt delete mode 100644 tasks/all/example/data/test_stl.txt delete mode 100644 tasks/all/example/data/test_tbb.txt diff --git a/cmake/opencv.cmake b/cmake/opencv.cmake index 6ec1b6417..84c87d01c 100644 --- a/cmake/opencv.cmake +++ b/cmake/opencv.cmake @@ -1,6 +1,5 @@ -# Build googletest components +# Build OpenCV components include_directories(${CMAKE_SOURCE_DIR}/3rdparty/opencv/include) - include(ExternalProject) ExternalProject_Add(ppc_opencv SOURCE_DIR "${CMAKE_SOURCE_DIR}/3rdparty/opencv" @@ -11,6 +10,6 @@ ExternalProject_Add(ppc_opencv -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -G${CMAKE_GENERATOR} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -D CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} -D CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} -DCMAKE_CXX_FLAGS="-w" -DCMAKE_C_FLAGS="-w" -DENABLE_CCACHE=ON -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_DOCS=OFF -DWITH_CUDA=OFF -DWITH_OPENCL=OFF -DBUILD_opencv_calib3d=OFF -DBUILD_opencv_dnn=OFF -DBUILD_opencv_ml=OFF -DBUILD_opencv_objdetect=OFF - -DBUILD_opencv_video=OFF -DBUILD_opencv_world=OFF + -DBUILD_opencv_video=OFF -DBUILD_opencv_world=OFF -DBUILD_opencv_features2d=OFF -DBUILD_opencv_flann=OFF -DBUILD_opencv_photo=OFF BUILD_COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" --config ${CMAKE_BUILD_TYPE} --parallel INSTALL_COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" --prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/install") diff --git a/tasks/CMakeLists.txt b/tasks/CMakeLists.txt index 38989af9e..5cf8ac6a5 100644 --- a/tasks/CMakeLists.txt +++ b/tasks/CMakeLists.txt @@ -138,7 +138,12 @@ foreach(TASK_TYPE ${LIST_OF_TASKS}) endif () add_dependencies(${EXEC_FUNC} ppc_opencv) + target_include_directories(${EXEC_FUNC} PUBLIC "${CMAKE_BINARY_DIR}/ppc_opencv/install/include/opencv4") target_link_directories(${EXEC_FUNC} PUBLIC "${CMAKE_BINARY_DIR}/ppc_opencv/install/lib") + if(NOT MSVC) + target_link_libraries(${EXEC_FUNC} PUBLIC + opencv_core opencv_highgui opencv_imgcodecs opencv_imgproc opencv_videoio) + endif() add_dependencies(${EXEC_FUNC} ppc_googletest) target_link_directories(${EXEC_FUNC} PUBLIC "${CMAKE_BINARY_DIR}/ppc_googletest/install/lib") diff --git a/tasks/all/example/data/pic_mpi.jpg b/tasks/all/example/data/pic_mpi.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f1579e94694376c73f0322f38ccddfad12460860 GIT binary patch literal 14731 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 literal 0 HcmV?d00001 diff --git a/tasks/all/example/data/pic_seq.jpg b/tasks/all/example/data/pic_seq.jpg new file mode 100644 index 0000000000000000000000000000000000000000..34458023494a39d66880a98aa5dcad18eb14b249 GIT binary patch literal 15356 zcmb7r1ymeM+h(J|Lh#^jgS!(nxH}|3!r<;sAOsKYPH>0dE6e&6od zf6v*P!%WfLQ`J@7_0Ic9Kg~R?0BAB2(h>j^6aYX$Ucl2D)Qq&4n7)#VqJ*^E>wk89 z2OtHO1put99qm;lMM<@^bx5DB{PT@p``&{cY=3?J4+YZh<mpyF;3wpd(jL+|a@S=2LIFre$`zZZ5<)UDE+G2tEq@V>V}Xyt;v7Y z4gRYRwzdCtd?@4?0V_+VUw!>5zs?xN$XZ<$@`(WXBLo}(6+jXY{WX5b|Bzyn1pqu3 z000yDpKS(708r--0JwAi*+%&V0ABb3K<&tXw*6;LY~S0z|J@uc}B7ywT50pPhd z0AT(A0Him+_d(wNhjSx^>>`Ammks1)0$2h@04X31SOZ{y2~uMNSO8Xl>uDYk17M(k zm0#~LkOB)2`>PgAVo71sMPU1NFQ79WC$- z0Uiz!76ux!R|O4nIS^rBkx>xfV4>h3hd=?)FmUkC&@nJ!u~@NjUXmf;vT=)OeDcew z8Y8Em`noY_Uo!DAF1^Q*^SP5kQd-wxrQ0dNSA z4iO=HHP8Vl7-(2nXlTUe$S5$7gP@>c(BUuuSa`B$n5-h?%2?P4IBZ-h_Kp=*FL5b2 zMBm$e^!*e)Hcrhc_F7dfDyFidlaiL5TODi^o0UDfMrE*``7{UoY6==11|1Lr5SWE7 z$Aqi}Jt})ogXX0k>MxE4Ncus+5yA){#z7(OyeXs56>}TSH!UPkRd@`O)C&{{JxaZU z3dWq3W;mr(;ooeu)rI48wv;6---WI|e`ktH3MX~p!O-Jqs1~P7Du-|)?vnnfWirkq zuT!)eXP&2P%7V6bNT>UAR7v9-9GfNUT6naiu^sHoj5{-uI^vdD@Xc!%{{T>6;JR;T z^j;`v*-$g){&*Ef-QYewdTJ(m*~XkMUlwtsK|2hxS~#IuPyl4LqqfP=%$ygw_UiQc zKS7h}-j(sJdB&`MoTB8y`*}^$BTQvCa9?wAF>@$7VkekE2za z;EYQl*-~;cz?RzQ6w3M%sJ9|g1_RQ#y@IW5*{M#5NQqP_2EFW|$h;O7+Eh;8tls6j zRBK4ZOON4)9&M8K;zV<`(fUFFBp@5_T8aBalZI^xpNIM)8q9LZlNaXHYB3PXAF0^`<4(kgxJ*8aN~9k5zUxXXSPA zY6b(w)}kNKg3=#Y+ZT$F~iWgw2P|?BJ(Xx*NT=ZdxE^l>#b&d5egtiwlOi- zS2CLJ(zcNVsL1cTd}KaGItNjkFbi`r9%BriEl<%f3-wppmBvUFITgvmeKeAWrXLJY zmT;snllkZR1Q-1u*GI~<6kBQ932wY_KvW|ZJG$}WuJOm8g4^Xqu;9Grc|e^SxM6}A?Yk` zIX0_Gh(E*u%jttk$rNHyV|hw5qKyx`DzhZ^d7b)fg)-!;TC&EY9$9=pHqw4F*omK99fTb zK0=SyYR6mM7XsEy=hZ}&#;il1dD^SuC8SHW7I3DJ5kY`|4p+-E-|^yDn}xUsUh3q%LRVW;`k6fxz@O2+FXIuJ#m@ zT9}$EYR*MrpT$0K{N>#PbJJL~^b^238v0m*Sad94t9ja@yiqic+_3&qTychxy~ab~ zc4D4BlGK!1VDATVmTf3nx&SrWXNC!)0`8Qd+H%L}T&zd{*4h~W;J5Lqvz5nqi71lC z=R7$2;`PMj$u{b17`w_aqTJ(iLFRrr(v&{WL_*%?%4aVS|i6|A1IPccJ`s zbPYl!Y`-umdXJ_4D`)ojT5qnSx+1UJ8-dCkj)%dIxC1Dz(#HA*X$qD4C6PtgIOdnt zXR4CCc|)Kq+kGBk7$t-?9jm`r7i6fqv%5hhEq)BAAL7D3kDwEi+!-_+Qhd;qOiS4G zW6%eRuI|7TG0O9}8GVlBdVci2>}vUX^Rub5(&lD&rd8quec#e)>W|nT-1s7d0^R9z zwGZ{5kNHW4sP0q-m=kj^3X{xAxH;p(Wp?NiqooHq&OEYV<#8dmPJydzK5rEG)refOr( zW6+CaofzxqxT5cRhu=_lSC|lN*-!Pc$r9YoEh`+GWJO_}QgV_lj)}>0keUUeR-g!M zv<;8maPp&#qCh9TqPP0!@_C>nX&(Ph?gV$Dnmfms{jjJgZ>ffD#iGEX5kLh!kT@tNi4N}25OvU3x(lq^q&@q87} zle8LkPsu5Pa@~zH)YG!M`@}q^&n=y1N!3n?VNI*4`_8nxAU_SR*}Is^FdO(jr^0bL zcfmz47>~jS{6gEj_VW|K;nnvjVw$?X?t)snK!?k9lHF%9sk?S%*pRQNkmVRGcQlG? z_X!gNmoFSw0;U8OF?qO+TWd;>-K(%g*RXVjD~2kW?P$~wOuM>8@BeCyU>hV%Gc0a1 z{vl=6afmuIX*k(|fl<*{l7Z^AeNw#++*l$Txj5c#@I&Uz_Ln%p%)RaKx8Lnu;T4-S zN^D8*Wby})s;nj0I@JttTPpN=?>g^Z%f2d>c^P|?zxP!pV^C} zF`0M5ov1_xxWb(6NZSA2NOaSM=W`tmdr)@O{v@3QxW}J#tjnfSc}>R>RZcTak__gg zC?hdlX3^B)zt5XJYhKT+nVx^)@&q^*Jk!}MV<4{_NUiF7)7a3#D(AW?R8sFZ41Pmx zr8YEkfO8Q?xl^QIgcT?XLPeW`4|+!`iZvHen#Q2M0QZ$rj;5RRd6zSdSx@j(BhSyv z^pK1f_Mau}ES?v9VLa;xsl+nqvp~5kuT`VHlfytoUpsg^a*%PcwQ5^@ZKS;&^DzD% zQP4F3FMMV^(>VP5>De@cp?f-9jP-?iHt&l$^;cTzDfW=eMS^tFG$WsdT&MbVxyr&8cMO8(9`#HyS)ZX^63;m!7Gx z09!P3V$(2Ra(wMsk-Xr+uRVoQuH_q7zfX4bZWAp6TD~1ti`T9#&<5+Or&xAr#IbEg zgzUWI$hCVE^AdryO>2*t>Iu*g(!{rzvw?pCVh12`vG{Uk7Hjz0rRUArhfF+G*d3R2 zn&KP1>eFPQ!_9lKvwX~1qGL_wQ$H_)`ZJDN1rJXnNuE87mpMkMt{-Shc$um@_=>!; zuDUb_?cyA1T8m8j@ovRenbfou{9i}reSRc4^==7#0xC_e%g>&Gl~tyn_qJO0y2}3i z2O+24Y4_yK2=s4TGtS+EN6u)Ra3lN$x2td7L09#>c(XIH%Pd+;VAN{D<~@pqR~0Wf znZ`8dp13^ppG=O9!8a~UXy2rBVc?y(_!Z5d+nViqD2eK=YV3&Uw%)4!kx>*#)PUFg znw@<)Zw7hfAvWcXV`1Rj6md@>&~44VEpA^CBsoD`>sd8W3p+SsD-f7YgMKY^A(YFl zdcNdz1b?_WixF33l34x;o#^&3f?d{dyRJvgAv}}JT|&DzaLv6ldS8y-Jb#Ya^R;I$ z@&n>=QPOF^hbSJ|ND+ygx~x$zJMZv$aP{EGGO^ZNs{ESG#P+CnpWFT2|2{@~3LRnm4_iGoa88nO5jpz;Ki$f0yIkAXVL zJT0SGe}b#8A_NTaxf(AdDm6;aJ#u?fHGxkq#(Zfm zBF!aE*o#NzUZggr_)2UtfEjeVzxPqyI)CRrh2Z(T*BO#do|R%pQ23%tcdUp+?hbr+ z%bIq&$8FaJ?;-QU6YwB(_kR3h@CoR60*;@6>ovn!?2RXY|5`kmS)BN4RiLetl7Dq+ z6Eci*qvNjisAZmXn!fE-aSJt(4# z@{^4wGfmA9b#P*7bETD}Kq^vjbg*c`q{Fz40^kSqF^tR45+Y31EeBV!4}M+VtO{A( zE8H&8?!Dba`EBW}HEdxe^-12@g@eoFG>JdC^aXi~iT8#MPci37*bQenLh_<#-+g5$ zBz>(QMw`utE@2v8!6Au`v9|mC>v@~x>sdx(Q;{ctSOHOY*}=DTP8|1@Y0bscX1@B;}ivRTs=vn1FQS%pgad& zV{8>s7;DPSZvs=Jmr8FLXR?sg>6-n~Ns}<=AR#x(d`#9TfOz?DuAwUi&m1YQbEw$3&zG^Gwn|js+AUNu=3E0+V2yk#m@p z8E$GvKQA9KW*qHA0T5#+z9Z^tz#}=Ke)}hw!4rQ!c5m>GrPx{QY+0|S_eWLeVtDM8N z_m(1u>JV$-U);mkLehWi^#p_~SfSmCjS9KBYZNwQniQ#;yeTEa9HX%lTpu`Dj|tG3 z^V`n#QX)BzupHLmD{|t>D(1 zwnz+Z+qE7}1n!VtjAcYx^-AH@nbq^Z%<$ltk(c0)L|B27Hw~O44!-MmnYI6JoM-Mu z;ohR(2DyiR+;`#*JppiiQhgda!(?ui#jt~Al41mJJ$ev$f(u>El*YAFYcs?sIEoo) z2jVBIg6RC?V~EiT7o?(=Sn6y;EB$Lc=%|hIzAj_e4oo^?D@qE)8|J4h;*vt(pFCvs zX~0j`VRq@e&A&2x%~aDkTI^h6RjH@kH`$Eef**&L9^nG|;djz*8(32C{O>GD%nagg z?YJ$Rxa8&^#z4jEGR)*Yk4rMP;^wppcSoS)q>M?o+jf!kNoD0(57hdZ&>_p!eYTY% zX<>3^ec_b9TplgY#;&;VoyG4*uTN|PchT$>vbKwc6z0+Q`ID&ah#zT^@;~rp=~53( zs1mGdXh}&VWtzn?V99ETgZaCxrt=5}0{m@Tv*SwRcH|XXk}a!5e^2ALx1h=53v(mU zr6IlV={iB%JhQnxsLzdq5G(*fS+=8eCU2t`nMW^?^j(Vu&K^~NWg79{>(9)FjH+nH z5VwMs49{V0XsTVlF{L|y(#awnjrWO zv0wQ7RtSY<Tgaz$cC_g*vDyqCtjhFYR%<+_Y2giI<3R!w6DHOU>(kLB7w7GML~lOPnslo8oj#s(#AFrn#z6fD5%c5p zfn<-erIC!EdHOa8SF{#wG>Zf`$1fwW{O|N056LdQXuj6qX7_<6&c3 zLh&mGP*gjgcHk$Knq!s9m8$il>C@XeM;254_)_ZY`$Z4jEl8RE1k5umuniU6_77Ik z%dYj$3c_MxP^62Y3LNd63IF(*m&(`clZY>1DTqFX?i^w=Q`c6-KH@Er+5*rin%$5D zwC$1<2Y62t6?vy@J^>;lb8C*Ew4cYJbz2XjY@SqSG#r@D{nA|rb=LBd??z`eB0mUhjVh7%KWCL=Kk)&5zNbAo~L2rf5nKgLUZWaa_ z{HYl>yL9~SDcA)Y!DB}J^DdAzgWZ_W`Cu(TcKi)zQ}s z&~Z!Azi36@89Q;GNWf$rIHN&+0t{VROWOKI&%;+Bw7!bX!MFqS=odP$lvN-kzA^PN&&3nP zTWL<^CFQ9v<7o8J=a)qhp5mGXTu~Fk`#tCQF+m6?Sa0|N`U&{*p_XQ9y~sP&=n0S? znKe*hj7eX{Qy%8?^PlrPaDW6e&t*+r8_kf#8%Quy(4Fl>kmGUtJ~LBRQL3-X`>rmt z=p*B)12rZXnf(3pcceT%*!6ClA?~p~)49Tm>jYg_9lQM&&Ad}673yRrbo=!BOj4v; z+W{-VT!~AtS7ARN=@_b#|IK#QZ$E@T&?F6$E}~=3dA6T@3&iD#kXd_{>0VKX-nXSY zh=}RUL_S%(l9YHjjp*`6I$&5e{kv=$nO4(P%PYe*DyB0fGCX-^jnny~5LRF@F69Rw zv=^Ghp*31txF{iTg~9CBI=g?D5h}W5TP2rkNuQYvz;=zEgN0V%D^OTByT|R0R0tzx zeGJ+~^bj{ai8z;(lAWVxHoG|vh}ab>_9-vpm-Xfz{P4-UrYAJ|_(d;VAk`$U>Z>`) z!`^adtw&`pT<2WRxymW(q`W$P9F6|C@iA7yQ%asrj~L)N0=`*h0T0rZmRD9p_$#CL z>IZgLlZiKck5MH&i@(<+HHa+s5NTEH4dpzoW_-Q}$8K&Yw=heWZ0xDte1{UN?5{|d zX(1w!ESm+Bn*<67&kjW+5+(a+r(`i}jB7!jQ?wiWk(dhiSn&Rbx(XJ!V2S%rdy-a&lS`FrD2^xW ztt)*yd{pLjpagnCWqdG!#C_lfET>EDW(VO=oobd^5bqXFd%)rg?^t>VwIzZpOz`+y zZ5gcV3U{tz1BV!>7w}p9zD1)+(1)>RjnP2!NuBmIJscGuT53zy?36 zcrDzV*m@-MS5y}FCZ)_ts*g7Pwd*Kw#ncRt1^;HV@-HXNL{HPAH$w~}`ss7SmJW@5 zG7A-cgpobWNy{PNzV9p%Lx8V`lI7P}u0!|Q2H)h`$eU1hzUIYXOj}uOMm_bAcA?`END>8x?kVwHKD zM&_F$teS)1t-R>dAV{hzPb5hQjo&T?UFz;HF_5<%jUmt<`^xFvR7&>;Dh*u*)r>a- z&@xJ$7Nk;`h^C3ru;PJJ;r+o2Wj<7jKPM0$Oly4u(QdhDXBe%g`5b0(6#BUd>KqY^RLg~CgMavK zt)n>E#!y}8C^hFBHW(ykpN8y$U7EDN(3-1OQ%HF`N2@}^mFNDLXJCp;ai`(I~HYG_7_XH9d~+ z?H&FAR`LIkmte`Tz$`vdrcup3lx|7pfpfqm$!~F!DAeU!;Io}MuJYa1d9|6kgn=yq zo&CX9GSj9klM<^jm(i_&4_=m#fm|)_OhzkQH73sVNUh+;2S*yRt6ZIj?OiBdv&k|n zCxY?XRvHG+MDvZXE`PyNr@C1a2rTU#VD0z?OQ}QUc_6SfK1|_9;q+vsd}Rxwxl2`8 zylJN+6d`ObJF~(T*{Ng>I^BtD8AbPMT7))wU1ZnPMVcX-TagOJc42g}jzHAFMkY8? zY)U3t_;qpfa$T@$8}=@@4(EFut6EtIrjGcenXQrqMnBr*LrdpDMZ1W70_w7FbdTFk z`noGwAyPy`p1)E-m1a$T<8Lj3u@JGdWEG+iQUr@P{s}Ec&X*313F_rMu^HsTH$Ths zc8eyBvL5)U_rJp1riFIK?tH8nZb`)x)p;C67AK_5;dio zZ?U-`D%xv9Gs85z??Xq*sdk;15geSr`W9Viyewsp6we9_2NWrWXc_G6N_q>a#GR!H zimq}ICq(C`2gRzSX7c2X)#O$eM)ya5Or&8!dr$rrS<6-%>4bW*iC@?2>y`JF6k~d# z?g(xp`G;?CefvbOH`?}k_f|gr@60Zma-k}!hewlXv5Yr@c zZ*zTzuB4NK4xS~Q_Pkts)p+|w{Y~Mm5Oq(d^Rj10d|`^}&n${M-JjSj+jR{PTDFDE zGKkc?=gUPERJ!h0V`C5W4S|y)SG#XdK;eUWe@5O}xn-RV)Au+sRe^3#+@RxWOStU6 z$=GNkNq57Gptlf~xT|_$;35dQF);su3}yQ!s=3P(+ik@4w7ndg=i6TBkeIYP_SmdV z(qP1SDGZnWNJCrhe6KP;rxY_?5H%_rJk#`_%!QF4^Zrfbwg0vouk$|$3Vy5bL%x^O z=ObVF3gVq!Z9%5fCDvS8o&CKinE~77(VLgG0XNgjgnofE3Fg#~YLe`oj(tH~7JqVg zjJLiBDivxMRjd1qAJN$tGRU?e3_B_Z^TcE9Ci@ugbp6}L0df_;uD9i%*adH`LKu8c z3w*8D&#H)n1dlu1yaS|MI$QdeQ!aM;P5#XV{Xi;NJ!a|_4_$OK`|k+kuEHzomOGyS z@e}SOQE=en=gaOvhw`geku}IS&Ne3O3rkGlg=rNz*s&tEcaBeh9b^eT*3;e2wykAc z3O!WR&eg8DLUcltAyC{&HL{Dw$il%nf0oSL~cz zrApa+`uVSFHN>&WWJJhCf~DapVTdSSFuc3ut?G9b;p%Eb^Ng49Owo>N8$z^m!+t9GFa;_>@5uGp8(rS$oCc2L^`<(u z9y?^ZWSmhZn?L@NdUbI8*Ecr>GgYGsG-F!zsQvPxW@OMiht<^a^CU?J8n`A6I^+NZ zU-6)iFeR(S*^b0TlQjbI*~2Ujct(xBHT7#)YJLnTyF>HtIK3xQsdG`_U_!8#v`Wp&KTfyocy{gJUeYLAkE>jBf!ngphgH`*>(_ zACWTD7IjH*xH<35G+)}FG1%S1m->Ne*0xf=LT0mZX&X-a4(gifs{-$Uk|V(V9MO(|ogKK$Ymvt*a%TBSP9 zsWYxiqncaDdl5~5OUVO4 z$51{{p0{L|fmt6;+1pqi3pe&JdXKRS6@@$(`W?vxSP2nSQWP#^b8nm8afu`PyXK&O zO>aNO_1@PtaP?Pw%^uiLQ_kZbh=r!{Z4p3R-FHySwkAf&0eKLXFWz74*=VZ>9Nio(<(NoLT+uto&GVjhRzt(#5 z^yXu}y909&eO-}B&fyf-5o;3xVbNqt#r)xcuG+4-!UyG=l;0Cg1+)Y4Zz%9K`GbcJ zv9(T#-?l8@txhFRn2z7sL4;E220!CzTv&dthqyV;nj8ZMWZI1#R|U0fl`qip-I$q( zt3j(I%AQZa-Pk2Rds~5Cx%VTRtn>Y7hA;l0y_A9l=?_m`klgUuSN;**s~+2lktWf} zq>HgwEymWLB9^gOpC=OKD@^M;p<%7Yk)|zA->Bc2m#HyMs~-gKtNk|MWc|t{zL1pw zb~I5R7@Rv($4w8y;G=9bb<(yer8&M2vpca!%U$R%^JFq#4wM67NYXF?Umce~{qo~c=y5seijy3sz&Q-nP zzhdm!Si|5jm?x)sEtZiVL(%bOy*MJ-{IkTkrI12jb^pLFoRk#;rTro+20776;mmztLJZ?4rR`zofEK&D+$G* z_cv9N+dzBtkl$oKE@s(_MGW_oXn#Sm8SogtuI??ZqLXcyWF%kbh@ESsM+GvLvZE*p zwd9KE3<3WIl4%5Hgo+Sbqvg%(?HjmBx$Fw*wrJ@_YH;-p)ON^or!Mz$G(i%`Z&$ed zG?!x5X%f^8yE zQBTXAQ<~d^2LrLc=lyoXaQ?fB?m)FP6!QMGt>V&I_awLSR*elBn|kV=N&?}a(FQ46 z22zT!k4%Jk@WQdsC#-L#=l>-HAda6q(=80!k=P2J350#hU&Tv097m_`o7uY2JS^(AE&vzLVvgp;&}z#kt4ZMVh0FZLzE+mXPNnlT z!>O0bh6mYpO|B|flc4F0gAqQo)P?uqWf)%&s8vz&nZ~pg#eJTwp@+(A6!L2q2q}94 zb@90ch&~!w*%;En{L<9?srJe7xuV^)R`Trf)(yp$_L_=P=MYUUk6H%qH-*%AhF4^0ys1Mwzd)Ph%LkKq4T_KbryH5(pF048|Dyq3JRx^*2`;B8=#7p zf~AExV8h#QRx>)REEIpl<(qS2F-ob*2qPd;%ls&BR1p_dbW5B^IsI4irzGq&7_CVH z^Wbn7mo7!PNf=hCrP!KEutB73^Wu1}ZuJVH*7oFRN9D*H;T>_xqP&p^)R*@faqaaAW8mt;5QKcu(ZA|F2vd%k z0K#ECdly{Q*4X5Q+&PfcWaBhOe(Y%b$vAbHd|7=_L>W1590%G8$QFhK26)&x7nIX9uUPw<@D?PFyVafn zj+2ETNq|hltgJ1K7c0s!ioZ9&r26u-b1%Qt?7WmMP3;s%i`L57CuMakGA+c{P>-gY z=w15#w%fXITijj*jR;6zJqfwSSvGz$gq?;dZrY|f>jf5FQ&&|e! zq{p`V#26T(Pk;^c8c7<@kN+rM-2zu_h?|diWXpdH$joWeE!2mbMgo_5n}lf+hbsk2 zAb>r9-9?oRaU-<$vU1#6Gv~2%Q z9BD=uhTZ#4cZ-^IZ1U7^P&S-NqSA?Q7Ea{vFfm+wV? zc*r>aU2)xyW`Ty3+ACdhrfX{VcbIZdK*|%qJaPV%Ho?qbmgDmqd|9{_BXwx4-{uc!NPzr7D2yB;+jt>e zlxM`uh5$usLu`0SGeSV)H%FJ5Nn18vL@yejul7|*O&p6%$T2o4HhmPmm9|p0`H%A) z|Br)RHl#vp9;db|9wHY1@}FduAbQW7dN%>S~*=S3TDWpANFMQBo0^n^k6A z0()Kd!q=>JtGDQFH8FATlz{Rlk~CQ|{YXoojOvKBtFe6yr3rdx{v%MK=@E~gEk7q2 z^VY;^`!8WC^eCYveb@VI{#DNYdF*1zyk!H#5=sK!q>(R=73g4;(3gX=!9^Vd90 z4a1PDU0XyzFE=<_9x`uujyY`3yCJZSdZdWPLu!`~|8)iQmm^y9kY8CoP4d2}`7lrT z5@+pH@6GMFM(O+!TL-rH0tqi?^*^aC8;R1f+w2PWo{RU|2<5m}>TjA=R-?=^siw4o z$hW<+D2>68Ekq0qpc5IG!UI%xG5v<@-(~jfc9HgwN;S0<{m==-t=jaibz0>$SZf(pJ&DPOQ1gZ3SrUa3atBJ1YbQH;GR#EYN)UKKN_qxJb{OOm0+b7o;^ z>JXj!gUkQT8`|m;a^hSA@vLQ@MeyuBtZj=P(`-s}Og<!foQEPYD(A_GcokyEFn zT0h@#(GB>fLZH*mf+8b=35&ZA>$bKu`l4D8^D5S)^0{K9-syv?Yq{wDGG#owwla~Q z1n$kiC`QEcyq^bS@vL6;-~h-|W1guRbGhXEcJyFSXH(4B-wf8la2HSDlm9{^X%vz4 z{7KB_=N8E>dD&w7!afZLfu6B1Um2`kks`n=`K5>O%h`vO3n3mI;v@M zZcr4A)#j%i{U?nY5t>bRB;&2`BzjBLNVSyvaPD&IUCCPMN_C7$akHG~0HtiihmE7z z$b9YH_jrk|*O#%@Hu3~~3VztNR31}xuCl7SqA|jM^*nlCHP5fhqp_!lO%muKuGHo{ z2$=N9ALAWKy%73j-?W%}-$#?&R)q1hR~>(%txm3+xm0dIZgOEtgO~nG{hW$4Z$P?@ zqX8?2fmu&@<|-xe_a1+RhboWP8iNgy$1abTPRU{B9FGeq$sEzvU__@5GK_;WHy14x zcDwh%F)#&T8!n+HR*b17<9kEKj@QaV)cerrgBrU^YNWZUt8{6hh=Tbf?4|DbGS-u! z3Sxb;5_Nt{7Lb!ZPYHe=Y8XHk>h)UqkL^m`A@p`}ve`+@bxE5|Cs@<9Wo{2YJxv@D z9dCggGXgg~vVFp|gOx~_Ty1Jj5)-0RzImmr#x9y|jOhSEB7QF;#P+qj&`v*C%|s0Q z$?%luf|Mi-j(@=IKm857&fyXodmv&qtfCK#3O5t3lq+~s%fV<$ zRS-cl7ak85UYRl{gPI`aNl4*v$9b<&iIKg5qc~XNq*fo*t-~&I8?tBw+pco@U6>j% zSXEdK8e9Ui84jcO-8grAmtb-)|EFQRwl_-;yZ1NLKTpl*^Gls4O2#=4#vLj5jW2m( zv*A0D(ahmmg2`qipL@cc|7D4hjoF3__X~`o5Rt{7kGxUzd{v0u{FuF}VUVwCf0d9h z^tM38c*$I%5Awj}a|lVgz=uHUYqE|E?$0`hF<3fb7!iChutxv|hkyF*I5JB8%LF4( zwMZ_bT_4`}^-PSm?OBb)Y&`+hmqf5=B5bT7C)lxV7$ zSdd3Re)}sR94(?v$*U#FE)u?q8o}^a7Y-z}`lB@vE*61Wf>rOOqQ}p4{nh9VUqsbH zZ!eRW3~z4X zW(L0C4E&~W1^+p?v6x^P)9SZO^Gi1UEergTJ>8w%!PhANl3mqR#lf;USf;W1FS6-> zkR8);4b~=7)1^M@H!X(Xqx!XvH$dmvx%$8Kh;5lKOrqG0f38Q003DB z0KoVL03hi7a}NCRKeUYme2Ng)D1b8@jcm$-^NC=21i16^pXviq9QBl!Q5s=U^&`~kK zGU~5NAb#Bm1q}zj5fu?05q$LjV|n=uK!bw-Kmwp3$N-RN5Kw3kFMR+a@RLJ9{3`!G z?JGC{EIbS}6y&ed+Nj|1fP;ZVL`Q~(0^bR~8UO))0yK0Cm{)L^SlFaExMUQpY@#8B z4b$wL+&mI0>Y7?6R)N8Jb$yfD@Ob1@QqpGTF8M`YHYhp7Bxy{0s4WwDfBi88xVqov z&p*S!zJi8>0@n`@KCO!efPjR7goc8FghfPp1qTKGi3SA?gH8&7#b6axd4)-ah0UgF zLN12GZtCLtfr6St%`HBmwr6shl8TdC+{`>Ex2|`JOF}&`F@FmVSJEOW@5@I0=K0GK z015mY;L6Yd!T^O~OnPK2Ng9R{GQ~`2aZDuvG44CU86U&f21h@9X!yYq5Id8ufg71jwgb z2ix%)ofce;(&0b66ij#;(s!H0vg}K~@AhCar3!`#-mPunbk#A!>mB#v$kdI=8TjSn zm`{j0Ye*Bqi?AHLkN(0QjGE1Q!`DwCbsk^gh|5YsYRp8zLWr`DXYr;jb?9BaWW}8E z=MM-pteU}LK)fM%lo1~PiH}etwuo3m$!{7XF*6ry9*A1#*9}l-OD6|PqXb!n6@0>tLgIaKsCXp@PQ=$KiZymH)pko)*AaPz zr|y9(r9)Le;`8#Cg$7cA&#`MJu9P&A=83eCe?FtSqiq@#y&;qH4 zVHZ!{S_zzLFSi@I#`7b3NUO?2A{;}nO{$7HtDns$v-3*E{UrXtW=H3|B@MxRzXe~Y}Tt3z(F{$aQh#b4AKh=D{B0)pI- z(^>@vv4t7lPTJ>+$ydT#1J_Ls{j)97EZcS@OAX9PTIdP_In~9nORUGqJH*f~vpp*e zJrIKF+)1%%D9{(4tV)R*W?Q)_s^&rR+neeIrJ_P{@UHL&QY_y4W2BT7d;m@%@d0Hl zslmpY^|??@i!tGdjTFSHMv+kcq4P@;nA2qBl-9*&ne90?`v>QVO13dz$aR!Kpf`NJ zG$9mRZyCfWIgcp(C9zwD5hR^$0-ZXcAtuywZL;4xG8ckwr@kmM1PONupi?igD%-rt zfb_t*9UU-SH~nvKbl}S$Ev~GG;@r8i*N{`&dd2b{Y--Q#ZM3c)-vznNF(ba+o*TUM z|E8+ZztI?++;rm;=x;pw1$v247i#L4l>l+$%D$EzJH?nmtK7kOAvD=}4Vo1gCz@mkzL#0YN2V(3B?P-U3 zs~tc!yumWqiG@1 z{9OAS(H3cCQq`X{xH{uZ9WmR2N7}wpG$q4LM&LHmqK8wzgC)0Oy*8@Tpmd7#)6J@f zK*T8&;Zd5gNb){72Ch!=$D~qQDA%NZ5YY$lQ1V)!je7D-3gn8767eP{p2UAXApF2M zRZ@=?bqkHCvwGic>|=LFPl@hwL{9YFmOQ$jXwTgpP9Hava*&O2gR!W_$*wsURBrpG zx!fy#U}?$!Jba3~KSXB=8=XGyj?(1=s)>9JO8L`Ans;i!GwGIQN}2Pla-4fpyAIs5YPZw(($ zE-G1MEalYYC(Kv zsg@rM27Z8iCxX-RE%>2&mG#ZKkE@;AbUZapL7}X+R!JN#rFahS;C|&ZGKOfvAKROqM4zzjBmH%Q%8TDU_tLWJkCeUs$?E2 z(J=ruAFDmT)fxR5y`7I3Jq@K|U=1m*iOX3b#tR_+V_R?m3+X3{pMtHdsq>Uf*&jAh zrR1=2Uj4kWnwbmIO<6quZr}P{gAG)OLmJH;S)Q1nS_ENwDur0X<3~iJ6I9GL1ogL802-Ux zSJW-o%=kxw@fwz23L%{f0pIWMU)%Bgny70jDYDAB-eeLw{e$sif0^}s2l zE@!%)DbvxF*Pqhl2jY52vu8awe^);@NGWhw(9qsj2_@}i0JP7b!@@(A`0jUEdB{$^ zoe}IMqGPcSEduC|G$3ICHoret9o^q5`~CzE1~t8jt5%YR^{h%&DOqwFK`y2=f0i5W zU2MAX9+M(3@U2!Vv5CCx&+upJ0W5D(xX=&1WaJ_G@G2w}4D1XZp1z(D^Cj#;Y@hs4~oy_5pK9W zAM|MQ_mo&PSrVhclwnMMYoo9=LJe#F7~NcUbUZO;=Y%{rWLcyiP-&+lz#*}#Nf|VT z>O7GQG=Pf01aEiW-U>a+E6Ho-EM^-`?l%v`4iN=IW4X4f30V8^q!Hw0q0Zj6>&KE&xT<0OT|7SJl3RdLd)lHmOQa&zPPlrj#J)ox921^v{YH7&QlM`)R>&!0c=RbUtARf)9A?sC^O_d?7w`q(0}vYIPl-AK-BU zj{g~oPyc-=fRCyR9*n0uf>{mJA$>l>L91q*rCP%V%SDwTJ+^%515bt1d5MKO$`YA8 zo49#iD`o-lV=eL)i3gUI8Tskz51nnw zX%%N6G^&+WcwOh?u#<%u>fS|*Z_O*TIvHgMTcn!X=t&Z?R`$ZwP(&Pzwb}CN#9f4< z#tpa02)m`9n(BA-)UZ0$8P))E-*9~S;=33aWwUBN8ZZwrAX$f?Qw%|s!LMSBZlw;e z_55dx;W$cCSVUDELQN{rJLqxAN`bXNX*;<6rlF~Yj{^7_5SxGVO+DA)vz3dpdrD`@Yd}jsuC`Mw*kM?rAttHIq~zha!+e9MDM4`o%L? zjLXgOYQ*;#h&hWQZ~@UAhFWX&GelT(f8A&p1jOv55)>6#2xgQpStLnVwED_kEhP8! zaM7KRT7>w-C9yBOhso?;ZZdEfzX$XSxDNVKre6zHPMT*2TD$L`qge&SV<@;jWHJwVQ68#q55Odqb$DtY%MgQ;Nw5R zl-_B=L{X=#8CPP7x(S&S%cdi$&A8cfi{aN$(KU!XisT`}F8S*A0wDezd2Lzv-h(UeTa5j^yON_ zBOK;9=OE{Gb?#~%rHx6MQb`$ePm9PytE@8ILXxUNF?)o zdWEUhJ|5^!vmp6gp!HN(STi06FNe+Itj>@stfMUtmIlL;|UlJOw2!)JQZX33M1sHWHg$ zR+~A;<2#y-bx+#jtsZHVhgK-v5y80!l!;1CMmciVyqTP=tmm=>xUZOT4*OWX;(vgvX(A2x5WgEKW za@}Mr?c~M!Ua*C6f9W2H!@3p?~DXSj+&oUTY9TuCnU$vDf zNG;4^Ne6)uRwTl%{D+0~Y(9GLM9^8ZP>c)KZOK-|A(==K-r}%dxbihcdAw5ger49p z&st%7ID=!uX8Dw}>AQBByXtSc2;;u1Q{N^HReb@&@vj7pU>L+rk0chtR1<$k_xL2$ zY12S4MX5$f30;J55LQy3peUDRel=N=`~P+~%<)m$3t$cB5fq@=>?Io;_X0qhrE9HF z%G)uY#tO@`#E3Gu%0d=WFLbwld)bSz(`{=dxVUoBw%9dxZ^Rb0mn9s#Dm-ssKA3r( zA4$8qC*JnB)_~nyzcfrzEUJwLPy(A)TaN7>@V;}EepVJVPMl%TPGR@J^R?5S*S=jJ zU0t1hNF-Wf72Z>wN=rfR$yrq)Ud>TB;(3*<4TrIWNT6ilssdL9`txV@O}A1_@7v~j z{c?REfXzIL)S)tS_1mMV8E{Q!5#y;(rE7bhLvN?gzvqYft#on)H^NA9V~Hx&jn=#P z72-J7p_)X6Z+);q?JvV8haQKM@ZDQEOfdViY=Bp#jQz02REma_l~Z`UZgbN=XQute zobd1?NxyAKvP42~^>i4xW>X@JK!n{lxzG5Tzk%&m@hSC4vgKAVEup`pV>6;7exlm( zYhR7=FmzzWbTQakf|=y!&vIAKdSKVJEU>*V&}kB_cBsN^1Mdvgp_PS!oDJa3T`F9Z z|1(QA>qOmgLa}3KAvwM*ZOVIfN5aT)JR<|m8>#6c&FyJscIZk{ks5kDQ{pMn!|HjN zn-_q`h{182{tMu#NZR`aP@c2uZ}Vrt_|gw~Y0jony|;1Ar#$6pDmc*c87&oF1;)^~ z85Agn@n=~@{w$t<0ay#r6^>vU=6$N9vQTxcnMtBd)js-;kpREzbC_K|$*s9mB2jpJ ztAas~TmgyoT|chSJ1GR?fNnQ$r4@G4NogQ3hUmt1!&mPaFF^5OQrZ1)r5Gy3Y-5>V zdpIDDDl=1gg?7vN%k$|S>zz?zaW^tudzI6ej}ASuMY94$H z&ne^_Ql(ZNbp&(luyV?8YPT%Q17&7y3?Mgr&TxcpE!AjJkZV?Sn@=p^7>wjgh^J=hUFeEa~g zlPXUyyLT+*TPX8>O=w{=#0~Q>jHNTB`~lJ^L6L<5F(L0ieR1iC+|yP-nTQUrE2~T# zMHK7q$C2NCsF#703^+-ux zty0O-2cV7gC?tqi24)JTXbuX167Aj9>R+l;i9g?H3ti+wCzdG#Pbv#vlcWm^P(;v< zPVsYgH9B1fJthsuwmdtX8Elq*cP}=*+qeeN+s|x!2H>p24Qe5*5e=h$+Uu;OY2T1* zZ09&5C%r$rZ>QTFThk`QQ zN?V;wQ$5QGl%kTu)g3()Jq0GyCG+>Q`4S{V-*J^v_ZD3)JNm^MXT3EHtj)8;IeD`1 z0y^!mlGt`-fJn3jSgYKlS)`FT z_-F)=(SFld?@}Kb<31HnZi=M`m)Nq(T2K@;mW-gX24xp@c3>4LPL-hLO!VkerVf)Z zQc_lg5+y-cK?{F7xYngKe}0bycEM(L(ii@y|NJHy#R$s@`#g83aL8_+6W+E~-e#bn zX#R}NC0!IRQ;Q8P=}ZU(e>5)?56``=%7!0gC9u5jqcA->IuaX%E@s>fNqq_62;M1o zeyW@PQsfA6H;eP5VO!TRm3(zQp;G#<4jxk}^D(f_S)Y{W3R|$G7B(=QE*ufzXqP4R z*=e`85`5Y$^d*rSF4KACB?tYkfG;ugr0uF39eQ!9Mh8}`74KIl^(4u=@Wj=wO+Bu! zEEQtrJ@s#+p-rzyO;>&oosjd+Sd^}22_1h^!;WPnrT2|O5yF^~$MA`qaS=%zLYQld zNH3guYH%OT7wNJcgMG8Og=w*1iof=kA@bkV$0AFqLEn+OsXO6Rnw?l*U+Xkh<{;#) zS?yWBS;Po-cxW>hk0~>wgt_>>YxY+)FgxvQ5{MruA;nkK+OSiRKpGUp^G*{r@vl6e zEAIoDl`^VR2JJ(m9$ol%u2z4teQyg`qPZa*$Elth`&5CyRIGa~me4(kc%#?WmlU4= zK?j}HRu!6zJrsg~_hZddAip;8{@k_qB*V0w2QA-zFlgB}8MnYBFv#5f{y9Frwll+g7Yu?wGN6m z{OoHM%XC6pcilZUJ4M=GlWS}x3(WBlxLyEq)hj0lm+^TqFb%XYWilke;{a&iJ+9s+ zS=1>j8=>7tmfR5#P&Zq0Wsuz`a8^pT0lh9(X7G!8{AfAD3qaqtN3h}g`5>H{J}z*x zKo?#&eji1|yp;S?jLvh*WceTaH_|3<>f;OGO&vSkh1ydWxl6}d<2p-HGMp2to2byM zU7u*Lzr!OFQe@*TRAbj#V7CYp^@Q5()?Oh(q4K#T1RVWCLc{9?e9ZW|;NN3ec*4s! zY6e-)7KHQ)rJ#7`J5pd)@W#~>XbqFMKh-Vq8&KyG4NABqwyHBZt|2s4AoDKmy)jPr zHFxRs_EQ{bsFL5gBflVBk?p$V@KEl-CEgboyRRMX6ChdxGKT`uh>O)G_N>Pf7fokA zwOZe^2bmPhCGUuG-F+)P%SAhsTx;;=VX2)cms*mB%LzA1nz@CmkUFsFbt$mDMz3yT z!_KIX7OMWWFFZnpj_LC&iiG?RDLj)UdU@}aDYuJ_OReB#B16#g2O(T25}eug@CEbnTax#CdNa*r?rRwKz?=<9+X^Xa2+Uv5vdk`#W;=Jx-#$Sg^hem`)JKhU9{qO+0=)%VN zKN_*NoLX8A+UoR(QW}Ex918>*qT}5q`pMV@1N7B8#LfiSvFNok8yY70ZQb4i^b4stbS>n-ZC@o~&l z3PN;K&vo9#jBAOQ&!s9U0zx0el(r zO?kN4381)ILjML5S%bBi|F+(@!MBq`3N*0s|}l8+sJ`52iWw2r4q+IYf!*o2v^n zTjat9?u5a+Yh`^b=H$JRHH5(u2#oKKKuX)g1`e~?gR9gJ26ZRMLbT=LFkkNceHWK6=X7Kg656lbX2qAJ| zOl82NI1pq)RGrvejHkub-8vnF|Qg=tDRD=lNF&WO*4&KUm?n_l-5cywXuX#y9>f)<&qE|Mh9vm z*X5oF$4G%|srJ`DW@O=3VqLgse{CJ+ZdyOt4*$(x@ zw>F_mMZ1pnRFCE!%V?Lt)cK75SV4Gv8aAEu8q2R%-*Dw3`F<|_HuknXYT0UWzM3HO9Cbbxk<;-c%R6=T zcT||xq0r!S%Zhk3lIZ_VZ}Dop;SG0ztNk_i_wtAOfYk1zN=E{N!`4;DId*O>U)F(> zo9}WD-#5Lgs23JisM_Z}CeW5c$ESHaJQViO$91#J-q! zF1!C{v<6$#G4j}{dgLCDKEI~wyulzvd)=>2(p(Me@VhCh%I(?EtqX12GcQ!UF5b0t z%(z0p{M%_y?Kj+Qbu<|pE=<~T22Lz_C&PDM+y?&Z=>sc~wseGV7)RjjDy@J?r?y?1 zmWLAx(mmZ*VV!T96m!kv#X>Z=*BgrFId_g*Yke*NZVhi|`0T!(vSapNfYs8Te|FEI zo*dTjweFGv0lU{(%L~Bx)M@RBd1w}@_Y~D{^HR9BqHdz=llA zr232Kl~>nui8_I{djNQPM39iJet6DwvZ}b~G^+ZR zvuzd~J}Y-LX6kiugkdrYHCf4-fftRRem!*MjBa%k<){y%>FDXVH@#hzQ)-5;czRrV zUAZ<_(f4||PiI?)FsYQqbL{)}W;eaD6{voP4?>RbtE-Z(pcXcnCJSJkP!znq!wJ$>Ez za4B5(PJlpY=hSaKDcR1y>WRSc{{J!OZxRPK*jFb`xIx_`PoVi_&)1V~+B%DiBd%@} z>ao2zZANP^fP_siquTBWheu|~xwBb^xpsY>#R)-`Uz67Vkv$+cU^ig@@aFj};IaJ$ zzz?=Y)WxO`@qRY3K5PukAqpd)de29`Sx7+@D6BBJjr|rI=Q+o_{zhP%CDy9R=)C#` z@LGQ2&w$C!{(-^YRlNRr=p$&I?kcRbD&*sYhl1gPhQ{pH*e|;D?dUPXHWpazv)+gq zL;QM_jE;BJ4wQRG`Ow5KY+xR*f@q6?O_WBk`bLN+LoR@_vi)b~$-V2h_18`FEm>B_ z?^f)Djz3zgYw)lBv^=;U4A9?H?G%!!X}EI0#+HsHKb3by7DC2-)y~RTb z{l+j6*y6!=2apbVGG3yvjc#XS*UkKx$8HDd0#8kyzwkDWp&CtJeMsU7_OOb8K8 z549c{#|)2ARt!rat$>z#dIv?#zW+)!7*rM&HJ4?j0>?zwa_sn3wl? zZT=9iY9Jol-wK25P;mgvJkc5+UG>_h|I@xfaNCo=g4=%Iid1?26UX;SJ+aI!)8^4g zrazDC;4-}korlp~Mtt+FkMu}2Ff9C$XcZ-DC+kOCqQ?tBFs*4k#nrc2!Dnc!el_dh zLrWO~M5(O~!7)v{H#p$g5W|C=@SZP@f<^v&Fx9BTcq>_&$_??@GZ>gjH?{WCY~Ux( zog)of3NQz(o8-#vYfZ5HbG zjY!L8=3_mtBG#a5TyzP7iWWThWXF=)TSlJ75o1Cd>j7HD;Y+9^Dq@9@fa|9opne2I z-9LeXly~n>%f`@!Q*P{oId2w%ke>;Rrcxfp#_ETzXwGrmzr`lsu#tqEpYzD5Z| zCPbyrtt?JZPbB=Gi8%1(w|rX3Dej^jg)vA}M6%I)YxnCPsNDAiF>bpeBKrT#is1xW zj-L+U>_hKA;PwUsj}`h#D2LSeQ-JUpboaVj#wQ^`Uyk z@IZv3WO^3YlA(@ChH(_>@<7@TJ&5{^3Aeah>^KJ~@yg;sa2Co%C3;$QrjC0_;q8MU z7#$^aW}*UkkjVUnl`9_qg!2^G@Kw6E=AU?Yrm+J;<9V*3_RLCtT7G z&nZ3S>&&;`M;4UOhT8+g@81*7yz)Ktv(%Jx{)}E8np)v#L4k^k`kXV7e4455@P9%- zlOum?p>5mh;m2wE55ChwqZyqZeiwe5T8sIictkh-Ek~OI%rMV|LhjjTp*Y=Yb(dFz zdAvxmkjP4@#I1t8d8|kS+GUEw$Soc^$>8$lRG-M9e`W#|FOqlZo zdl_XVBz;YGXF#?J-u%0=cRRFTP{S|e4(O)d$cdwydVuT8ljS`n&0Xtpc!iSd ziH>~6+zPKSwUSFIb7+|gQ$xr%k*L^L%rX|ovdzCTHT?mUIS+(iDGXU7^07)oUGWO+ zbqsKu-;7ii5P#{0@aZ8rxvi(o5?MxI$a8*UnU$%a`4e+&f>ZWO&QIF%Y zR>!l0849e0p`sjiRmBX`Xo4&n1PHN&;Z(xVbybAZpi&1z_L_u7_JXWJzL>by-Q8b%ESRhl=K4{MUnOo9B%9NnUPiTJux>pEcN1pzx{YBg)#lT=#+Ff1)Acrh~`U z>_Q5z--4wfTEx>V$0}z$zJ)ksmW6j<$$W0d{hnX_w90tPw%x|+XGO5=aw@bTJo%lGfOCX|Ey4F+p35@g9aOwZHmN2_60lt5y3 z%K}B1;&Mj``JdPek>lHqkIKBaxub{USqeb~bhpK!s$eV^@-q&lw&%ej^jUb;S6$2Y zvb#@e=6JA68xl0~?d2O~5yl@$5)jqnQNe($sgPT?#WM7lfA>44*;+L|oaUe9$VsVL zc;p89V0`I4{M&dizI0r>ws#Y8lHbmC#3M2x0mD3tpsD?{;isQ^xldJ?WC{kBOfC(b zF;KmtRv=Jz8%0m0tTObu&9RM2?RFfQXhb(h3&e$&(FcgQ_|W8&nKr?H%;jFbD_UJ8 z<(Fw)61DoK*(W3P3`D40R)p&zf);EAM=E4?f};qYm6JX+U0xeJ3e!*SclB0&C8X|M z59=+Ptkvp{AWoI}U3Cj7x%PX7;hlFK8N(e*rrM+((hV3JZ>>6}_$p?_>UD(r!}BT8 zWMpJi#NbG2wQG{Tm+iqY=x220UO^bH5`1Kz(T*};qT2{XV+<_-B=y6hCnee_Yb(=S znb*Fe68y`2`95W3IS!8Bb&tepZIPUD-bby<&X5lmjURV^5FmI~g<4*lo;-UxFY9Q0 zgS{R=3&Y~HXAGXef)z(Q*{u#19}7zGsVeOX^Gvlt`g|ezRVfxWf#5)S9%j&N0Z-_k z0r@(*g*r`G$WK4|x+c49w^k?$lqj$HCL&dl(R1z{$DJx@GIx0bNh$g1pWys3=-)kJ zmJ!2FA~0m^OK3>}VnpzEX{SWGTmo3l^3F||IfTCe?AU2xRIor8@Dw1z1X)>%#02k5 zNc%Afm8&3w(PfhP^7S7f4?7!%tYk4T62G81=kRe{NZ$c)>=OQTDqEQ-=dA3MLA))k zRw&pbQG5>ErY4Mc;5J3nYfO!PpP_6@gI;>c)K9?DGZl;6MF?KEsmaOu zTrA|~W->`wLm(ozj11ny_90&Ff8T|0-lyGzYmWjs{8PIkcT4$;od#e`ak)Qv(#C^*TCi|x>nA0n&mT=6`g@G-+(AmHKT zDFFxz?-?a?PhO?-P8fLp+|^YA)w>)zk|w*r}*}My*)Pu zuPs*Obcy*Ld?JYx(lWbZK>_IdoCkZL8`V?EM>%X#x4HojvJ;@ALzYsebp5jSH!$ie z!pR7H0&kI>O8=1NY-pfLA)+yONa5=V+^XaP{rul@fMXI17wBOwSd6w` z((STQUjj$&TT~A)m=4iZ3IjPzr5J%C|DmEvf-!|Z)KVjQ)800m8q9LHJpW&~cMC;Y zBE|>owKHlyv+H7?%yr6T%IBv$qakHF{&w5mNa&vuAZ~42O~R|1D?hHeo4NVCQF!kH zV^C5HEdFd5d8#O3Pw!!e#(^ftNYe=Ti+hQyZ!H#Z&Uz!S*cBIm@Cb7XGh}$n=Tt7P zGZ_iDS~|4X`jxevx9oNU7jou<}-tVtKOT68eXUQOo>O1g~|O!>v&I! zJR}UH4*@77UE65;F!I{;j4ML!H7uO_x*(%~LCa#Kz8%BH$U2*ZO)&EHhxm4a6`9g7 z=BbJN1{7zvYzL0fBX1ZXt4k6>vWXnT=fOq)=AZH#$E;(&078wXyMAimFVw~aj>6FE ze4;Sp;rM6~w7NT{2rV%6Zo_?{3EVAdr<}mNHt1PCj*oo!JW*l^?@5;rlt~#J0DQ4* zB7{S;ZMBq&QDSLDs<|Yz&UuvZKrzW-;Cm zZ4l6x?7dq#hI&YsYR?w%x{v98?S=~uYchZNGfvm5BLa)Q!N)i5MU*Mv_0D97^{nJ` z>UVPP6h_`=%DjX@A70Ao9n|lhR8GTXsH9#)>oNm7smmz*Zd6OsP(UWKSVDC!C3>G_ z4$~wHPwzug4J{0hGXb)m(#3`ofRU(S1% z=Km!f|dcAEz&(C5~5|s**fi8Xzo}%|#3aw<=Y2az0 zaplPo9YnIMPZNTexeA^aa?rNns{dV!-z4 zL|m*lvS)$$Jgmn*F4!)C8X|~{4Eya&e5^n2rX2*GN&Bfx(%QntIaTWEE@sQw5~cfE zRT6Fls8ucKJ9phrk1eFJR};X0>&Rhi`qcdC)0p4_!yrpgs#eJ(*1e-jl^ zl_Ly(4GnH_tbLx0GW}@1@Di-K!I<&%KbZ0QznJkDW7^chf>Qvo7ISKi%``zMVP6Hu zvM(1YiEHx@xWPHNnNRX#2JEFNp<1qR8WF9%tgb}8#y{=tI9PteM!;T45@1D61f;VV zOCK0Acma@SJ9kOv0 zIEMxY0?hYRwp0Q0J-;^+DQrDYoqhXF17>zpnOPG)W=8%K{i<*{J@@YZp8o<6P|$x{ zeOngs2tDyI=>ZP<<+^3HGHddYfw2N@4sR+jx8CWe*rS$5w5$rIGu)5%sHUl=l)l>I#fG4EK-ae~Aj@C~@2oMPiosZq)zkIS+VC$~*sLxjz5 zYev82|2;`mjHJiPw=iJIPEU@-A#IupJYJ|;j6(kvz#yQ%0TXXTUH~1L?wvR{qL1rS z9BdZ%#eGlxHhH*UOwK{ZDkV(=g3yqrg84#PXyYO~M<9CSbjeYjy zQ}V?LMMlv>7hhrXP;`uqK05J_R4e_(4o#EW98ioY2biaM98#8*$S->XCUm0cXDa-~ zobjWuhO5b+ZVmQ21*q&;&-vR|FG4L3t3G{rn)erC++H^te`;`UpfqQ7=y#evmSdD( zw{Bdn2)=PI+4`V?3R8+J4^DgmQ={D~Bu0qlIrTJlwJd^U!!~gcyXv*&2yw#iQla;x zh*IpIDRNUh{z+m$ui9J0d}^k|Z>4EWEhTxMmyoR+DEB_ji>Aq|Sy0x~aj^KPgq{DZ zsGa&3EN9@bJa=SG2oDfUnYZZFUtA|S;HS0*<~ZWRXzC=}RX5}vxuWW0#}5FY!Pz0v z;8Z6xV%{6RZ3%|sx&Y~Gy^)p#*GV$D^79?v52i1JPLv&QpoGV^tqpyzO-*3~(R0!c!IaFr<4 zI8w9>7P!Sxhp;2m&$$NsKHi#%xL*Sc(Z$VUzW;=3sz_+KRgIz-Wf}uhkH$FWh$=%N z%P;1cY#!M$dL7$l`D_wSSuaW8$5WA01n-(qqz;ZNv9Y_#zI-b4E-q&MT9(nSkI6Iy zvXa%7%48lc2B3uu##3OINcl3ckGtXi5NDnhqCO!XOS~7ZTQlfOO!9O;flotTDPfsP zKyT6Sxl{J}DCWuZ0w`7UY{?gsV1FF}!z5N^Q3$yhn+s-X@+n^&$|q650>vHChN1OrB%Q?MP0*&*Hs3f1Anw zpi?9MPO>@V+|nmzk0UASH%LH|9_yvlS0pJbCUh$4+k4Sa+3Bf&OcnCR6+u-!U8l#s zk~}ZW|GrtX-<}0)^RsHBfyT@;$Mm!+6CJnu!E`|}qhk+hJ4f6BMpik&0W_;$y#V~(F9V!A7Z10OmLxg`3;amrnjQzvBd`K<*r^@oz6t02=;IPKimQDp(Ab$tpHwd5a*uB@nkOcoXj3lwpe~?u} z{6BF}5NRVtSrSGYIjtBEaPD)|8$4x21YqhC@yz4GN5$>89a-OVvr(zkbGeeLXn-=P zRqxeN8A+<9dllB2nY5$1vTbTgP}W;$J>x0dWHSpM($BtxF=;@~O^wty`~GBNCnfgG zeXJgy3_#}I0e0_p45KpCRw59ddV0KB8lv<5P*^qxQtWFQZt>uh7WdLj#hluO9)c*B zasiwIzW5FZjl^c|Qo#;*jA_n#ffkLYOm0KIoL0=C55Q~+SwiqmhFL5NMfs!N+bWLoJFtdcalCxpG$mByr(kpjn8aeq@aHYomO zs{Mhru;gow6-p_)%t0z8rLwx}%8+mn?}1$x>IO63^;{hEcE?`A*afq?m9)y6y(+=b zWa#OtkUgX(mU}t}qYJx=Mf?ADCNr6j>0-YQO&oQFwiJ%Qg4o>+am)Mq?`40Y|50!H zqAMp<^fT5AX+^b)VZJ2rb+LKdDTSsF2Y6}Z$tdN*iK*xw4UOUeE#rHV#l-!Gq%5f3e{u}y|_@Q2aP z>^Kn>G-pVlKF#?kBk?t4Bewt#Ta%rf9Aoc5m1YNa%cOFNckln6E=p z0Bgp`liCP6vKR=WUpbM%QqG^jIgw4oHPUw6U@XTzZyNDZjqW5>TFcO}9*mjUaKSmj zy*=v^m~dI~stXW-1uN+TS18}#U}dn8qXxOA`A*5?XVhVILcz79KsH%ocOg#2#Y?%2 z+`*wf$Z1&I0Ra-?AIIgKxs0MJAN!Tnj_Mg!jBF&qrU|a;CeL?W39vB`{?`~t-AXdD z@Cv-flF!8`d1oe5(vN1^7Y>IUm|c1hw65bx9ir|q$&ofRSgTr4Ks{9e_?$TVidWF1 zc*%`nah3eT{2k<{ztSjru+d8E>&$?!*>~=TM>_s{Pua7TLepuM3=7FyLQcqAZ%GR%91Ee27?e6d4k45=ddnH&pelS-Rc@iel^Fsb#?wJ>cT-yteh z{7V?1Ef^om9J@6MNFfWt1$$t=W3+WhAq38Om{bO{dlX<24)lLd1P*f~>ZR8N$>Y*0 zlZtGk^tn@ab(UelsW}ItBDU{cJ-OHFZT(=nyDx=j_}9)1?}n?pm`VYNl8H>Ca4v z;ZZR*`4GRZvE+Wl%U}J9apcGS_|k9Od*}Oa28&+<2ufnM(!D`m4!t}~xxr)VsFFpt za1@*b?cETDI{rHex@9rLluG+6I5~EI1Q~+{$qKgjM0cOBqqI39qtEznsP(JNaYUPf z^GVCFYzm$3uXK1vcq9?IsNVbZbc{I@nX~I++124ymppN{T?&mQglg+t6VgaAeM91z zm4&SGzuE8@PB!#hGmW}4^%Bdh43r^!poV21;a-MEF0m67a^>U0S&e z5&i)snU}Ne6;2l$W=hL|%1Obfb)wF|3|&mTB);}8&WAqc*S0>_#VCae5y&+1EP>eS zh#|C!jK4DFwLHHznb$YX5fLwClWxi&*wj=%gLiVdc+zR@IS%B1kO2CdC6%}E`#TVX z&HxgW0@%OUu-u_Wsdscs2pp=YZ?h>M#=08OP1pW%UPc5j2O}NuOQ$Fa3ouNQaNB*J zBI>QukLM9DPjp4iL$XyZ0$9F*p>?I0v0<;ba`VSE z+8M5`yYY=?;?E86%mJ&bc`ntFvr}5__x^cTNGrv7q$=09$f}gK?Js7r?Zu zu8z-+Wu_u2y-Ww_JIl|f<*2qWDXZ~#>f+qnMkE#MoZcv;bJ?hUg;IA^1cb5i+R3!b z!8d0A`2A!K(f8&HPiLEm&}?}xfJ%kFE?s$+fT*mSV}m(Xf{J)a8hTx{B*hQVetW6zGU#w)5#w=0z%@z^_?!e0fYIfp3t0xjW~)0J=ec$e9=uP3?T zQw(d>FnrUvg4EI%5|%jr+@zCDyM$w@X&k4QT)e9A%9P$vLM)~ig7}7X*+D+FtnFWZ zxLMl7IgUn;n+l(FvHOXM()v2$9r-=hHY=L^fiU-_^NDlUiX{mBf5?q`9%`Oc8tFKq zf|uxT70)N`lde~jtJmRYEQK9*Q#A-n+yvvs6N7lY)~+4=r#I7%33~}k%X1w%EGd6Z zgegOFN6_FXK0t$-sn3)3VvKbZN}PBdW@U7Ccx6;fcnBd)5uYk0FOv2D5#1fn_*#GL z@eRr%`e9gGQAJNzn)!|&H4-Vk}?ag+oH19FLKbWv4H-98fIb4#H z=$UQ#p|8iY;ZuU}aY1;VOr%S6_d70ab~iN`euc}#cml~kFJ}doqEo|8HM={#sPR0c zD=G^XqU*tqZG@AHSsJt3;cKpPvy>Umee2YqDEe8E(2Qo!$5j3~n%0=+&{RUOSI*hJ zq1DMs-U18>eJxS%YDtxK6mq%;l2Y;LuJPfaeGpA~A#ECGOK{vpKdGd4bzr6i8-O8h zc=M#Q6XxwFNw~EK2eGjQhf>v!!{!3}+MkIk;!j^c+8esIrv~XF{ec^~_uF-xX=s;U zN>zm+vD_-^6R~;dyX_JtI%6r+(6{n|4L1_t5XJ+oe3N;5w2@TH?;b_fnwrRc8|xyR zHh-gUnFZZ>j!7tUZ@AaP<#P|wV?L<5&Z-c^`^#@F!B2BWVhs!idNxwqwmdYD10U&J z71^P;nB*~NiYyeIe6$QKc*-qbXQCIrIlfxI8W}P*+;=lEi`&Q}FtfWHm9v02S!N4@TPDcrCKLQE`zf;@2{>4m`&+kS);jyRd(dlt%FGw5P2{lW~0 zr0FuS#+0XbRs@vB3QWs*-TkVa&KkfwWdfJ&COzu(ynjU<`ir$I`EGaH1Z!8=<3dinEEC+omrLE8_F_vAKg}ubD)#9JPz)AE{V0iG0HTC_UwqOyi{ zXubxMb%8%SNSc+Nqu45k=!*o0EbK7&v3=R?(<&?Vj=OT5`Ab|&gb zzVX#A#FA-e!;g;0Cv8eCB(CQY)Z)$@2t1y+hxi4hNsRSxUrc`x$r%~cX#+U2Q6A?&h^hP z6C!=6AwlqPhThEYJaW|02`NF(Bo@p+?VyEolSrJj|zdGWr> z(41PtcW^pxGC1J-QS+GfOvkW`@kDD`=lFE{jz;6hWAN@t-XQpS;WhRWnlAIN9E1ej z`3A3Km9-FE$|Wz>HFr zszWfN6fjHxqtrH(i4qv49zM}5Zvm{J9_qJO2!a1^V>grNsnD#IZz921n9n8;lPQkO zO9<^d6e7QTVDl4Qj7ayIN{ozZbZ+r>6*^(uBCG+KRSZm@^;3pM{V|xEMk1U|AC7uL z6o}R^$JPw9Ak%zVEkjDasdzrT<5u8f!Z>WQEO|29rf{XniU#=D8xYL}DtfV)#S&l3 zRqi@Ifr!Y=R7X^f9OiFW!BiqvIj?wP_$#d&b_%tHMwi}oP2W|R!K}pE`!gCO z-0X%r%QviV)q5=L0g!?bGlg&K6Ym4*-MsWE%upz>(F^9&ebVu=qHP6PP+EdDF0K&X zWn4WV&XVC~#Ri)8f~3SivhFFcnM5;*f&j4I<4^W~;PC6}bkR>_MoZ4}xku_hbGrGg z)*jTbRxC{MCi~lPR4|rw7j3KXx~ILpA@-O{_Ktt=NXfEPRDx;wme1z7OU9)GsvCKj z;*7W>N8D1Vt?L|4qc$E)+r7y{I=YlK%nt_lBwrL%v^Chz&<6WTHai|Gud$iX5<9-8 z^Smie`w)MRk-G9vn%tMSO}j9wU~c@ z`eLaWo!beb^sBe2w{;mvPc@EVQF@~S17;AV|2FB!BZ`9C z^iVg!RMa|E)_ss5ICQ#RwNP;}63P6BIRkZsXIR(GPg3Oq;~(SUb3b=;cub;;>QFrY ztcNtI*qkp*x;@=0V;E|$mUVZvZ^Xt{d|kQ%_#CQE=hyJ)-S1Zj2n8FP{bEul2y5q} zA~1sIezQCJK;DH^&QdzZI+D;ATaun;D0e`DitP;v*z&VWm$=9O*6CnPdLfJJ_yFTDC&Y7?4=RUPn0425tpoK(70u z;sGPqz0-FAQ1yPxZILyHN zA>laD{>4Yph$-AHT804h7{5{<;{kOc%7HMr-<}U1^(GZ)N{!u(qsrH*#7EC!)@%3I ze;-z@cN(W0vIixHOIF2{>^8YHcS%)W@&qWF-Dqy(Qe@h^)HM!Zt=lLVdEE4~=cQ?D zpi1R>?m}%y9T~2_Gkns_-B&`=qxWQbdCCE)A?@vJ7^&fof7|)<=m|&-*UzIbMBzn5 zVRSSL>o2#NjX!WN>ikz!5Dn7=6Zt67lT1Z{@IX}e;xcH=mm#?!DH)++Xf!{gEhLOh zK85)-J>3h{lG83Lkwxx>RBuK-1>@cKna`eiDc{B-lqbLoNlELv%fe&ct;F#(jnqi~ zr-wWkO@G(YrfGn$5{(BA+b`?kmNl`b6^ZdSLpCL>Ol_!>Ed z)z#~V5nE&>@%{zc91^|Z&0B*nb#n$58|U6RhvO>mRrS?+ro~v@{=~=TQPrFdC>CbU zVWP{@&SRSn$4%9ERP^d?15yvk>HTlDk$BXK{@ATN!f<#b=da&Z8YS64UP6c6b-N($ zy<))NGUMX*T?%keCy_mLcX7w~%#ytKp1;lEfW2Y`&=f){O<**IkC-r;!eD$ijHYlH zlYFy;e`(_~VM5Hz*1~?Nn=4dY=;jGQc(%-`63mK12sE~El*`=Zq{XV*xw?rTsNpq? zS;y%@GEwh^rQt^*=xxuHjcCGG^Q)#xi6{Bnsmm)E`jUuYdUEobxgNCf-SSA=S4_V0 z?7$9Xml`C`-&w3f(%G`+#)h@q&tq8`i`wpPnf9GYIfXxP1{EdSCzHd6)fL)QDv_#3 z*yW``=LTR}9qk2~IB(SQP&C5xtG2`6Y@F@(c;#)&lb7F!5NA)FRvizM%~ABiXJ2Us z_qP52B7ReoMMvi;=62>i_5S>v*|13wMWX84LZ~$)#$CcXZYfU7M=_{QUo|tO0PhCD z!-uL~G0$23ZZOKD8sWpSHH9EQENH!4!0-+#PT0;8_tW^UB?bD7uPMCXv_2!6=zbXY z2d)gv*jbOtEcQ1N!R*K95(x=iBjUW;L0>x`eYRWV_{#haN9BpEpC=9Wo#ectJ0L3CpB9n!`>^Bi)w?#+`c~XJUF}&B z7WB;1v=8(_43R8>gNEQA%R3hI)}M7%by#*x zUR$uCn50c|!!+kLCrj1F8#+vgj4H$0a^Ge6IquJYbdt^If!NYYZu@^h(6eWkM9jfX zMi1OcXyK-J?|ee{K2tmpJ|Z&XD-ND@HAc@ONS_W)mH&u~olr2_<@zSeLZTdFUiJ`G zWe#<&NGS_%0?vtxVpd|DbHalU&vvsqB>WmN1rTq4-~i(-+rG)4j-i-!u`lK1^mgaY z+gXJihQ}T=_2b3A6x_7;sH%BiNig-iG+W4VJ{CiQe{XFIESAanCOy&2T>Vya=(Ehn zO57Wpk(dJnz)~Jw53`i-pIge4uPx;{!%oh_KEg$%MoJ@%GH=S1N!E^h+V#w(7aC;) z7Ue04AM)cU>ks*D__x}1IS|#W?gELe((lKM0dQ^Omr9-qF<9C9l397(bfX+RBlrTT*N zvteE-g0I%VD;3IV{uOwo=KrQj5OX>mV838HJ|Y19R~mP2(ODclFNxr}5)Dcw6PICyCzqMgW%;;?4i%ig zI?-y^fT;A@2tdbRTg|;vPx@Y6uQl9#4)@g0GWSVu1#r(zUxiT)7~B&(kNQx>^9Bs= zNnR%WXwELlA*QvvWPUhRi5wyZ@vaWZltPDe_hi@-MY9Hf*F53ykq@7=FAje&5Z8RwxA1m20nA8xt3iB?0EA@&0-LSCP z%Xbs5_77Y^t!y&wx)27N+h%~>c&oD;U@JY?6%u6Yma?;l;uR|O=>_w#zkJrV_=8??k~S@<@nSNVLpovR3h5v(N|>-3QB5P%)2ai zb4}#p&2{V(B_if2Borw`5C?>izMzl?-V1bHF;OUCiR4I8Thau6_xdB*yY@9Y(tx#e zet#xVx2hk_SeGY%KqTSaSa?=e

#ZGat+(A-~nUY}Y&7cI&fx^W~Z-RDm$FkRzSJ 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

5hGX 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 z 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 literal 0 HcmV?d00001 diff --git a/tasks/all/example/data/test_mpi.txt b/tasks/all/example/data/test_mpi.txt deleted file mode 100644 index 8bc658371..000000000 --- a/tasks/all/example/data/test_mpi.txt +++ /dev/null @@ -1 +0,0 @@ -120 \ No newline at end of file diff --git a/tasks/all/example/data/test_omp.txt b/tasks/all/example/data/test_omp.txt deleted file mode 100644 index 7813681f5..000000000 --- a/tasks/all/example/data/test_omp.txt +++ /dev/null @@ -1 +0,0 @@ -5 \ No newline at end of file diff --git a/tasks/all/example/data/test_seq.txt b/tasks/all/example/data/test_seq.txt deleted file mode 100644 index 105d7d9ad..000000000 --- a/tasks/all/example/data/test_seq.txt +++ /dev/null @@ -1 +0,0 @@ -100 \ No newline at end of file diff --git a/tasks/all/example/data/test_stl.txt b/tasks/all/example/data/test_stl.txt deleted file mode 100644 index 3f10ffe7a..000000000 --- a/tasks/all/example/data/test_stl.txt +++ /dev/null @@ -1 +0,0 @@ -15 \ No newline at end of file diff --git a/tasks/all/example/data/test_tbb.txt b/tasks/all/example/data/test_tbb.txt deleted file mode 100644 index 7813681f5..000000000 --- a/tasks/all/example/data/test_tbb.txt +++ /dev/null @@ -1 +0,0 @@ -5 \ No newline at end of file diff --git a/tasks/all/example/func_tests/func_mpi.cpp b/tasks/all/example/func_tests/func_mpi.cpp index 1dbc5c5f6..5f07bdb55 100644 --- a/tasks/all/example/func_tests/func_mpi.cpp +++ b/tasks/all/example/func_tests/func_mpi.cpp @@ -1,8 +1,7 @@ #include #include -#include -#include +#include #include #include @@ -248,14 +247,10 @@ TEST(Parallel_Operations_MPI, Test_Max_2_File) { auto task_data_par = std::make_shared(); if (world.rank() == 0) { - std::string line; - std::ifstream test_file(ppc::core::GetAbsolutePath("all/example/data/test_mpi.txt")); - if (test_file.is_open()) { - getline(test_file, line); - } - test_file.close(); - - const int count_size_vector = std::stoi(line); + cv::Mat img = cv::imread(ppc::core::GetAbsolutePath("all/example/data/pic_mpi.jpg")); + EXPECT_EQ(img.rows, img.cols); + const int count_size_vector = img.rows + img.cols; + global_vec = GetRandomVector(count_size_vector); task_data_par->inputs.emplace_back(reinterpret_cast(global_vec.data())); task_data_par->inputs_count.emplace_back(global_vec.size()); diff --git a/tasks/all/example/func_tests/func_omp.cpp b/tasks/all/example/func_tests/func_omp.cpp index 3e590a619..f2e5d1090 100644 --- a/tasks/all/example/func_tests/func_omp.cpp +++ b/tasks/all/example/func_tests/func_omp.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include #include @@ -210,14 +210,11 @@ TEST(Parallel_Operations_OpenMP, Test_Mult_2) { } TEST(Parallel_Operations_OpenMP, Test_Mult_2_File) { - std::string line; - std::ifstream test_file(ppc::core::GetAbsolutePath("all/example/data/test_omp.txt")); - if (test_file.is_open()) { - getline(test_file, line); - } - test_file.close(); + cv::Mat img = cv::imread(ppc::core::GetAbsolutePath("all/example/data/pic_omp.jpg")); + EXPECT_EQ(static_cast(sqrt(img.rows) * sqrt(img.rows)), img.cols); + const int count_size_vector = img.rows + img.cols; + std::vector vec = GetRandomVector(count_size_vector); - std::vector vec = GetRandomVector(std::stoi(line)); // Create data std::vector ref_res(1, 0); diff --git a/tasks/all/example/func_tests/func_seq.cpp b/tasks/all/example/func_tests/func_seq.cpp index cda2304e9..823fd3dc3 100644 --- a/tasks/all/example/func_tests/func_seq.cpp +++ b/tasks/all/example/func_tests/func_seq.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include #include "seq/example/include/ops_seq.hpp" @@ -121,14 +121,9 @@ TEST(Sequential, Test_Sum_100) { } TEST(Sequential, Test_Sum_100_From_File) { - std::string line; - std::ifstream test_file(ppc::core::GetAbsolutePath("all/example/data/test_seq.txt")); - if (test_file.is_open()) { - getline(test_file, line); - } - test_file.close(); - - const int count = std::stoi(line); + cv::Mat img = cv::imread(ppc::core::GetAbsolutePath("all/example/data/pic_seq.jpg")); + EXPECT_EQ(img.rows, img.cols); + const int count = img.rows + img.cols; // Create data std::vector in(1, count); diff --git a/tasks/all/example/func_tests/func_stl.cpp b/tasks/all/example/func_tests/func_stl.cpp index 1a3ade05c..372283baa 100644 --- a/tasks/all/example/func_tests/func_stl.cpp +++ b/tasks/all/example/func_tests/func_stl.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include #include #include @@ -215,14 +215,11 @@ TEST(Parallel_Operations_STL_Threads, Test_Diff_2) { } TEST(Parallel_Operations_STL_Threads, Test_Diff_2_File) { - std::string line; - std::ifstream test_file(ppc::core::GetAbsolutePath("all/example/data/test_stl.txt")); - if (test_file.is_open()) { - getline(test_file, line); - } - test_file.close(); + cv::Mat img = cv::imread(ppc::core::GetAbsolutePath("all/example/data/pic_stl.jpg")); + EXPECT_EQ(static_cast(sqrt(img.cols / 2) * sqrt(img.cols / 2)), img.rows); + const int count_size_vector = static_cast(sqrt(sqrt(img.rows))); - auto nthreads = std::thread::hardware_concurrency() * std::stoi(line); + auto nthreads = std::thread::hardware_concurrency() * count_size_vector; std::vector vec = GetRandomVector(static_cast(nthreads)); // Create data std::vector ref_res(1, 0); diff --git a/tasks/all/example/func_tests/func_tbb.cpp b/tasks/all/example/func_tests/func_tbb.cpp index eeb5e3c50..63070eb30 100644 --- a/tasks/all/example/func_tests/func_tbb.cpp +++ b/tasks/all/example/func_tests/func_tbb.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include #include @@ -209,14 +209,11 @@ TEST(Parallel_Operations_TBB, Test_Mult_2) { } TEST(Parallel_Operations_TBB, Test_Mult_2_File) { - std::string line; - std::ifstream test_file(ppc::core::GetAbsolutePath("all/example/data/test_tbb.txt")); - if (test_file.is_open()) { - getline(test_file, line); - } - test_file.close(); + cv::Mat img = cv::imread(ppc::core::GetAbsolutePath("all/example/data/pic_tbb.jpg")); + EXPECT_EQ(static_cast(sqrt(img.rows / 2) * sqrt(img.rows / 2)), img.cols); + const int count_size_vector = img.rows + img.cols; - std::vector vec = GetRandomVector(std::stoi(line)); + std::vector vec = GetRandomVector(count_size_vector); // Create data std::vector ref_res(1, 0); From 1130bd6b990bd6198c4f1283a76d02a29fdd51f3 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Thu, 16 Jan 2025 21:50:41 +0100 Subject: [PATCH 6/9] fix linker --- .github/workflows/main.yml | 16 ++++++++-------- cmake/configure.cmake | 7 +++++++ cmake/opencv.cmake | 2 +- tasks/CMakeLists.txt | 3 +-- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9ef1d343a..eeca7d5d1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -43,7 +43,7 @@ jobs: sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install gcc-13 g++-13 - sudo apt-get install ninja-build + sudo apt-get install ninja-build mold sudo apt-get install mpich sudo apt-get install libomp-dev sudo apt-get install valgrind @@ -56,7 +56,7 @@ jobs: - name: CMake configure run: > cmake -S . -B build - -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache + -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -DENABLE_MOLD=ON -G Ninja -D USE_SEQ=ON -D USE_MPI=ON -D USE_OMP=ON -D USE_TBB=ON -D USE_STL=ON -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -D CMAKE_BUILD_TYPE=RELEASE @@ -122,7 +122,7 @@ jobs: sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install gcc-13 g++-13 - sudo apt-get install ninja-build + sudo apt-get install ninja-build mold sudo apt-get install mpich sudo apt-get install libomp-dev sudo apt-get install valgrind @@ -135,7 +135,7 @@ jobs: - name: CMake configure run: > cmake -S . -B build - -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache + -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -DENABLE_MOLD=ON -G Ninja -D USE_SEQ=ON -D USE_MPI=ON -D USE_OMP=ON -D USE_TBB=ON -D USE_STL=ON -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -D CMAKE_BUILD_TYPE=RELEASE @@ -887,7 +887,7 @@ jobs: run: | sudo apt-get update sudo apt-get install gcc g++ - sudo apt-get install ninja-build + sudo apt-get install ninja-build mold sudo apt-get install mpich sudo apt-get install libomp-dev sudo apt-get install valgrind @@ -896,7 +896,7 @@ jobs: run: > cmake -S . -B build -G Ninja -D USE_SEQ=ON -D USE_MPI=ON -D USE_OMP=ON -D USE_TBB=ON -D USE_STL=ON - -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON + -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -DENABLE_MOLD=ON -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_VERBOSE_MAKEFILE=ON -D USE_COVERAGE=ON @@ -962,7 +962,7 @@ jobs: sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install gcc-12 g++-12 - sudo apt-get install ninja-build + sudo apt-get install ninja-build mold sudo apt-get install mpich sudo apt-get install libomp-dev sudo apt-get install valgrind @@ -975,7 +975,7 @@ jobs: - name: CMake configure run: > cmake -S . -B build - -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache + -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -DENABLE_MOLD=ON -G Ninja -D USE_SEQ=ON -D USE_MPI=ON -D USE_OMP=ON -D USE_TBB=ON -D USE_STL=ON -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -D CMAKE_BUILD_TYPE=RELEASE diff --git a/cmake/configure.cmake b/cmake/configure.cmake index 3810aa05a..cc40e83de 100644 --- a/cmake/configure.cmake +++ b/cmake/configure.cmake @@ -49,6 +49,13 @@ endif( MSVC ) add_compile_definitions(PPC_PATH_TO_PROJECT="${CMAKE_CURRENT_SOURCE_DIR}") +option(ENABLE_MOLD OFF) +if (ENABLE_MOLD) + set(CMAKE_LINKER mold) + set(CMAKE_EXE_LINKER_FLAGS "-fuse-ld=mold ${CMAKE_EXE_LINKER_FLAGS}") + set(CMAKE_SHARED_LINKER_FLAGS "-fuse-ld=mold ${CMAKE_SHARED_LINKER_FLAGS}") +endif() + MACRO(SUBDIRLIST result curdir) FILE(GLOB children RELATIVE ${curdir} ${curdir}/*) SET(dirlist "") diff --git a/cmake/opencv.cmake b/cmake/opencv.cmake index 84c87d01c..bac0b6fe5 100644 --- a/cmake/opencv.cmake +++ b/cmake/opencv.cmake @@ -10,6 +10,6 @@ ExternalProject_Add(ppc_opencv -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -G${CMAKE_GENERATOR} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -D CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} -D CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} -DCMAKE_CXX_FLAGS="-w" -DCMAKE_C_FLAGS="-w" -DENABLE_CCACHE=ON -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_DOCS=OFF -DWITH_CUDA=OFF -DWITH_OPENCL=OFF -DBUILD_opencv_calib3d=OFF -DBUILD_opencv_dnn=OFF -DBUILD_opencv_ml=OFF -DBUILD_opencv_objdetect=OFF - -DBUILD_opencv_video=OFF -DBUILD_opencv_world=OFF -DBUILD_opencv_features2d=OFF -DBUILD_opencv_flann=OFF -DBUILD_opencv_photo=OFF + -DBUILD_opencv_java=OFF -DBUILD_opencv_gapi=OFF -DBUILD_opencv_video=OFF -DBUILD_opencv_world=OFF -DBUILD_opencv_features2d=OFF -DBUILD_opencv_flann=OFF -DBUILD_opencv_photo=OFF BUILD_COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" --config ${CMAKE_BUILD_TYPE} --parallel INSTALL_COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" --prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/install") diff --git a/tasks/CMakeLists.txt b/tasks/CMakeLists.txt index 5cf8ac6a5..9a3571182 100644 --- a/tasks/CMakeLists.txt +++ b/tasks/CMakeLists.txt @@ -141,8 +141,7 @@ foreach(TASK_TYPE ${LIST_OF_TASKS}) target_include_directories(${EXEC_FUNC} PUBLIC "${CMAKE_BINARY_DIR}/ppc_opencv/install/include/opencv4") target_link_directories(${EXEC_FUNC} PUBLIC "${CMAKE_BINARY_DIR}/ppc_opencv/install/lib") if(NOT MSVC) - target_link_libraries(${EXEC_FUNC} PUBLIC - opencv_core opencv_highgui opencv_imgcodecs opencv_imgproc opencv_videoio) + target_link_libraries(${EXEC_FUNC} PUBLIC opencv_core opencv_highgui opencv_imgcodecs opencv_imgproc opencv_videoio) endif() add_dependencies(${EXEC_FUNC} ppc_googletest) From eb2da2f9bf177fc6a5abae61063aa835ef5efba3 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Fri, 17 Jan 2025 02:12:03 +0100 Subject: [PATCH 7/9] big changes --- .github/labeler.yml | 1 - .github/workflows/main.yml | 58 ++++++++++--------- 1stsamples/CMakeLists.txt | 7 --- 1stsamples/mpi/CMakeLists.txt | 17 ------ 1stsamples/mpi/main.cpp | 25 --------- 1stsamples/mpi_boost/CMakeLists.txt | 22 -------- 1stsamples/mpi_boost/main.cpp | 19 ------- 1stsamples/omp/CMakeLists.txt | 8 --- 1stsamples/omp/main.cpp | 12 ---- 1stsamples/stl/CMakeLists.txt | 8 --- 1stsamples/stl/main.cpp | 23 -------- 1stsamples/tbb/CMakeLists.txt | 12 ---- 1stsamples/tbb/main.cpp | 20 ------- CMakeLists.txt | 86 +++++++---------------------- cmake/configure.cmake | 29 +++------- cmake/modes.cmake | 24 ++++++++ cmake/mpi.cmake | 9 +++ cmake/onetbb.cmake | 57 ++++++++++--------- cmake/opencv.cmake | 4 +- cmake/openmp.cmake | 22 ++++++++ cmake/sanitizers.cmake | 1 + cmake/threads.cmake | 4 ++ 22 files changed, 153 insertions(+), 315 deletions(-) delete mode 100644 1stsamples/CMakeLists.txt delete mode 100644 1stsamples/mpi/CMakeLists.txt delete mode 100644 1stsamples/mpi/main.cpp delete mode 100644 1stsamples/mpi_boost/CMakeLists.txt delete mode 100644 1stsamples/mpi_boost/main.cpp delete mode 100644 1stsamples/omp/CMakeLists.txt delete mode 100644 1stsamples/omp/main.cpp delete mode 100644 1stsamples/stl/CMakeLists.txt delete mode 100644 1stsamples/stl/main.cpp delete mode 100644 1stsamples/tbb/CMakeLists.txt delete mode 100644 1stsamples/tbb/main.cpp create mode 100644 cmake/modes.cmake create mode 100644 cmake/mpi.cmake create mode 100644 cmake/openmp.cmake create mode 100644 cmake/threads.cmake diff --git a/.github/labeler.yml b/.github/labeler.yml index 1fb12bf6b..cfee42ee1 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -16,7 +16,6 @@ ci: core: - "modules/core/**" samples: - - "1stsamples/**" - "modules/ref/**" 3rdparty: - "3rdparty/**" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index eeca7d5d1..1bc7ccbc3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -56,16 +56,17 @@ jobs: - name: CMake configure run: > cmake -S . -B build - -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -DENABLE_MOLD=ON + -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -D ENABLE_MOLD=ON -G Ninja -D USE_SEQ=ON -D USE_MPI=ON -D USE_OMP=ON -D USE_TBB=ON -D USE_STL=ON -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -D CMAKE_BUILD_TYPE=RELEASE env: CC: gcc-13 CXX: g++-13 - - name: Ninja build + - name: Build project run: | - cmake --build build + cmake --build build --parallel + source build/ppc_opencv/install/bin/setup_vars_opencv4.sh env: CC: gcc-13 CXX: g++-13 @@ -135,16 +136,17 @@ jobs: - name: CMake configure run: > cmake -S . -B build - -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -DENABLE_MOLD=ON + -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -D ENABLE_MOLD=ON -G Ninja -D USE_SEQ=ON -D USE_MPI=ON -D USE_OMP=ON -D USE_TBB=ON -D USE_STL=ON -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -D CMAKE_BUILD_TYPE=RELEASE env: CC: gcc-13 CXX: g++-13 - - name: Ninja build + - name: Build project run: | - cmake --build build + cmake --build build --parallel + source build/ppc_opencv/install/bin/setup_vars_opencv4.sh env: CC: gcc-13 CXX: g++-13 @@ -214,9 +216,9 @@ jobs: env: CC: clang-19 CXX: clang++-19 - - name: Ninja build + - name: Build project run: | - cmake --build build + cmake --build build --parallel env: CC: clang-19 CXX: clang++-19 @@ -293,9 +295,9 @@ jobs: env: CC: clang-19 CXX: clang++-19 - - name: Ninja build + - name: Build project run: | - cmake --build build + cmake --build build --parallel env: CC: clang-19 CXX: clang++-19 @@ -364,9 +366,9 @@ jobs: env: CC: clang-19 CXX: clang++-19 - - name: Ninja build + - name: Build project run: | - cmake --build build + cmake --build build --parallel env: CC: clang-19 CXX: clang++-19 @@ -430,9 +432,9 @@ jobs: env: CC: clang-19 CXX: clang++-19 - - name: Ninja build + - name: Build project run: | - cmake --build build + cmake --build build --parallel env: CC: clang-19 CXX: clang++-19 @@ -505,9 +507,9 @@ jobs: -G Ninja -D USE_SEQ=ON -D USE_MPI=ON -D USE_OMP=ON -D USE_TBB=ON -D USE_STL=ON -DCMAKE_C_FLAGS="-I$(brew --prefix)/opt/libomp/include" -DCMAKE_CXX_FLAGS="-I$(brew --prefix)/opt/libomp/include" -D CMAKE_BUILD_TYPE=RELEASE -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON - - name: Ninja build + - name: Build project run: | - cmake --build build + cmake --build build --parallel - name: Run func tests (MPI, num_proc=1) run: | source scripts/run_mpi.sh @@ -576,9 +578,9 @@ jobs: -G Ninja -D USE_SEQ=ON -D USE_MPI=ON -D USE_OMP=ON -D USE_TBB=ON -D USE_STL=ON -DCMAKE_C_FLAGS="-I$(brew --prefix)/opt/libomp/include" -DCMAKE_CXX_FLAGS="-I$(brew --prefix)/opt/libomp/include" -D CMAKE_BUILD_TYPE=RELEASE -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON - - name: Ninja build + - name: Build project run: | - cmake --build build + cmake --build build --parallel - name: Run tests (threads, num_threads=5) run: source scripts/run_threads.sh env: @@ -650,7 +652,7 @@ jobs: -D USE_SEQ=ON -D USE_MPI=ON -D USE_OMP=ON -D USE_TBB=ON -D USE_STL=ON -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -D CMAKE_BUILD_TYPE=RELEASE - - name: MSBuild + - name: Build project shell: bash run: | cmake --build build --config Release --parallel @@ -708,7 +710,7 @@ jobs: -D USE_SEQ=ON -D USE_MPI=ON -D USE_OMP=ON -D USE_TBB=ON -D USE_STL=ON -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -D CMAKE_BUILD_TYPE=RELEASE - - name: MSBuild + - name: Build project shell: bash run: | cmake --build build --config Release --parallel @@ -773,7 +775,7 @@ jobs: env: CC: clang-cl CXX: clang-cl - - name: Ninja build + - name: Build project run: | cmake --build build --config Release --parallel -v env: @@ -827,7 +829,7 @@ jobs: env: CC: clang-cl CXX: clang-cl - - name: Ninja build + - name: Build project run: | cmake --build build --config Release --parallel -v env: @@ -896,13 +898,14 @@ jobs: run: > cmake -S . -B build -G Ninja -D USE_SEQ=ON -D USE_MPI=ON -D USE_OMP=ON -D USE_TBB=ON -D USE_STL=ON - -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -DENABLE_MOLD=ON + -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -D ENABLE_MOLD=ON -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_VERBOSE_MAKEFILE=ON -D USE_COVERAGE=ON - - name: Ninja build + - name: Build project run: | cmake --build build --parallel + source build/ppc_opencv/install/bin/setup_vars_opencv4.sh - name: Run tests (MPI) run: | source scripts/run_mpi.sh @@ -975,16 +978,17 @@ jobs: - name: CMake configure run: > cmake -S . -B build - -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -DENABLE_MOLD=ON + -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -D ENABLE_MOLD=ON -G Ninja -D USE_SEQ=ON -D USE_MPI=ON -D USE_OMP=ON -D USE_TBB=ON -D USE_STL=ON -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -D CMAKE_BUILD_TYPE=RELEASE env: CC: gcc-12 CXX: g++-12 - - name: Ninja build + - name: Build project run: | - cmake --build build + cmake --build build --parallel + source build/ppc_opencv/install/bin/setup_vars_opencv4.sh env: CC: gcc-12 CXX: g++-12 diff --git a/1stsamples/CMakeLists.txt b/1stsamples/CMakeLists.txt deleted file mode 100644 index dda80e6c9..000000000 --- a/1stsamples/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -message(STATUS "First samples") - -SUBDIRLIST(subdirs ${CMAKE_CURRENT_SOURCE_DIR}) - -foreach(subd ${subdirs}) - add_subdirectory(${subd}) -endforeach() diff --git a/1stsamples/mpi/CMakeLists.txt b/1stsamples/mpi/CMakeLists.txt deleted file mode 100644 index ad0a0d998..000000000 --- a/1stsamples/mpi/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -get_filename_component(Project_ID ${CMAKE_CURRENT_SOURCE_DIR} NAME) -set(Project_ID "sample_${Project_ID}") -message( STATUS "-- " ${Project_ID} ) - -if(USE_MPI) - add_executable( ${Project_ID} main.cpp ) - - if(MPI_COMPILE_FLAGS) - set_target_properties( ${Project_ID} PROPERTIES COMPILE_FLAGS "${MPI_COMPILE_FLAGS}" ) - endif(MPI_COMPILE_FLAGS) - - if(MPI_LINK_FLAGS) - set_target_properties( ${Project_ID} PROPERTIES LINK_FLAGS "${MPI_LINK_FLAGS}" ) - endif(MPI_LINK_FLAGS) - - target_link_libraries(${Project_ID} ${MPI_LIBRARIES}) -endif() \ No newline at end of file diff --git a/1stsamples/mpi/main.cpp b/1stsamples/mpi/main.cpp deleted file mode 100644 index 638a2c005..000000000 --- a/1stsamples/mpi/main.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include - -#include - -int main(int argc, char** argv) { - MPI_Init(&argc, &argv); - - int world_size; - MPI_Comm_size(MPI_COMM_WORLD, &world_size); - - int world_rank; - MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); - - char processor_name[MPI_MAX_PROCESSOR_NAME]; - int len_chars; - MPI_Get_processor_name(processor_name, &len_chars); - - MPI_Barrier(MPI_COMM_WORLD); - std::cout << "Processor = " << processor_name << '\n'; - std::cout << "Rank = " << world_rank << '\n'; - std::cout << "Number of processors = " << world_size << '\n'; - - MPI_Finalize(); - return 0; -} \ No newline at end of file diff --git a/1stsamples/mpi_boost/CMakeLists.txt b/1stsamples/mpi_boost/CMakeLists.txt deleted file mode 100644 index a9ad9a4a9..000000000 --- a/1stsamples/mpi_boost/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -get_filename_component(Project_ID ${CMAKE_CURRENT_SOURCE_DIR} NAME) -set(Project_ID "sample_${Project_ID}") -message( STATUS "-- " ${Project_ID} ) - -if(USE_MPI) - add_executable( ${Project_ID} main.cpp ) - - if (MPI_COMPILE_FLAGS) - set_target_properties( ${Project_ID} PROPERTIES COMPILE_FLAGS "${MPI_COMPILE_FLAGS}" ) - endif (MPI_COMPILE_FLAGS) - - if (MPI_LINK_FLAGS) - set_target_properties( ${Project_ID} PROPERTIES LINK_FLAGS "${MPI_LINK_FLAGS}" ) - endif (MPI_LINK_FLAGS) - - target_link_libraries(${Project_ID} PUBLIC ${MPI_LIBRARIES}) - add_dependencies(${Project_ID} ppc_boost) - target_link_directories(${Project_ID} PUBLIC ${CMAKE_BINARY_DIR}/ppc_boost/install/lib) - if (NOT MSVC) - target_link_libraries(${Project_ID} PUBLIC boost_mpi) - endif () -endif() diff --git a/1stsamples/mpi_boost/main.cpp b/1stsamples/mpi_boost/main.cpp deleted file mode 100644 index 86a42f516..000000000 --- a/1stsamples/mpi_boost/main.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include - -#include -#include -#include -#include - -// https://www.boost.org/doc/libs/1_68_0/doc/html/mpi/tutorial.html -int main(int argc, char** argv) { - boost::mpi::environment env(argc, argv); - boost::mpi::communicator world; - - world.barrier(); - std::cout << "Processor = " << boost::mpi::environment::processor_name() << '\n'; - std::cout << "Rank = " << world.rank() << '\n'; - std::cout << "Number of processors = " << world.size() << '\n'; - - return 0; -} diff --git a/1stsamples/omp/CMakeLists.txt b/1stsamples/omp/CMakeLists.txt deleted file mode 100644 index 7cfc5320b..000000000 --- a/1stsamples/omp/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -get_filename_component(Project_ID ${CMAKE_CURRENT_SOURCE_DIR} NAME) -set(Project_ID "sample_${Project_ID}") -message( STATUS "-- " ${Project_ID} ) - -if(USE_OMP) - add_executable( ${Project_ID} main.cpp ) - target_link_libraries(${Project_ID} PUBLIC ${OpenMP_libomp_LIBRARY}) -endif() \ No newline at end of file diff --git a/1stsamples/omp/main.cpp b/1stsamples/omp/main.cpp deleted file mode 100644 index 7b44a37d3..000000000 --- a/1stsamples/omp/main.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include - -#include - -int main() { -#pragma omp parallel - { - std::cout << "Thread number = " << omp_get_thread_num() << '\n'; - std::cout << "Number of threads = " << omp_get_num_threads() << '\n'; - } - return 0; -} \ No newline at end of file diff --git a/1stsamples/stl/CMakeLists.txt b/1stsamples/stl/CMakeLists.txt deleted file mode 100644 index 342002f92..000000000 --- a/1stsamples/stl/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -get_filename_component(Project_ID ${CMAKE_CURRENT_SOURCE_DIR} NAME) -set(Project_ID "sample_${Project_ID}") -message( STATUS "-- " ${Project_ID} ) - -if(USE_STL) - add_executable(${Project_ID} main.cpp) - target_link_libraries(${Project_ID} PUBLIC Threads::Threads) -endif() \ No newline at end of file diff --git a/1stsamples/stl/main.cpp b/1stsamples/stl/main.cpp deleted file mode 100644 index f3a04339c..000000000 --- a/1stsamples/stl/main.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include -#include -#include - -namespace { -void Task(const std::string& msg) { std::cout << "thread number: " + msg << '\n'; } -} // namespace - -int main() { - const auto num_max_threads = std::thread::hardware_concurrency(); - std::cout << "Number of threads = " << num_max_threads << '\n'; - std::vector thr(num_max_threads); - - for (unsigned int i = 0; i < num_max_threads; ++i) { - thr[i] = std::thread(Task, std::to_string(i)); - } - - for (unsigned int i = 0; i < num_max_threads; ++i) { - thr[i].join(); - } - return 0; -} \ No newline at end of file diff --git a/1stsamples/tbb/CMakeLists.txt b/1stsamples/tbb/CMakeLists.txt deleted file mode 100644 index 61b98ff55..000000000 --- a/1stsamples/tbb/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -get_filename_component(Project_ID ${CMAKE_CURRENT_SOURCE_DIR} NAME) -set(Project_ID "sample_${Project_ID}") -message( STATUS "-- " ${Project_ID} ) - -if(USE_TBB) - add_executable( ${Project_ID} main.cpp ) - add_dependencies(${Project_ID} ppc_onetbb) - target_link_directories(${Project_ID} PUBLIC ${CMAKE_BINARY_DIR}/ppc_onetbb/install/lib) - if(NOT MSVC) - target_link_libraries(${Project_ID} PUBLIC tbb) - endif() -endif() \ No newline at end of file diff --git a/1stsamples/tbb/main.cpp b/1stsamples/tbb/main.cpp deleted file mode 100644 index d8058ea4b..000000000 --- a/1stsamples/tbb/main.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include - -#include - -namespace { -int FibFunc(int n) { - if (n < 2) { - return n; - } - int x; - int y; - oneapi::tbb::task_group g; - g.run([&] { x = FibFunc(n - 1); }); - g.run([&] { y = FibFunc(n - 2); }); - g.wait(); - return x + y; -} -} // namespace - -int main() { return FibFunc(10) - 55; } diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d567ab7a..16b5656dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,83 +1,39 @@ cmake_minimum_required( VERSION 3.25 ) +message( STATUS "Parallel Programming Course (PPC)" ) project(parallel_programming_course) -message( STATUS "Parallel Programming Course" ) -include(cmake/configure.cmake) -include(cmake/opencv.cmake) -include(cmake/gtest.cmake) +############################ Configures ############################# -option(ENABLE_ADDRESS_SANITIZER OFF) +message( STATUS "PPC step: First configures" ) +include(cmake/configure.cmake) +include(cmake/modes.cmake) include(cmake/sanitizers.cmake) -################################ MPI ################################ -option(USE_MPI OFF) -if( USE_MPI ) - find_package( MPI ) - if( MPI_FOUND ) - include_directories( ${MPI_INCLUDE_PATH} ) - else( MPI_FOUND ) - set( USE_MPI OFF ) - endif( MPI_FOUND ) - include(cmake/boost.cmake) -endif( USE_MPI ) - -############################### OpenMP ############################## -option(USE_OMP OFF) -if( USE_OMP ) - find_package( OpenMP ) - if( OpenMP_FOUND ) - include_directories( ${OpenMP_C_INCLUDE_DIRS} ${OpenMP_CXX_INCLUDE_DIRS} ) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") - if ( MSVC AND MSVC_VERSION GREATER 1919 ) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /openmp:experimental") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /openmp:experimental") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") - add_compile_options(/openmp:experimental) - endif() - else( OpenMP_FOUND ) - if (WIN32) - message(WARNING "OpenMP NOT FOUND") - else() - message(FATAL_ERROR "OpenMP NOT FOUND") - endif() - endif( OpenMP_FOUND ) -endif( USE_OMP ) - -############################ std::thread ############################ -option(USE_STL OFF) -if( USE_STL ) - find_package( Threads ) -endif( USE_STL ) +################# Parallel programming technologies ################# -################################ TBB ################################ -option(USE_TBB OFF) -if( USE_TBB ) - include(cmake/onetbb.cmake) -endif( USE_TBB ) +message( STATUS "PPC step: Setup parallel programming technologies" ) +include(cmake/mpi.cmake) +include(cmake/openmp.cmake) +include(cmake/threads.cmake) +include(cmake/onetbb.cmake) -######################### Functional mode ########################## -option(USE_FUNC_TESTS OFF) -if( USE_FUNC_TESTS ) - message( STATUS "Enable functional tests" ) - add_compile_definitions(USE_FUNC_TESTS) -endif( USE_FUNC_TESTS ) +######################### External projects ######################### -######################### Performance mode ########################## -option(USE_PERF_TESTS OFF) -if( USE_PERF_TESTS ) - message( STATUS "Enable performance tests" ) - add_compile_definitions(USE_PERF_TESTS) -endif( USE_PERF_TESTS ) +message( STATUS "PPC step: Setup external projects" ) +include(cmake/opencv.cmake) +include(cmake/gtest.cmake) +include(cmake/boost.cmake) -############################## Modules ############################## +############################## Headers ############################## +message( STATUS "PPC step: Setup headers" ) include_directories(3rdparty) include_directories(modules) include_directories(tasks) +############################## Modules ############################## + +message( STATUS "PPC step: Setup modules" ) add_subdirectory(modules) add_subdirectory(tasks) -add_subdirectory(1stsamples) diff --git a/cmake/configure.cmake b/cmake/configure.cmake index cc40e83de..00af318e5 100644 --- a/cmake/configure.cmake +++ b/cmake/configure.cmake @@ -1,3 +1,12 @@ +option(ENABLE_MOLD OFF) +if (ENABLE_MOLD) + set(CMAKE_LINKER mold) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=mold") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=mold") + set(CMAKE_EXE_LINKER_FLAGS "-fuse-ld=mold ${CMAKE_EXE_LINKER_FLAGS}") + set(CMAKE_SHARED_LINKER_FLAGS "-fuse-ld=mold ${CMAKE_SHARED_LINKER_FLAGS}") +endif() + if(MSVC) option(gtest_force_shared_crt "" TRUE) endif(MSVC) @@ -46,23 +55,3 @@ if( MSVC ) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W4 /wd4267 /wd4244 /wd4100 /WX") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /wd4267 /wd4244 /wd4100 /WX" ) endif( MSVC ) - -add_compile_definitions(PPC_PATH_TO_PROJECT="${CMAKE_CURRENT_SOURCE_DIR}") - -option(ENABLE_MOLD OFF) -if (ENABLE_MOLD) - set(CMAKE_LINKER mold) - set(CMAKE_EXE_LINKER_FLAGS "-fuse-ld=mold ${CMAKE_EXE_LINKER_FLAGS}") - set(CMAKE_SHARED_LINKER_FLAGS "-fuse-ld=mold ${CMAKE_SHARED_LINKER_FLAGS}") -endif() - -MACRO(SUBDIRLIST result curdir) - FILE(GLOB children RELATIVE ${curdir} ${curdir}/*) - SET(dirlist "") - FOREACH(child ${children}) - IF(IS_DIRECTORY ${curdir}/${child}) - LIST(APPEND dirlist ${child}) - ENDIF() - ENDFOREACH() - SET(${result} ${dirlist}) -ENDMACRO() diff --git a/cmake/modes.cmake b/cmake/modes.cmake new file mode 100644 index 000000000..ee787ccd0 --- /dev/null +++ b/cmake/modes.cmake @@ -0,0 +1,24 @@ +add_compile_definitions(PPC_PATH_TO_PROJECT="${CMAKE_CURRENT_SOURCE_DIR}") + +MACRO(SUBDIRLIST result curdir) + FILE(GLOB children RELATIVE ${curdir} ${curdir}/*) + SET(dirlist "") + FOREACH(child ${children}) + IF(IS_DIRECTORY ${curdir}/${child}) + LIST(APPEND dirlist ${child}) + ENDIF() + ENDFOREACH() + SET(${result} ${dirlist}) +ENDMACRO() + +option(USE_FUNC_TESTS OFF) +if( USE_FUNC_TESTS ) + message( STATUS "Enable functional tests" ) + add_compile_definitions(USE_FUNC_TESTS) +endif( USE_FUNC_TESTS ) + +option(USE_PERF_TESTS OFF) +if( USE_PERF_TESTS ) + message( STATUS "Enable performance tests" ) + add_compile_definitions(USE_PERF_TESTS) +endif( USE_PERF_TESTS ) diff --git a/cmake/mpi.cmake b/cmake/mpi.cmake new file mode 100644 index 000000000..3a26e000e --- /dev/null +++ b/cmake/mpi.cmake @@ -0,0 +1,9 @@ +option(USE_MPI OFF) +if( USE_MPI ) + find_package( MPI ) + if( MPI_FOUND ) + include_directories( ${MPI_INCLUDE_PATH} ) + else( MPI_FOUND ) + set( USE_MPI OFF ) + endif( MPI_FOUND ) +endif( USE_MPI ) diff --git a/cmake/onetbb.cmake b/cmake/onetbb.cmake index 76523ed87..ba529e4ca 100644 --- a/cmake/onetbb.cmake +++ b/cmake/onetbb.cmake @@ -1,28 +1,31 @@ -# Build Core OneTBB components -include_directories(${CMAKE_SOURCE_DIR}/3rdparty/onetbb/include) +option(USE_TBB OFF) +if( USE_TBB ) + # Build Core OneTBB components + include_directories(${CMAKE_SOURCE_DIR}/3rdparty/onetbb/include) -include(ExternalProject) -if(MSVC) - ExternalProject_Add(ppc_onetbb - SOURCE_DIR "${CMAKE_SOURCE_DIR}/3rdparty/onetbb" - PREFIX "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb" - BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" - INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install" - CONFIGURE_COMMAND "${CMAKE_COMMAND}" -S "${CMAKE_SOURCE_DIR}/3rdparty/onetbb/" -B "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build/" -DCMAKE_CXX_FLAGS="-w" -DCMAKE_C_FLAGS="-w" - -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -D CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} -D CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} - -G${CMAKE_GENERATOR} -DTBB_TEST=OFF -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - BUILD_COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" --config ${CMAKE_BUILD_TYPE} --parallel - INSTALL_COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" --prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install" - TEST_COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install/bin" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") -else(MSVC) - ExternalProject_Add(ppc_onetbb - SOURCE_DIR "${CMAKE_SOURCE_DIR}/3rdparty/onetbb" - PREFIX "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb" - BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" - INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install" - CONFIGURE_COMMAND "${CMAKE_COMMAND}" -S "${CMAKE_SOURCE_DIR}/3rdparty/onetbb/" -B "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build/" -DCMAKE_CXX_FLAGS="-w" -DCMAKE_C_FLAGS="-w" - -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -D CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} -D CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} - -G${CMAKE_GENERATOR} -DTBB_TEST=OFF -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - BUILD_COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" --config ${CMAKE_BUILD_TYPE} --parallel - INSTALL_COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" --prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install") -endif(MSVC) + include(ExternalProject) + if(MSVC) + ExternalProject_Add(ppc_onetbb + SOURCE_DIR "${CMAKE_SOURCE_DIR}/3rdparty/onetbb" + PREFIX "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb" + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" + INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install" + CONFIGURE_COMMAND "${CMAKE_COMMAND}" -S "${CMAKE_SOURCE_DIR}/3rdparty/onetbb/" -B "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build/" -DCMAKE_CXX_FLAGS="-w" -DCMAKE_C_FLAGS="-w" + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -D CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} -D CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} + -G${CMAKE_GENERATOR} -DTBB_TEST=OFF -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + BUILD_COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" --config ${CMAKE_BUILD_TYPE} --parallel + INSTALL_COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" --prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install" + TEST_COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install/bin" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") + else(MSVC) + ExternalProject_Add(ppc_onetbb + SOURCE_DIR "${CMAKE_SOURCE_DIR}/3rdparty/onetbb" + PREFIX "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb" + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" + INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install" + CONFIGURE_COMMAND "${CMAKE_COMMAND}" -S "${CMAKE_SOURCE_DIR}/3rdparty/onetbb/" -B "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build/" -DCMAKE_CXX_FLAGS="-w" -DCMAKE_C_FLAGS="-w" + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -D CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} -D CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} + -G${CMAKE_GENERATOR} -DTBB_TEST=OFF -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + BUILD_COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" --config ${CMAKE_BUILD_TYPE} --parallel + INSTALL_COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" --prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install") + endif(MSVC) +endif( USE_TBB ) diff --git a/cmake/opencv.cmake b/cmake/opencv.cmake index bac0b6fe5..7099c5bb2 100644 --- a/cmake/opencv.cmake +++ b/cmake/opencv.cmake @@ -1,4 +1,5 @@ # Build OpenCV components +# core highgui imgcodecs imgproc videoio include_directories(${CMAKE_SOURCE_DIR}/3rdparty/opencv/include) include(ExternalProject) ExternalProject_Add(ppc_opencv @@ -9,7 +10,6 @@ ExternalProject_Add(ppc_opencv CONFIGURE_COMMAND "${CMAKE_COMMAND}" -S "${CMAKE_SOURCE_DIR}/3rdparty/opencv/" -B "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build/" -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -G${CMAKE_GENERATOR} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -D CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} -D CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} -DCMAKE_CXX_FLAGS="-w" -DCMAKE_C_FLAGS="-w" -DENABLE_CCACHE=ON -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF - -DBUILD_EXAMPLES=OFF -DBUILD_DOCS=OFF -DWITH_CUDA=OFF -DWITH_OPENCL=OFF -DBUILD_opencv_calib3d=OFF -DBUILD_opencv_dnn=OFF -DBUILD_opencv_ml=OFF -DBUILD_opencv_objdetect=OFF - -DBUILD_opencv_java=OFF -DBUILD_opencv_gapi=OFF -DBUILD_opencv_video=OFF -DBUILD_opencv_world=OFF -DBUILD_opencv_features2d=OFF -DBUILD_opencv_flann=OFF -DBUILD_opencv_photo=OFF + -DBUILD_EXAMPLES=OFF -DBUILD_DOCS=OFF -DWITH_CUDA=OFF -DWITH_OPENCL=OFF -DBUILD_LIST="core,highgui,imgcodecs,imgproc,videoio," BUILD_COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" --config ${CMAKE_BUILD_TYPE} --parallel INSTALL_COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" --prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/install") diff --git a/cmake/openmp.cmake b/cmake/openmp.cmake new file mode 100644 index 000000000..ec648df31 --- /dev/null +++ b/cmake/openmp.cmake @@ -0,0 +1,22 @@ +option(USE_OMP OFF) +if( USE_OMP ) + find_package( OpenMP ) + if( OpenMP_FOUND ) + include_directories( ${OpenMP_C_INCLUDE_DIRS} ${OpenMP_CXX_INCLUDE_DIRS} ) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") + if ( MSVC AND MSVC_VERSION GREATER 1919 ) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /openmp:experimental") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /openmp:experimental") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") + add_compile_options(/openmp:experimental) + endif() + else( OpenMP_FOUND ) + if (WIN32) + message(WARNING "OpenMP NOT FOUND") + else() + message(FATAL_ERROR "OpenMP NOT FOUND") + endif() + endif( OpenMP_FOUND ) +endif( USE_OMP ) diff --git a/cmake/sanitizers.cmake b/cmake/sanitizers.cmake index fd32d7daa..d0726be15 100644 --- a/cmake/sanitizers.cmake +++ b/cmake/sanitizers.cmake @@ -1,3 +1,4 @@ +option(ENABLE_ADDRESS_SANITIZER OFF) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") if (ENABLE_ADDRESS_SANITIZER) add_compile_options(-fsanitize=address) diff --git a/cmake/threads.cmake b/cmake/threads.cmake new file mode 100644 index 000000000..be534ffd9 --- /dev/null +++ b/cmake/threads.cmake @@ -0,0 +1,4 @@ +option(USE_STL OFF) +if( USE_STL ) + find_package( Threads ) +endif( USE_STL ) From 38f1657229ebd633f3f46a34ed6a5a88f707e68e Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Fri, 17 Jan 2025 02:37:55 +0100 Subject: [PATCH 8/9] fix scripts --- .github/workflows/main.yml | 4 ---- scripts/run.bat | 6 ------ scripts/run_mpi.sh | 3 +-- scripts/run_perf_collector.sh | 1 + scripts/run_threads.sh | 5 +---- 5 files changed, 3 insertions(+), 16 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1bc7ccbc3..68bc96dda 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -66,7 +66,6 @@ jobs: - name: Build project run: | cmake --build build --parallel - source build/ppc_opencv/install/bin/setup_vars_opencv4.sh env: CC: gcc-13 CXX: g++-13 @@ -146,7 +145,6 @@ jobs: - name: Build project run: | cmake --build build --parallel - source build/ppc_opencv/install/bin/setup_vars_opencv4.sh env: CC: gcc-13 CXX: g++-13 @@ -905,7 +903,6 @@ jobs: - name: Build project run: | cmake --build build --parallel - source build/ppc_opencv/install/bin/setup_vars_opencv4.sh - name: Run tests (MPI) run: | source scripts/run_mpi.sh @@ -988,7 +985,6 @@ jobs: - name: Build project run: | cmake --build build --parallel - source build/ppc_opencv/install/bin/setup_vars_opencv4.sh env: CC: gcc-12 CXX: g++-12 diff --git a/scripts/run.bat b/scripts/run.bat index bc20417e3..f6dfba950 100644 --- a/scripts/run.bat +++ b/scripts/run.bat @@ -3,12 +3,6 @@ build\bin\core_func_tests.exe --gtest_also_run_disabled_tests --gtest_repeat=10 --gtest_recreate_environments_when_repeating || exit 1 build\bin\ref_func_tests.exe --gtest_also_run_disabled_tests --gtest_repeat=10 --gtest_recreate_environments_when_repeating || exit 1 -if "%CLANG_BUILD%" NEQ "1" mpiexec.exe -np 4 build\bin\sample_mpi.exe -if "%CLANG_BUILD%" NEQ "1" mpiexec.exe -np 4 build\bin\sample_mpi_boost.exe -if "%CLANG_BUILD%" NEQ "1" build\bin\sample_omp.exe -build\bin\sample_stl.exe -build\bin\sample_tbb.exe - if "%CLANG_BUILD%" NEQ "1" mpiexec.exe -np 4 build\bin\all_func_tests.exe --gtest_repeat=10 || exit 1 if "%CLANG_BUILD%" NEQ "1" mpiexec.exe -np 4 build\bin\mpi_func_tests.exe --gtest_repeat=10 || exit 1 if "%CLANG_BUILD%" NEQ "1" build\bin\all_func_tests.exe || exit 1 diff --git a/scripts/run_mpi.sh b/scripts/run_mpi.sh index 9eb1bac5f..92d2835a9 100644 --- a/scripts/run_mpi.sh +++ b/scripts/run_mpi.sh @@ -1,4 +1,5 @@ #!/bin/bash +source build/ppc_opencv/install/bin/setup_vars_opencv4.sh if [[ $OSTYPE == "linux-gnu" && -z "$ASAN_RUN" ]]; then valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/bin/core_func_tests @@ -12,8 +13,6 @@ fi ./build/bin/ref_func_tests --gtest_also_run_disabled_tests --gtest_repeat=10 --gtest_recreate_environments_when_repeating if [[ -z "$ASAN_RUN" ]]; then - mpirun $1 -np $PROC_COUNT ./build/bin/sample_mpi - mpirun $1 -np $PROC_COUNT ./build/bin/sample_mpi_boost mpirun $1 -np $PROC_COUNT ./build/bin/all_func_tests --gtest_also_run_disabled_tests --gtest_repeat=10 --gtest_recreate_environments_when_repeating mpirun $1 -np $PROC_COUNT ./build/bin/mpi_func_tests --gtest_also_run_disabled_tests --gtest_repeat=10 --gtest_recreate_environments_when_repeating fi diff --git a/scripts/run_perf_collector.sh b/scripts/run_perf_collector.sh index f319b0f0d..6c58772e2 100644 --- a/scripts/run_perf_collector.sh +++ b/scripts/run_perf_collector.sh @@ -1,4 +1,5 @@ #!/bin/bash +source build/ppc_opencv/install/bin/setup_vars_opencv4.sh if [[ -z "$ASAN_RUN" ]]; then if [[ $OSTYPE == "linux-gnu" ]]; then diff --git a/scripts/run_threads.sh b/scripts/run_threads.sh index 947e935a1..731276bc8 100644 --- a/scripts/run_threads.sh +++ b/scripts/run_threads.sh @@ -1,4 +1,5 @@ #!/bin/bash +source build/ppc_opencv/install/bin/setup_vars_opencv4.sh if [[ $OSTYPE == "linux-gnu" && -z "$ASAN_RUN" ]]; then valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/bin/core_func_tests @@ -13,10 +14,6 @@ fi ./build/bin/core_func_tests --gtest_also_run_disabled_tests --gtest_repeat=3 --gtest_recreate_environments_when_repeating ./build/bin/ref_func_tests --gtest_also_run_disabled_tests --gtest_repeat=3 --gtest_recreate_environments_when_repeating -./build/bin/sample_omp -./build/bin/sample_stl -./build/bin/sample_tbb - ./build/bin/omp_func_tests --gtest_also_run_disabled_tests --gtest_repeat=3 --gtest_recreate_environments_when_repeating ./build/bin/seq_func_tests --gtest_also_run_disabled_tests --gtest_repeat=3 --gtest_recreate_environments_when_repeating ./build/bin/stl_func_tests --gtest_also_run_disabled_tests --gtest_repeat=3 --gtest_recreate_environments_when_repeating From 402e9f891bb438d4ac428ab9831ba80ddd51e33d Mon Sep 17 00:00:00 2001 From: anesterov Date: Fri, 17 Jan 2025 14:08:36 +0100 Subject: [PATCH 9/9] fix win --- .github/workflows/main.yml | 16 ++++++------ CMakeLists.txt | 1 - cmake/configure.cmake | 9 ------- cmake/mpi.cmake | 1 + cmake/onetbb.cmake | 6 ++--- cmake/opencv.cmake | 39 +++++++++++++++++++++--------- cmake/openmp.cmake | 6 ----- modules/core/task/include/task.hpp | 6 ++--- tasks/CMakeLists.txt | 23 +++++++++++++++--- 9 files changed, 61 insertions(+), 46 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 82f77f33e..4a7efde44 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -43,7 +43,7 @@ jobs: sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install gcc-13 g++-13 - sudo apt-get install ninja-build mold + sudo apt-get install ninja-build sudo apt-get install mpich sudo apt-get install libomp-dev sudo apt-get install valgrind @@ -56,7 +56,7 @@ jobs: - name: CMake configure run: > cmake -S . -B build - -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -D ENABLE_MOLD=ON + -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -G Ninja -D USE_SEQ=ON -D USE_MPI=ON -D USE_OMP=ON -D USE_TBB=ON -D USE_STL=ON -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -D CMAKE_BUILD_TYPE=RELEASE @@ -122,7 +122,7 @@ jobs: sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install gcc-13 g++-13 - sudo apt-get install ninja-build mold + sudo apt-get install ninja-build sudo apt-get install mpich sudo apt-get install libomp-dev sudo apt-get install valgrind @@ -135,7 +135,7 @@ jobs: - name: CMake configure run: > cmake -S . -B build - -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -D ENABLE_MOLD=ON + -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -G Ninja -D USE_SEQ=ON -D USE_MPI=ON -D USE_OMP=ON -D USE_TBB=ON -D USE_STL=ON -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -D CMAKE_BUILD_TYPE=RELEASE @@ -887,7 +887,7 @@ jobs: run: | sudo apt-get update sudo apt-get install gcc g++ - sudo apt-get install ninja-build mold + sudo apt-get install ninja-build sudo apt-get install mpich sudo apt-get install libomp-dev sudo apt-get install valgrind @@ -902,7 +902,7 @@ jobs: cmake -S . -B build -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -G Ninja -D USE_SEQ=ON -D USE_MPI=ON -D USE_OMP=ON -D USE_TBB=ON -D USE_STL=ON - -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -D ENABLE_MOLD=ON + -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_VERBOSE_MAKEFILE=ON -D USE_COVERAGE=ON @@ -974,7 +974,7 @@ jobs: sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install gcc-12 g++-12 - sudo apt-get install ninja-build mold + sudo apt-get install ninja-build sudo apt-get install mpich sudo apt-get install libomp-dev sudo apt-get install valgrind @@ -987,7 +987,7 @@ jobs: - name: CMake configure run: > cmake -S . -B build - -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -D ENABLE_MOLD=ON + -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -G Ninja -D USE_SEQ=ON -D USE_MPI=ON -D USE_OMP=ON -D USE_TBB=ON -D USE_STL=ON -D USE_FUNC_TESTS=ON -D USE_PERF_TESTS=ON -D CMAKE_BUILD_TYPE=RELEASE diff --git a/CMakeLists.txt b/CMakeLists.txt index 16b5656dc..a6d2b0636 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,6 @@ include(cmake/onetbb.cmake) message( STATUS "PPC step: Setup external projects" ) include(cmake/opencv.cmake) include(cmake/gtest.cmake) -include(cmake/boost.cmake) ############################## Headers ############################## diff --git a/cmake/configure.cmake b/cmake/configure.cmake index 00af318e5..18776fa7a 100644 --- a/cmake/configure.cmake +++ b/cmake/configure.cmake @@ -1,12 +1,3 @@ -option(ENABLE_MOLD OFF) -if (ENABLE_MOLD) - set(CMAKE_LINKER mold) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=mold") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=mold") - set(CMAKE_EXE_LINKER_FLAGS "-fuse-ld=mold ${CMAKE_EXE_LINKER_FLAGS}") - set(CMAKE_SHARED_LINKER_FLAGS "-fuse-ld=mold ${CMAKE_SHARED_LINKER_FLAGS}") -endif() - if(MSVC) option(gtest_force_shared_crt "" TRUE) endif(MSVC) diff --git a/cmake/mpi.cmake b/cmake/mpi.cmake index 3a26e000e..460e8ab58 100644 --- a/cmake/mpi.cmake +++ b/cmake/mpi.cmake @@ -6,4 +6,5 @@ if( USE_MPI ) else( MPI_FOUND ) set( USE_MPI OFF ) endif( MPI_FOUND ) + include(cmake/boost.cmake) endif( USE_MPI ) diff --git a/cmake/onetbb.cmake b/cmake/onetbb.cmake index ba529e4ca..f565aed09 100644 --- a/cmake/onetbb.cmake +++ b/cmake/onetbb.cmake @@ -4,7 +4,7 @@ if( USE_TBB ) include_directories(${CMAKE_SOURCE_DIR}/3rdparty/onetbb/include) include(ExternalProject) - if(MSVC) + if(WIN32) ExternalProject_Add(ppc_onetbb SOURCE_DIR "${CMAKE_SOURCE_DIR}/3rdparty/onetbb" PREFIX "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb" @@ -16,7 +16,7 @@ if( USE_TBB ) BUILD_COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" --config ${CMAKE_BUILD_TYPE} --parallel INSTALL_COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" --prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install" TEST_COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install/bin" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") - else(MSVC) + else() ExternalProject_Add(ppc_onetbb SOURCE_DIR "${CMAKE_SOURCE_DIR}/3rdparty/onetbb" PREFIX "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb" @@ -27,5 +27,5 @@ if( USE_TBB ) -G${CMAKE_GENERATOR} -DTBB_TEST=OFF -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} BUILD_COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" --config ${CMAKE_BUILD_TYPE} --parallel INSTALL_COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/build" --prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_onetbb/install") - endif(MSVC) + endif() endif( USE_TBB ) diff --git a/cmake/opencv.cmake b/cmake/opencv.cmake index 7099c5bb2..90d2ec1c2 100644 --- a/cmake/opencv.cmake +++ b/cmake/opencv.cmake @@ -1,15 +1,30 @@ # Build OpenCV components # core highgui imgcodecs imgproc videoio -include_directories(${CMAKE_SOURCE_DIR}/3rdparty/opencv/include) include(ExternalProject) -ExternalProject_Add(ppc_opencv - SOURCE_DIR "${CMAKE_SOURCE_DIR}/3rdparty/opencv" - PREFIX "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv" - BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" - INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/install" - CONFIGURE_COMMAND "${CMAKE_COMMAND}" -S "${CMAKE_SOURCE_DIR}/3rdparty/opencv/" -B "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build/" - -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -G${CMAKE_GENERATOR} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -D CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} - -D CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} -DCMAKE_CXX_FLAGS="-w" -DCMAKE_C_FLAGS="-w" -DENABLE_CCACHE=ON -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF - -DBUILD_EXAMPLES=OFF -DBUILD_DOCS=OFF -DWITH_CUDA=OFF -DWITH_OPENCL=OFF -DBUILD_LIST="core,highgui,imgcodecs,imgproc,videoio," - BUILD_COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" --config ${CMAKE_BUILD_TYPE} --parallel - INSTALL_COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" --prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/install") +include_directories(${CMAKE_SOURCE_DIR}/3rdparty/opencv/include) +if(WIN32) + ExternalProject_Add(ppc_opencv + SOURCE_DIR "${CMAKE_SOURCE_DIR}/3rdparty/opencv" + PREFIX "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv" + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" + INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/install" + CONFIGURE_COMMAND "${CMAKE_COMMAND}" -S "${CMAKE_SOURCE_DIR}/3rdparty/opencv/" -B "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build/" + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -G${CMAKE_GENERATOR} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -D CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} + -D CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} -DCMAKE_CXX_FLAGS="-w" -DCMAKE_C_FLAGS="-w" -DENABLE_CCACHE=ON -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF + -DBUILD_EXAMPLES=OFF -DBUILD_DOCS=OFF -DWITH_CUDA=OFF -DWITH_OPENCL=OFF -DBUILD_LIST="core,highgui,imgcodecs,imgproc,videoio," + BUILD_COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" --config ${CMAKE_BUILD_TYPE} --parallel + INSTALL_COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" --prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/install" + TEST_COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build/bin" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") +else() + ExternalProject_Add(ppc_opencv + SOURCE_DIR "${CMAKE_SOURCE_DIR}/3rdparty/opencv" + PREFIX "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv" + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" + INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/install" + CONFIGURE_COMMAND "${CMAKE_COMMAND}" -S "${CMAKE_SOURCE_DIR}/3rdparty/opencv/" -B "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build/" + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -G${CMAKE_GENERATOR} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -D CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} + -D CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} -DCMAKE_CXX_FLAGS="-w" -DCMAKE_C_FLAGS="-w" -DENABLE_CCACHE=ON -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF + -DBUILD_EXAMPLES=OFF -DBUILD_DOCS=OFF -DWITH_CUDA=OFF -DWITH_OPENCL=OFF -DBUILD_LIST="core,highgui,imgcodecs,imgproc,videoio," + BUILD_COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" --config ${CMAKE_BUILD_TYPE} --parallel + INSTALL_COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/build" --prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_opencv/install") +endif() diff --git a/cmake/openmp.cmake b/cmake/openmp.cmake index ec648df31..e94fd3e64 100644 --- a/cmake/openmp.cmake +++ b/cmake/openmp.cmake @@ -6,12 +6,6 @@ if( USE_OMP ) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") - if ( MSVC AND MSVC_VERSION GREATER 1919 ) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /openmp:experimental") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /openmp:experimental") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") - add_compile_options(/openmp:experimental) - endif() else( OpenMP_FOUND ) if (WIN32) message(WARNING "OpenMP NOT FOUND") diff --git a/modules/core/task/include/task.hpp b/modules/core/task/include/task.hpp index 2018226c5..bfaa236ee 100644 --- a/modules/core/task/include/task.hpp +++ b/modules/core/task/include/task.hpp @@ -70,9 +70,9 @@ class Task { std::chrono::high_resolution_clock::time_point tmp_time_point_; }; -inline std::filesystem::path GetAbsolutePath(const std::string &relative_path) { - std::filesystem::path path = std::string(PPC_PATH_TO_PROJECT) + "/tasks/" + relative_path; - return path; +inline std::string GetAbsolutePath(const std::string &relative_path) { + const std::filesystem::path path = std::string(PPC_PATH_TO_PROJECT) + "/tasks/" + relative_path; + return path.string(); } } // namespace ppc::core diff --git a/tasks/CMakeLists.txt b/tasks/CMakeLists.txt index 9a3571182..1ba576a9d 100644 --- a/tasks/CMakeLists.txt +++ b/tasks/CMakeLists.txt @@ -138,12 +138,27 @@ foreach(TASK_TYPE ${LIST_OF_TASKS}) endif () add_dependencies(${EXEC_FUNC} ppc_opencv) - target_include_directories(${EXEC_FUNC} PUBLIC "${CMAKE_BINARY_DIR}/ppc_opencv/install/include/opencv4") - target_link_directories(${EXEC_FUNC} PUBLIC "${CMAKE_BINARY_DIR}/ppc_opencv/install/lib") - if(NOT MSVC) - target_link_libraries(${EXEC_FUNC} PUBLIC opencv_core opencv_highgui opencv_imgcodecs opencv_imgproc opencv_videoio) + if(WIN32) + target_include_directories(${EXEC_FUNC} PUBLIC "${CMAKE_BINARY_DIR}/ppc_opencv/install/include") + else() + target_include_directories(${EXEC_FUNC} PUBLIC "${CMAKE_BINARY_DIR}/ppc_opencv/install/include/opencv4") endif() + + if(WIN32) + target_link_directories(${EXEC_FUNC} PUBLIC "${CMAKE_BINARY_DIR}/ppc_opencv/build/lib") + set(OCV_VERSION "4110") + else() + target_link_directories(${EXEC_FUNC} PUBLIC "${CMAKE_BINARY_DIR}/ppc_opencv/install/lib") + endif() + + target_link_libraries(${EXEC_FUNC} PUBLIC + opencv_core${OCV_VERSION} + opencv_highgui${OCV_VERSION} + opencv_imgcodecs${OCV_VERSION} + opencv_imgproc${OCV_VERSION} + opencv_videoio${OCV_VERSION}) + add_dependencies(${EXEC_FUNC} ppc_googletest) target_link_directories(${EXEC_FUNC} PUBLIC "${CMAKE_BINARY_DIR}/ppc_googletest/install/lib") target_link_libraries(${EXEC_FUNC} PUBLIC gtest gtest_main)