From 4815b53a4b9f874adc0c5d58b04ee38f17a18612 Mon Sep 17 00:00:00 2001 From: Alex Tsvetanov Date: Tue, 29 Apr 2025 02:53:03 +0300 Subject: [PATCH 01/13] Add OMP support --- CMakeLists.txt | 8 ++++++++ benchmarks/main.cpp | 12 ++++++++++++ include/pubsub.h | 27 +++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index febd543..5b7e9a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,9 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(Catch2) +# Enable OpenMP +find_package(OpenMP REQUIRED) + # Create target for the library (header-only) add_library(pubsub INTERFACE) @@ -25,6 +28,11 @@ target_include_directories(pubsub INTERFACE $ ) +if(OpenMP_CXX_FOUND) + add_definitions(-DWITH_OMP) + target_link_libraries(pubsub INTERFACE OpenMP::OpenMP_CXX) +endif() + # Install the headers install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install(TARGETS pubsub EXPORT pubsubTargets) diff --git a/benchmarks/main.cpp b/benchmarks/main.cpp index 879f9de..825bf59 100644 --- a/benchmarks/main.cpp +++ b/benchmarks/main.cpp @@ -34,6 +34,18 @@ static void BM_PubSubLib_ASYNC(benchmark::State& state) { } BENCHMARK(BM_PubSubLib_ASYNC); +#ifdef WITH_OMP +// =============== pubsub-lib async using OpenMP Benchmark ============== +static void BM_PubSubLib_OMP_ASYNC(benchmark::State& state) { + omp_set_num_threads(state.range(0)); // Set the number of OpenMP threads dynamically + for (auto _ : state) { + pub.emit_omp_async(42); + } +} +// Pass the thread count as a "range" argument to the benchmark +BENCHMARK(BM_PubSubLib_OMP_ASYNC)->Arg(1)->Arg(2)->Arg(4)->Arg(8)->Arg(16); +#endif + // ================= Boost.Signals2 Benchmark ================= #ifdef USE_BOOST #include diff --git a/include/pubsub.h b/include/pubsub.h index 5c4db81..a1c46cb 100644 --- a/include/pubsub.h +++ b/include/pubsub.h @@ -10,6 +10,10 @@ #include #include +#ifdef WITH_OMP + #include +#endif + #include "unique_couter.h" /** @@ -162,6 +166,19 @@ namespace pubsub { (void)std::async(std::launch::async, cb, args...); } } + +#ifdef WITH_OMP + /** + * @brief Emit an event asynchronously using OpenMP. + */ + template + void emit_omp_async(Args... args) { + #pragma omp parallel for + for (const auto& cb : callbacks) { + cb(args...); + } + } +#endif }; /** @@ -221,6 +238,16 @@ namespace pubsub { get_handler()->emit_async(args...); } +#ifdef WITH_OMP + /** + * @brief Emit an event asynchronously using OpenMP to all listeners. + */ + template requires IsEvent + void emit_omp_async(Args... args) { + get_handler()->emit_omp_async(args...); + } +#endif + /** * @brief Unsubscribe an object from the event. */ From a762759cc4e56497c8b69333dc58d1cd88c7c4c9 Mon Sep 17 00:00:00 2001 From: Alex Tsvetanov Date: Tue, 29 Apr 2025 19:01:26 +0300 Subject: [PATCH 02/13] Update ci.yaml Update ci.yaml Update ci.yaml Update ci.yaml Update ci.yaml Update ci.yaml Update ci.yaml --- .github/workflows/ci.yaml | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f11b00b..f0456c1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -21,7 +21,7 @@ jobs: - uses: actions/checkout@v4 - run: | sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" 17 all - sudo apt install -y cmake ninja-build ccache libomp-dev + sudo apt install -y cmake ninja-build ccache libomp-17-dev echo "CC=${{ matrix.compiler }}" >> $GITHUB_ENV if [[ "${{ matrix.compiler }}" == "gcc" ]]; then echo "CXX=g++" >> $GITHUB_ENV @@ -55,19 +55,16 @@ jobs: matrix: os: [macos-13, macos-14, macos-15] generator: [Ninja, "Unix Makefiles"] - exclude: - - os: macos-13 runs-on: ${{ matrix.os }} name: macOS-${{ matrix.os }}-${{ matrix.generator }} steps: - uses: actions/checkout@v4 - run: | brew install llvm libomp cmake ninja ccache - HOMEBREW_PREFIX=$(brew --prefix) - echo "PATH=${HOMEBREW_PREFIX}/bin:${HOMEBREW_PREFIX}/opt/llvm/bin:$PATH" >> $GITHUB_ENV - echo "LDFLAGS=-L${HOMEBREW_PREFIX}/opt/libomp/lib -L${HOMEBREW_PREFIX}/opt/llvm/lib" >> $GITHUB_ENV - echo "CPPFLAGS=-I${HOMEBREW_PREFIX}/opt/libomp/include -I${HOMEBREW_PREFIX}/opt/llvm/include" >> $GITHUB_ENV - echo "CMAKE_PREFIX_PATH=${HOMEBREW_PREFIX}/opt/libomp;${HOMEBREW_PREFIX}/opt/llvm" >> $GITHUB_ENV + echo "PATH=/opt/homebrew/opt/llvm/bin:/opt/homebrew/opt/ccache/libexec:$PATH" >> $GITHUB_ENV + echo "LDFLAGS=-L/opt/homebrew/opt/libomp/lib -L/opt/homebrew/opt/llvm/lib" >> $GITHUB_ENV + echo "CPPFLAGS=-I/opt/homebrew/opt/libomp/include -I/opt/homebrew/opt/llvm/include" >> $GITHUB_ENV + echo "CMAKE_PREFIX_PATH=/opt/homebrew/opt/libomp;/opt/homebrew/opt/llvm" >> $GITHUB_ENV echo "CC=clang" >> $GITHUB_ENV echo "CXX=clang++" >> $GITHUB_ENV - uses: actions/cache@v4 @@ -93,7 +90,7 @@ jobs: strategy: fail-fast: false matrix: - os: [windows-2022] + os: [windows-2019, windows-2022] runs-on: ${{ matrix.os }} name: Windows-${{ matrix.os }}-MSVC steps: @@ -110,16 +107,12 @@ jobs: os: [windows-2019, windows-2022] compiler: [mingw, llvm] generator: [Ninja, "Unix Makefiles"] - exclude: - - os: windows-2019 - compiler: mingw runs-on: ${{ matrix.os }} name: Windows-${{ matrix.os }}-${{ matrix.compiler }}-${{ matrix.generator }} steps: - uses: actions/checkout@v4 - run: | - choco install cmake ninja ccache llvm -y - choco install mingw --version=12.2.0 + choco install cmake ninja ccache llvm mingw -y echo "CC=${{ matrix.compiler }}" >> $GITHUB_ENV if [[ "${{ matrix.compiler }}" == "mingw" ]]; then echo "CXX=g++" >> $GITHUB_ENV @@ -134,16 +127,6 @@ jobs: -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache shell: bash - - name: Add MinGW to PATH (Windows) - shell: bash - run: | - echo "C:/mingw64/bin" >> $GITHUB_PATH - echo "C:/mingw64/lib" >> $GITHUB_PATH - cp "C:/mingw64/bin/libgomp-1.dll" build/tests/ - - name: Build - shell: bash - run: | - export PATH="/c/mingw64/bin:$PATH" - cmake --build build --config Release --verbose + - run: cmake --build build --config Release --verbose - run: ctest --test-dir build --output-on-failure From d35a2471a81a401fcd8147acaddbc4b75724545f Mon Sep 17 00:00:00 2001 From: Alex Tsvetanov Date: Wed, 30 Apr 2025 01:27:58 +0300 Subject: [PATCH 03/13] Update ci.yaml --- .github/workflows/ci.yaml | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f0456c1..afbc8c5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -21,7 +21,7 @@ jobs: - uses: actions/checkout@v4 - run: | sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" 17 all - sudo apt install -y cmake ninja-build ccache libomp-17-dev + sudo apt install -y cmake ninja-build ccache libomp-dev echo "CC=${{ matrix.compiler }}" >> $GITHUB_ENV if [[ "${{ matrix.compiler }}" == "gcc" ]]; then echo "CXX=g++" >> $GITHUB_ENV @@ -55,16 +55,19 @@ jobs: matrix: os: [macos-13, macos-14, macos-15] generator: [Ninja, "Unix Makefiles"] + exclude: + - os: macos-13 runs-on: ${{ matrix.os }} name: macOS-${{ matrix.os }}-${{ matrix.generator }} steps: - uses: actions/checkout@v4 - run: | brew install llvm libomp cmake ninja ccache - echo "PATH=/opt/homebrew/opt/llvm/bin:/opt/homebrew/opt/ccache/libexec:$PATH" >> $GITHUB_ENV - echo "LDFLAGS=-L/opt/homebrew/opt/libomp/lib -L/opt/homebrew/opt/llvm/lib" >> $GITHUB_ENV - echo "CPPFLAGS=-I/opt/homebrew/opt/libomp/include -I/opt/homebrew/opt/llvm/include" >> $GITHUB_ENV - echo "CMAKE_PREFIX_PATH=/opt/homebrew/opt/libomp;/opt/homebrew/opt/llvm" >> $GITHUB_ENV + HOMEBREW_PREFIX=$(brew --prefix) + echo "PATH=${HOMEBREW_PREFIX}/bin:${HOMEBREW_PREFIX}/opt/llvm/bin:$PATH" >> $GITHUB_ENV + echo "LDFLAGS=-L${HOMEBREW_PREFIX}/opt/libomp/lib -L${HOMEBREW_PREFIX}/opt/llvm/lib" >> $GITHUB_ENV + echo "CPPFLAGS=-I${HOMEBREW_PREFIX}/opt/libomp/include -I${HOMEBREW_PREFIX}/opt/llvm/include" >> $GITHUB_ENV + echo "CMAKE_PREFIX_PATH=${HOMEBREW_PREFIX}/opt/libomp;${HOMEBREW_PREFIX}/opt/llvm" >> $GITHUB_ENV echo "CC=clang" >> $GITHUB_ENV echo "CXX=clang++" >> $GITHUB_ENV - uses: actions/cache@v4 @@ -90,7 +93,7 @@ jobs: strategy: fail-fast: false matrix: - os: [windows-2019, windows-2022] + os: [windows-2022] runs-on: ${{ matrix.os }} name: Windows-${{ matrix.os }}-MSVC steps: @@ -107,12 +110,16 @@ jobs: os: [windows-2019, windows-2022] compiler: [mingw, llvm] generator: [Ninja, "Unix Makefiles"] + exclude: + - os: windows-2019 + compiler: mingw runs-on: ${{ matrix.os }} name: Windows-${{ matrix.os }}-${{ matrix.compiler }}-${{ matrix.generator }} steps: - uses: actions/checkout@v4 - run: | - choco install cmake ninja ccache llvm mingw -y + choco install cmake ninja ccache llvm -y + choco install mingw --version=12.2.0 echo "CC=${{ matrix.compiler }}" >> $GITHUB_ENV if [[ "${{ matrix.compiler }}" == "mingw" ]]; then echo "CXX=g++" >> $GITHUB_ENV @@ -127,6 +134,15 @@ jobs: -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache shell: bash - - run: cmake --build build --config Release --verbose + - name: Add MinGW to PATH (Windows) + shell: bash + run: | + echo "C:/mingw64/bin" >> $GITHUB_PATH + echo "C:/mingw64/lib" >> $GITHUB_PATH + cp "C:/mingw64/bin/libgomp-1.dll" build/tests/ + - name: Build + shell: bash + run: | + export PATH="/c/mingw64/bin:$PATH" + cmake --build build --config Release --verbose - run: ctest --test-dir build --output-on-failure - From 32d7e770f7c1d03a9263ea966838c44e3936e096 Mon Sep 17 00:00:00 2001 From: Alex Tsvetanov Date: Wed, 30 Apr 2025 02:03:38 +0300 Subject: [PATCH 04/13] Update ci.yaml --- .github/workflows/ci.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index afbc8c5..10673ec 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -27,9 +27,9 @@ jobs: echo "CXX=g++" >> $GITHUB_ENV else echo "CXX=clang++" >> $GITHUB_ENV + echo "LDFLAGS=-L/usr/lib/llvm-17/lib" >> $GITHUB_ENV + echo "CPPFLAGS=-I/usr/lib/llvm-17/include" >> $GITHUB_ENV fi - echo "LDFLAGS=-L/usr/lib/llvm-17/lib" >> $GITHUB_ENV - echo "CPPFLAGS=-I/usr/lib/llvm-17/include" >> $GITHUB_ENV - uses: actions/cache@v4 with: path: build From a659266a46a268a1d793085274f7327fd189ac1b Mon Sep 17 00:00:00 2001 From: Alex Tsvetanov Date: Wed, 30 Apr 2025 02:49:53 +0300 Subject: [PATCH 05/13] Update ci.yaml --- .github/workflows/ci.yaml | 190 ++++++++++++++++++++------------------ 1 file changed, 101 insertions(+), 89 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 10673ec..c5ad226 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -9,140 +9,152 @@ on: jobs: linux: + name: Linux ${{ matrix.os }} - ${{ matrix.compiler }} - ${{ matrix.generator }} - ${{ matrix.build_type }} + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-22.04, ubuntu-24.04] compiler: [gcc, clang] generator: [Ninja, "Unix Makefiles"] - runs-on: ${{ matrix.os }} - name: Linux-${{ matrix.os }}-${{ matrix.compiler }}-${{ matrix.generator }} + build_type: [Debug, Release] + steps: - uses: actions/checkout@v4 - - run: | - sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" 17 all - sudo apt install -y cmake ninja-build ccache libomp-dev + + - name: Setup compiler and tools + run: | + sudo apt update + sudo apt install -y cmake ninja-build ccache ${{ matrix.compiler }} g++ echo "CC=${{ matrix.compiler }}" >> $GITHUB_ENV - if [[ "${{ matrix.compiler }}" == "gcc" ]]; then - echo "CXX=g++" >> $GITHUB_ENV - else - echo "CXX=clang++" >> $GITHUB_ENV - echo "LDFLAGS=-L/usr/lib/llvm-17/lib" >> $GITHUB_ENV - echo "CPPFLAGS=-I/usr/lib/llvm-17/include" >> $GITHUB_ENV - fi - - uses: actions/cache@v4 - with: - path: build - key: linux-${{ matrix.compiler }}-${{ matrix.generator }}-build-${{ github.sha }} - restore-keys: linux-${{ matrix.compiler }}-${{ matrix.generator }}-build- - - uses: actions/cache@v4 - with: - path: ~/.ccache - key: linux-${{ matrix.compiler }}-${{ matrix.generator }}-ccache-${{ github.sha }} - restore-keys: linux-${{ matrix.compiler }}-${{ matrix.generator }}-ccache- - - run: | + echo "CXX=${{ matrix.compiler }}++" >> $GITHUB_ENV + + - name: Build OpenMP from source + run: | + git clone --depth 1 https://github.com/llvm/llvm-project.git + cd llvm-project/openmp + mkdir build && cd build + cmake .. -DCMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/openmp-install + cmake --build . --target install -j$(nproc) + + - name: Configure CMake + run: | cmake -S . -B build -G "${{ matrix.generator }}" \ -DCMAKE_C_COMPILER=${{ env.CC }} \ -DCMAKE_CXX_COMPILER=${{ env.CXX }} \ + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ + -DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/openmp-install \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - - run: cmake --build build --config Release --verbose - - run: ctest --test-dir build --output-on-failure - mac: + - name: Build + run: cmake --build build --verbose + + - name: Test + run: | + export LD_LIBRARY_PATH=$GITHUB_WORKSPACE/openmp-install/lib:$LD_LIBRARY_PATH + ctest --test-dir build --output-on-failure + + macos: + name: macOS ${{ matrix.os }} - ${{ matrix.generator }} - ${{ matrix.build_type }} + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [macos-13, macos-14, macos-15] + os: [macos-13, macos-14] generator: [Ninja, "Unix Makefiles"] - exclude: - - os: macos-13 - runs-on: ${{ matrix.os }} - name: macOS-${{ matrix.os }}-${{ matrix.generator }} + build_type: [Debug, Release] + steps: - uses: actions/checkout@v4 - - run: | - brew install llvm libomp cmake ninja ccache - HOMEBREW_PREFIX=$(brew --prefix) - echo "PATH=${HOMEBREW_PREFIX}/bin:${HOMEBREW_PREFIX}/opt/llvm/bin:$PATH" >> $GITHUB_ENV - echo "LDFLAGS=-L${HOMEBREW_PREFIX}/opt/libomp/lib -L${HOMEBREW_PREFIX}/opt/llvm/lib" >> $GITHUB_ENV - echo "CPPFLAGS=-I${HOMEBREW_PREFIX}/opt/libomp/include -I${HOMEBREW_PREFIX}/opt/llvm/include" >> $GITHUB_ENV - echo "CMAKE_PREFIX_PATH=${HOMEBREW_PREFIX}/opt/libomp;${HOMEBREW_PREFIX}/opt/llvm" >> $GITHUB_ENV + + - name: Install dependencies + run: | + brew install cmake ninja ccache llvm echo "CC=clang" >> $GITHUB_ENV echo "CXX=clang++" >> $GITHUB_ENV - - uses: actions/cache@v4 - with: - path: build - key: mac-${{ matrix.generator }}-build-${{ github.sha }} - restore-keys: mac-${{ matrix.generator }}-build- - - uses: actions/cache@v4 - with: - path: ~/.ccache - key: mac-${{ matrix.generator }}-ccache-${{ github.sha }} - restore-keys: mac-${{ matrix.generator }}-ccache- - - run: | + echo "CMAKE_PREFIX_PATH=$(brew --prefix llvm)" >> $GITHUB_ENV + + - name: Build OpenMP + run: | + git clone --depth 1 https://github.com/llvm/llvm-project.git + cd llvm-project/openmp + mkdir build && cd build + cmake .. -DCMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/openmp-install + cmake --build . --target install -j$(sysctl -n hw.logicalcpu) + + - name: Configure + run: | cmake -S . -B build -G "${{ matrix.generator }}" \ + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ + -DCMAKE_PREFIX_PATH="$GITHUB_WORKSPACE/openmp-install;$CMAKE_PREFIX_PATH" \ -DCMAKE_C_COMPILER=${{ env.CC }} \ -DCMAKE_CXX_COMPILER=${{ env.CXX }} \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - - run: cmake --build build --config Release --verbose - - run: ctest --test-dir build --output-on-failure + + - name: Build + run: cmake --build build --verbose + + - name: Test + run: | + export DYLD_LIBRARY_PATH=$GITHUB_WORKSPACE/openmp-install/lib:$DYLD_LIBRARY_PATH + ctest --test-dir build --output-on-failure windows: - strategy: - fail-fast: false - matrix: - os: [windows-2022] + name: Windows ${{ matrix.os }} - ${{ matrix.compiler }} - ${{ matrix.generator }} - ${{ matrix.build_type }} runs-on: ${{ matrix.os }} - name: Windows-${{ matrix.os }}-MSVC - steps: - - uses: actions/checkout@v4 - - run: choco install cmake ninja ccache -y - - run: cmake -S . -B build -A x64 - - run: cmake --build build --config Release --verbose - - run: ctest --test-dir build --output-on-failure - - windows-alt: strategy: fail-fast: false matrix: os: [windows-2019, windows-2022] - compiler: [mingw, llvm] + compiler: [msvc, clang, mingw] generator: [Ninja, "Unix Makefiles"] - exclude: - - os: windows-2019 - compiler: mingw - runs-on: ${{ matrix.os }} - name: Windows-${{ matrix.os }}-${{ matrix.compiler }}-${{ matrix.generator }} + build_type: [Debug, Release] + steps: - uses: actions/checkout@v4 - - run: | + + - name: Install dependencies + shell: bash + run: | choco install cmake ninja ccache llvm -y - choco install mingw --version=12.2.0 - echo "CC=${{ matrix.compiler }}" >> $GITHUB_ENV if [[ "${{ matrix.compiler }}" == "mingw" ]]; then + choco install mingw --version=12.2.0 -y + echo "CC=gcc" >> $GITHUB_ENV echo "CXX=g++" >> $GITHUB_ENV - else + echo "PATH=C:/mingw64/bin:$PATH" >> $GITHUB_ENV + elif [[ "${{ matrix.compiler }}" == "clang" ]]; then + echo "CC=clang" >> $GITHUB_ENV echo "CXX=clang++" >> $GITHUB_ENV + echo "PATH=C:/Program Files/LLVM/bin:$PATH" >> $GITHUB_ENV + else + echo "CC=cl.exe" >> $GITHUB_ENV + echo "CXX=cl.exe" >> $GITHUB_ENV fi + + - name: Build OpenMP shell: bash - - run: | - cmake -S . -B build -G "${{ matrix.generator }}" \ - -DCMAKE_C_COMPILER=${{ env.CC }} \ - -DCMAKE_CXX_COMPILER=${{ env.CXX }} \ - -DCMAKE_C_COMPILER_LAUNCHER=ccache \ - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - shell: bash - - name: Add MinGW to PATH (Windows) + run: | + git clone --depth 1 https://github.com/llvm/llvm-project.git + cd llvm-project/openmp + mkdir build && cd build + cmake .. -DCMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/openmp-install -DCMAKE_GENERATOR="${{ matrix.generator }}" + cmake --build . --target install + + - name: Configure shell: bash run: | - echo "C:/mingw64/bin" >> $GITHUB_PATH - echo "C:/mingw64/lib" >> $GITHUB_PATH - cp "C:/mingw64/bin/libgomp-1.dll" build/tests/ + cmake -S . -B build -G "${{ matrix.generator }}" \ + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ + -DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/openmp-install \ + -DCMAKE_C_COMPILER=${{ env.CC }} \ + -DCMAKE_CXX_COMPILER=${{ env.CXX }} + - name: Build - shell: bash + run: cmake --build build --config ${{ matrix.build_type }} --verbose + + - name: Test run: | - export PATH="/c/mingw64/bin:$PATH" - cmake --build build --config Release --verbose - - run: ctest --test-dir build --output-on-failure + cd build + ctest -C ${{ matrix.build_type }} --output-on-failure From c9be9f6850fae7c77d5c9f535dda54ccc5f8c046 Mon Sep 17 00:00:00 2001 From: Alex Tsvetanov Date: Wed, 30 Apr 2025 03:00:58 +0300 Subject: [PATCH 06/13] Update ci.yaml --- .github/workflows/ci.yaml | 102 +++++++++++++++++++++++++++++--------- 1 file changed, 79 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c5ad226..85675c9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -26,8 +26,13 @@ jobs: run: | sudo apt update sudo apt install -y cmake ninja-build ccache ${{ matrix.compiler }} g++ - echo "CC=${{ matrix.compiler }}" >> $GITHUB_ENV - echo "CXX=${{ matrix.compiler }}++" >> $GITHUB_ENV + if [[ "${{ matrix.compiler }}" == "gcc" ]]; then + echo "CC=gcc" >> $GITHUB_ENV + echo "CXX=g++" >> $GITHUB_ENV + elif [[ "${{ matrix.compiler }}" == "clang" ]]; then + echo "CC=clang" >> $GITHUB_ENV + echo "CXX=clang++" >> $GITHUB_ENV + fi - name: Build OpenMP from source run: | @@ -119,42 +124,93 @@ jobs: shell: bash run: | choco install cmake ninja ccache llvm -y + echo "PATH=/c/ProgramData/chocolatey/bin:$PATH" >> $GITHUB_ENV + if [[ "${{ matrix.compiler }}" == "mingw" ]]; then choco install mingw --version=12.2.0 -y echo "CC=gcc" >> $GITHUB_ENV echo "CXX=g++" >> $GITHUB_ENV echo "PATH=C:/mingw64/bin:$PATH" >> $GITHUB_ENV + + if [[ "${{ matrix.generator }}" == "Unix Makefiles" ]]; then + echo "CMAKE_MAKE_PROGRAM=C:/mingw64/bin/mingw32-make.exe" >> $GITHUB_ENV + fi + elif [[ "${{ matrix.compiler }}" == "clang" ]]; then echo "CC=clang" >> $GITHUB_ENV echo "CXX=clang++" >> $GITHUB_ENV echo "PATH=C:/Program Files/LLVM/bin:$PATH" >> $GITHUB_ENV - else - echo "CC=cl.exe" >> $GITHUB_ENV - echo "CXX=cl.exe" >> $GITHUB_ENV - fi - - name: Build OpenMP - shell: bash - run: | - git clone --depth 1 https://github.com/llvm/llvm-project.git - cd llvm-project/openmp - mkdir build && cd build - cmake .. -DCMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/openmp-install -DCMAKE_GENERATOR="${{ matrix.generator }}" - cmake --build . --target install + elif [[ "${{ matrix.compiler }}" == "msvc" ]]; then + # Let CMake use VS environment by default, don't set CC/CXX + echo "USE_MSVC=true" >> $GITHUB_ENV + fi - - name: Configure + - name: Configure CMake shell: bash run: | - cmake -S . -B build -G "${{ matrix.generator }}" \ - -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ - -DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/openmp-install \ - -DCMAKE_C_COMPILER=${{ env.CC }} \ - -DCMAKE_CXX_COMPILER=${{ env.CXX }} + CONFIGURE_CMD="cmake -S . -B build -G \"${{ matrix.generator }}\"" + CONFIGURE_CMD+=" -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}" + if [[ "${{ env.USE_MSVC }}" != "true" ]]; then + CONFIGURE_CMD+=" -DCMAKE_C_COMPILER=${{ env.CC }} -DCMAKE_CXX_COMPILER=${{ env.CXX }}" + CONFIGURE_CMD+=" -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" + if [[ -n "${{ env.CMAKE_MAKE_PROGRAM }}" ]]; then + CONFIGURE_CMD+=" -DCMAKE_MAKE_PROGRAM=${{ env.CMAKE_MAKE_PROGRAM }}" + fi + fi + eval $CONFIGURE_CMD - name: Build run: cmake --build build --config ${{ matrix.build_type }} --verbose - name: Test - run: | - cd build - ctest -C ${{ matrix.build_type }} --output-on-failure + run: ctest --test-dir build --build-config ${{ matrix.build_type }} --output-on-failure + name: Windows ${{ matrix.os }} - ${{ matrix.compiler }} - ${{ matrix.generator }} - ${{ matrix.build_type }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [windows-2019, windows-2022] + compiler: [msvc, clang, mingw] + generator: [Ninja, "Unix Makefiles"] + build_type: [Debug, Release] + + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + shell: bash + run: | + choco install cmake ninja ccache llvm -y + if [[ "${{ matrix.compiler }}" == "mingw" ]]; then + choco install mingw --version=12.2.0 -y + echo "CC=gcc" >> $GITHUB_ENV + echo "CXX=g++" >> $GITHUB_ENV + echo "CMAKE_GENERATOR=${{ matrix.generator }}" >> $GITHUB_ENV + echo "PATH=/c/mingw64/bin:$PATH" >> $GITHUB_ENV + elif [[ "${{ matrix.compiler }}" == "clang" ]]; then + echo "CC=clang" >> $GITHUB_ENV + echo "CXX=clang++" >> $GITHUB_ENV + echo "CMAKE_GENERATOR=${{ matrix.generator }}" >> $GITHUB_ENV + echo "PATH=\"/c/Program Files/LLVM/bin\":$PATH" >> $GITHUB_ENV + fi + + - name: Configure CMake + shell: bash + run: | + if [[ "${{ matrix.compiler }}" == "msvc" ]]; then + cmake -S . -B build -G "${{ matrix.generator }}" -A x64 -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + else + cmake -S . -B build -G "${{ matrix.generator }}" \ + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ + -DCMAKE_C_COMPILER=${{ env.CC }} \ + -DCMAKE_CXX_COMPILER=${{ env.CXX }} \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + fi + + - name: Build + run: cmake --build build --config ${{ matrix.build_type }} --verbose + + - name: Run tests + run: ctest --test-dir build --output-on-failure --build-config ${{ matrix.build_type }} \ No newline at end of file From 18ce70cf9a3f943018d52b5d250a72ec1f0eac67 Mon Sep 17 00:00:00 2001 From: Alex Tsvetanov Date: Wed, 30 Apr 2025 03:03:25 +0300 Subject: [PATCH 07/13] Update ci.yaml --- .github/workflows/ci.yaml | 60 ++------------------------------------- 1 file changed, 2 insertions(+), 58 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 85675c9..c64cd65 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -107,64 +107,6 @@ jobs: ctest --test-dir build --output-on-failure windows: - name: Windows ${{ matrix.os }} - ${{ matrix.compiler }} - ${{ matrix.generator }} - ${{ matrix.build_type }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [windows-2019, windows-2022] - compiler: [msvc, clang, mingw] - generator: [Ninja, "Unix Makefiles"] - build_type: [Debug, Release] - - steps: - - uses: actions/checkout@v4 - - - name: Install dependencies - shell: bash - run: | - choco install cmake ninja ccache llvm -y - echo "PATH=/c/ProgramData/chocolatey/bin:$PATH" >> $GITHUB_ENV - - if [[ "${{ matrix.compiler }}" == "mingw" ]]; then - choco install mingw --version=12.2.0 -y - echo "CC=gcc" >> $GITHUB_ENV - echo "CXX=g++" >> $GITHUB_ENV - echo "PATH=C:/mingw64/bin:$PATH" >> $GITHUB_ENV - - if [[ "${{ matrix.generator }}" == "Unix Makefiles" ]]; then - echo "CMAKE_MAKE_PROGRAM=C:/mingw64/bin/mingw32-make.exe" >> $GITHUB_ENV - fi - - elif [[ "${{ matrix.compiler }}" == "clang" ]]; then - echo "CC=clang" >> $GITHUB_ENV - echo "CXX=clang++" >> $GITHUB_ENV - echo "PATH=C:/Program Files/LLVM/bin:$PATH" >> $GITHUB_ENV - - elif [[ "${{ matrix.compiler }}" == "msvc" ]]; then - # Let CMake use VS environment by default, don't set CC/CXX - echo "USE_MSVC=true" >> $GITHUB_ENV - fi - - - name: Configure CMake - shell: bash - run: | - CONFIGURE_CMD="cmake -S . -B build -G \"${{ matrix.generator }}\"" - CONFIGURE_CMD+=" -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}" - if [[ "${{ env.USE_MSVC }}" != "true" ]]; then - CONFIGURE_CMD+=" -DCMAKE_C_COMPILER=${{ env.CC }} -DCMAKE_CXX_COMPILER=${{ env.CXX }}" - CONFIGURE_CMD+=" -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" - if [[ -n "${{ env.CMAKE_MAKE_PROGRAM }}" ]]; then - CONFIGURE_CMD+=" -DCMAKE_MAKE_PROGRAM=${{ env.CMAKE_MAKE_PROGRAM }}" - fi - fi - eval $CONFIGURE_CMD - - - name: Build - run: cmake --build build --config ${{ matrix.build_type }} --verbose - - - name: Test - run: ctest --test-dir build --build-config ${{ matrix.build_type }} --output-on-failure name: Windows ${{ matrix.os }} - ${{ matrix.compiler }} - ${{ matrix.generator }} - ${{ matrix.build_type }} runs-on: ${{ matrix.os }} strategy: @@ -182,6 +124,8 @@ jobs: shell: bash run: | choco install cmake ninja ccache llvm -y + echo "PATH=/c/ProgramData/chocolatey/bin:$PATH" >> $GITHUB_ENV + if [[ "${{ matrix.compiler }}" == "mingw" ]]; then choco install mingw --version=12.2.0 -y echo "CC=gcc" >> $GITHUB_ENV From 90d48f8926d2a41bdde140d285088229efe05702 Mon Sep 17 00:00:00 2001 From: Alex Tsvetanov Date: Wed, 30 Apr 2025 03:11:00 +0300 Subject: [PATCH 08/13] Update ci.yaml --- .github/workflows/ci.yaml | 97 ++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 46 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c64cd65..11ebfb0 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -107,54 +107,59 @@ jobs: ctest --test-dir build --output-on-failure windows: - name: Windows ${{ matrix.os }} - ${{ matrix.compiler }} - ${{ matrix.generator }} - ${{ matrix.build_type }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [windows-2019, windows-2022] - compiler: [msvc, clang, mingw] - generator: [Ninja, "Unix Makefiles"] - build_type: [Debug, Release] - - steps: - - uses: actions/checkout@v4 - - - name: Install dependencies - shell: bash - run: | - choco install cmake ninja ccache llvm -y - echo "PATH=/c/ProgramData/chocolatey/bin:$PATH" >> $GITHUB_ENV - - if [[ "${{ matrix.compiler }}" == "mingw" ]]; then - choco install mingw --version=12.2.0 -y - echo "CC=gcc" >> $GITHUB_ENV - echo "CXX=g++" >> $GITHUB_ENV - echo "CMAKE_GENERATOR=${{ matrix.generator }}" >> $GITHUB_ENV - echo "PATH=/c/mingw64/bin:$PATH" >> $GITHUB_ENV - elif [[ "${{ matrix.compiler }}" == "clang" ]]; then - echo "CC=clang" >> $GITHUB_ENV - echo "CXX=clang++" >> $GITHUB_ENV - echo "CMAKE_GENERATOR=${{ matrix.generator }}" >> $GITHUB_ENV - echo "PATH=\"/c/Program Files/LLVM/bin\":$PATH" >> $GITHUB_ENV + name: Windows ${{ matrix.os }} - ${{ matrix.compiler }} - ${{ matrix.generator }} - ${{ matrix.build_type }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [windows-2019, windows-2022] + compiler: [msvc, clang, mingw] + generator: [Ninja, "Unix Makefiles"] + build_type: [Debug, Release] + + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + shell: bash + run: | + choco install cmake ninja ccache llvm -y + + if [[ "${{ matrix.compiler }}" == "mingw" ]]; then + choco install mingw --version=12.2.0 -y + echo "CC=gcc" >> $GITHUB_ENV + echo "CXX=g++" >> $GITHUB_ENV + echo "PATH=/c/mingw64/bin:$PATH" >> $GITHUB_ENV + if [[ "${{ matrix.generator }}" == "Unix Makefiles" ]]; then + echo "CMAKE_MAKE_PROGRAM=C:/mingw64/bin/mingw32-make.exe" >> $GITHUB_ENV fi + elif [[ "${{ matrix.compiler }}" == "clang" ]]; then + echo "CC=clang" >> $GITHUB_ENV + echo "CXX=clang++" >> $GITHUB_ENV + echo "PATH=/c/Program Files/LLVM/bin:$PATH" >> $GITHUB_ENV + elif [[ "${{ matrix.compiler }}" == "msvc" ]]; then + echo "USE_MSVC=true" >> $GITHUB_ENV + fi - - name: Configure CMake - shell: bash - run: | - if [[ "${{ matrix.compiler }}" == "msvc" ]]; then - cmake -S . -B build -G "${{ matrix.generator }}" -A x64 -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} - else - cmake -S . -B build -G "${{ matrix.generator }}" \ - -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ - -DCMAKE_C_COMPILER=${{ env.CC }} \ - -DCMAKE_CXX_COMPILER=${{ env.CXX }} \ - -DCMAKE_C_COMPILER_LAUNCHER=ccache \ - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + - name: Configure CMake + shell: bash + run: | + CONFIGURE_CMD="cmake -S . -B build -G \"${{ matrix.generator }}\"" + CONFIGURE_CMD+=" -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}" + if [[ "${{ env.USE_MSVC }}" != "true" ]]; then + CONFIGURE_CMD+=" -DCMAKE_C_COMPILER=${{ env.CC }} -DCMAKE_CXX_COMPILER=${{ env.CXX }}" + CONFIGURE_CMD+=" -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" + if [[ -n "${{ env.CMAKE_MAKE_PROGRAM }}" ]]; then + CONFIGURE_CMD+=" -DCMAKE_MAKE_PROGRAM=${{ env.CMAKE_MAKE_PROGRAM }}" fi + else + CONFIGURE_CMD+=" -A x64" + fi + echo "Running: $CONFIGURE_CMD" + eval $CONFIGURE_CMD - - name: Build - run: cmake --build build --config ${{ matrix.build_type }} --verbose + - name: Build + run: cmake --build build --config ${{ matrix.build_type }} --verbose - - name: Run tests - run: ctest --test-dir build --output-on-failure --build-config ${{ matrix.build_type }} \ No newline at end of file + - name: Run tests + run: ctest --test-dir build --output-on-failure --build-config ${{ matrix.build_type }} From daf9ebd7ae7492058f6bbdd0cf3909e4149bf6da Mon Sep 17 00:00:00 2001 From: Alex Tsvetanov Date: Wed, 30 Apr 2025 03:18:40 +0300 Subject: [PATCH 09/13] Update ci.yaml --- .github/workflows/ci.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 11ebfb0..fb57a6e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -129,14 +129,14 @@ jobs: choco install mingw --version=12.2.0 -y echo "CC=gcc" >> $GITHUB_ENV echo "CXX=g++" >> $GITHUB_ENV - echo "PATH=/c/mingw64/bin:$PATH" >> $GITHUB_ENV + echo "C:/mingw64/bin" >> $GITHUB_PATH if [[ "${{ matrix.generator }}" == "Unix Makefiles" ]]; then echo "CMAKE_MAKE_PROGRAM=C:/mingw64/bin/mingw32-make.exe" >> $GITHUB_ENV fi elif [[ "${{ matrix.compiler }}" == "clang" ]]; then echo "CC=clang" >> $GITHUB_ENV echo "CXX=clang++" >> $GITHUB_ENV - echo "PATH=/c/Program Files/LLVM/bin:$PATH" >> $GITHUB_ENV + echo "C:/Program Files/LLVM/bin" >> $GITHUB_PATH elif [[ "${{ matrix.compiler }}" == "msvc" ]]; then echo "USE_MSVC=true" >> $GITHUB_ENV fi From 2319aa55739ffed55ccaa177b8265f215e036d8d Mon Sep 17 00:00:00 2001 From: Alex Tsvetanov Date: Wed, 30 Apr 2025 03:29:38 +0300 Subject: [PATCH 10/13] Update ci.yaml --- .github/workflows/ci.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fb57a6e..c4b7118 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -152,8 +152,6 @@ jobs: if [[ -n "${{ env.CMAKE_MAKE_PROGRAM }}" ]]; then CONFIGURE_CMD+=" -DCMAKE_MAKE_PROGRAM=${{ env.CMAKE_MAKE_PROGRAM }}" fi - else - CONFIGURE_CMD+=" -A x64" fi echo "Running: $CONFIGURE_CMD" eval $CONFIGURE_CMD From c73c3fcd418c694350058fe37d6b0b8b787ee83f Mon Sep 17 00:00:00 2001 From: Alex Tsvetanov Date: Thu, 1 May 2025 02:12:24 +0300 Subject: [PATCH 11/13] TBB pipelines --- .github/workflows/ci.yaml | 181 +++++++++++++++----------------------- .gitmodules | 3 + CMakeLists.txt | 10 +-- benchmarks/CMakeLists.txt | 3 +- benchmarks/main.cpp | 137 +++++++++++++---------------- example/CMakeLists.txt | 3 +- include/pubsub.h | 62 +++++++++++-- tests/test_pubsub.cpp | 2 +- 8 files changed, 202 insertions(+), 199 deletions(-) create mode 100644 .gitmodules diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c4b7118..4feb196 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,163 +1,124 @@ -name: CI +name: Verify Parallelization Libraries for C++ on: push: - branches: [main] + branches: [ main ] pull_request: - branches: [main] + branches: [ main ] jobs: linux: - name: Linux ${{ matrix.os }} - ${{ matrix.compiler }} - ${{ matrix.generator }} - ${{ matrix.build_type }} - runs-on: ${{ matrix.os }} + name: Linux Verification + runs-on: ubuntu-latest strategy: fail-fast: false matrix: - os: [ubuntu-22.04, ubuntu-24.04] - compiler: [gcc, clang] - generator: [Ninja, "Unix Makefiles"] - build_type: [Debug, Release] + compiler: [g++, clang++] + generator: [Unix Makefiles, Ninja] steps: - uses: actions/checkout@v4 - - name: Setup compiler and tools - run: | - sudo apt update - sudo apt install -y cmake ninja-build ccache ${{ matrix.compiler }} g++ - if [[ "${{ matrix.compiler }}" == "gcc" ]]; then - echo "CC=gcc" >> $GITHUB_ENV - echo "CXX=g++" >> $GITHUB_ENV - elif [[ "${{ matrix.compiler }}" == "clang" ]]; then - echo "CC=clang" >> $GITHUB_ENV - echo "CXX=clang++" >> $GITHUB_ENV - fi - - - name: Build OpenMP from source + - name: Install dependencies run: | - git clone --depth 1 https://github.com/llvm/llvm-project.git - cd llvm-project/openmp - mkdir build && cd build - cmake .. -DCMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/openmp-install - cmake --build . --target install -j$(nproc) + sudo apt-get update + sudo apt-get install -y cmake ninja-build g++ clang libtbb-dev + + - name: Set compiler path + run: echo "CXX=${{ matrix.compiler }}" >> $GITHUB_ENV + shell: bash - name: Configure CMake - run: | - cmake -S . -B build -G "${{ matrix.generator }}" \ - -DCMAKE_C_COMPILER=${{ env.CC }} \ - -DCMAKE_CXX_COMPILER=${{ env.CXX }} \ - -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ - -DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/openmp-install \ - -DCMAKE_C_COMPILER_LAUNCHER=ccache \ - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + run: > + cmake -S . -B build + -G "${{ matrix.generator }}" + -DCMAKE_CXX_COMPILER=${{ env.CXX }} + shell: bash - name: Build - run: cmake --build build --verbose + run: cmake --build build --config Release - - name: Test - run: | - export LD_LIBRARY_PATH=$GITHUB_WORKSPACE/openmp-install/lib:$LD_LIBRARY_PATH - ctest --test-dir build --output-on-failure + - name: Run tests + run: ctest --test-dir build --output-on-failure --build-config Release - macos: - name: macOS ${{ matrix.os }} - ${{ matrix.generator }} - ${{ matrix.build_type }} - runs-on: ${{ matrix.os }} + windows: + name: Windows Verification + runs-on: windows-latest strategy: fail-fast: false matrix: - os: [macos-13, macos-14] - generator: [Ninja, "Unix Makefiles"] - build_type: [Debug, Release] + compiler: [cl] + generator: ["Visual Studio 17 2022"] steps: - uses: actions/checkout@v4 - name: Install dependencies - run: | - brew install cmake ninja ccache llvm - echo "CC=clang" >> $GITHUB_ENV - echo "CXX=clang++" >> $GITHUB_ENV - echo "CMAKE_PREFIX_PATH=$(brew --prefix llvm)" >> $GITHUB_ENV + run: choco install cmake ninja -y - - name: Build OpenMP + - name: Install oneTBB via vcpkg run: | - git clone --depth 1 https://github.com/llvm/llvm-project.git - cd llvm-project/openmp - mkdir build && cd build - cmake .. -DCMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/openmp-install - cmake --build . --target install -j$(sysctl -n hw.logicalcpu) + git clone https://github.com/microsoft/vcpkg + ./vcpkg/bootstrap-vcpkg.bat + ./vcpkg/vcpkg install tbb:x64-windows + echo "CMAKE_TOOLCHAIN_FILE=$PWD/vcpkg/scripts/buildsystems/vcpkg.cmake" >> $env:GITHUB_ENV + shell: pwsh - - name: Configure + - name: Debug vcpkg TBB install (optional) run: | - cmake -S . -B build -G "${{ matrix.generator }}" \ - -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ - -DCMAKE_PREFIX_PATH="$GITHUB_WORKSPACE/openmp-install;$CMAKE_PREFIX_PATH" \ - -DCMAKE_C_COMPILER=${{ env.CC }} \ - -DCMAKE_CXX_COMPILER=${{ env.CXX }} \ - -DCMAKE_C_COMPILER_LAUNCHER=ccache \ - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + dir vcpkg/installed/x64-windows/share/tbb + dir vcpkg/installed/x64-windows/lib + shell: pwsh - - name: Build - run: cmake --build build --verbose + - name: Set up MSVC environment + uses: ilammy/msvc-dev-cmd@v1 - - name: Test - run: | - export DYLD_LIBRARY_PATH=$GITHUB_WORKSPACE/openmp-install/lib:$DYLD_LIBRARY_PATH - ctest --test-dir build --output-on-failure + - name: Configure CMake + run: > + cmake -S . -B build + -G "${{ matrix.generator }}" + -DCMAKE_CXX_COMPILER="${{ matrix.compiler }}" + -DCMAKE_TOOLCHAIN_FILE="${{ env.CMAKE_TOOLCHAIN_FILE }}" + shell: bash - windows: - name: Windows ${{ matrix.os }} - ${{ matrix.compiler }} - ${{ matrix.generator }} - ${{ matrix.build_type }} - runs-on: ${{ matrix.os }} + - name: Build + run: cmake --build build --config Release + + - name: Run tests + run: ctest --test-dir build --output-on-failure --build-config Release + macos: + name: macOS Verification + runs-on: macos-latest strategy: fail-fast: false matrix: - os: [windows-2019, windows-2022] - compiler: [msvc, clang, mingw] - generator: [Ninja, "Unix Makefiles"] - build_type: [Debug, Release] + compiler: [clang++, g++-13] + generator: [Unix Makefiles, Ninja] steps: - uses: actions/checkout@v4 - name: Install dependencies + run: brew install cmake ninja tbb + + - name: Install GCC + if: matrix.compiler == 'g++-13' + run: brew install gcc + + - name: Set compiler path + run: echo "CXX=${{ matrix.compiler }}" >> $GITHUB_ENV shell: bash - run: | - choco install cmake ninja ccache llvm -y - - if [[ "${{ matrix.compiler }}" == "mingw" ]]; then - choco install mingw --version=12.2.0 -y - echo "CC=gcc" >> $GITHUB_ENV - echo "CXX=g++" >> $GITHUB_ENV - echo "C:/mingw64/bin" >> $GITHUB_PATH - if [[ "${{ matrix.generator }}" == "Unix Makefiles" ]]; then - echo "CMAKE_MAKE_PROGRAM=C:/mingw64/bin/mingw32-make.exe" >> $GITHUB_ENV - fi - elif [[ "${{ matrix.compiler }}" == "clang" ]]; then - echo "CC=clang" >> $GITHUB_ENV - echo "CXX=clang++" >> $GITHUB_ENV - echo "C:/Program Files/LLVM/bin" >> $GITHUB_PATH - elif [[ "${{ matrix.compiler }}" == "msvc" ]]; then - echo "USE_MSVC=true" >> $GITHUB_ENV - fi - name: Configure CMake + run: > + cmake -S . -B build + -G "${{ matrix.generator }}" + -DCMAKE_CXX_COMPILER=${{ env.CXX }} shell: bash - run: | - CONFIGURE_CMD="cmake -S . -B build -G \"${{ matrix.generator }}\"" - CONFIGURE_CMD+=" -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}" - if [[ "${{ env.USE_MSVC }}" != "true" ]]; then - CONFIGURE_CMD+=" -DCMAKE_C_COMPILER=${{ env.CC }} -DCMAKE_CXX_COMPILER=${{ env.CXX }}" - CONFIGURE_CMD+=" -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" - if [[ -n "${{ env.CMAKE_MAKE_PROGRAM }}" ]]; then - CONFIGURE_CMD+=" -DCMAKE_MAKE_PROGRAM=${{ env.CMAKE_MAKE_PROGRAM }}" - fi - fi - echo "Running: $CONFIGURE_CMD" - eval $CONFIGURE_CMD - name: Build - run: cmake --build build --config ${{ matrix.build_type }} --verbose + run: cmake --build build --config Release - name: Run tests - run: ctest --test-dir build --output-on-failure --build-config ${{ matrix.build_type }} + run: ctest --test-dir build --output-on-failure --build-config Release \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..bdf0de9 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "oneTBB"] + path = libs/oneTBB + url = https://github.com/oneapi-src/oneTBB.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b7e9a3..400a732 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,10 +14,10 @@ FetchContent_Declare( GIT_REPOSITORY https://github.com/catchorg/Catch2.git GIT_TAG v3.5.2 ) + FetchContent_MakeAvailable(Catch2) -# Enable OpenMP -find_package(OpenMP REQUIRED) +find_package(TBB CONFIG REQUIRED) # Create target for the library (header-only) add_library(pubsub INTERFACE) @@ -28,10 +28,8 @@ target_include_directories(pubsub INTERFACE $ ) -if(OpenMP_CXX_FOUND) - add_definitions(-DWITH_OMP) - target_link_libraries(pubsub INTERFACE OpenMP::OpenMP_CXX) -endif() +target_compile_definitions(pubsub INTERFACE -DWITH_TBB) +target_link_libraries(pubsub INTERFACE TBB::tbb) # Install the headers install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index fcbbc6e..ed6eccd 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -38,9 +38,10 @@ if(ENABLE_BM) ) # Linking - target_link_libraries(benchmark_pubsub + target_link_libraries(benchmark_pubsub PUBLIC benchmark::benchmark benchmark::benchmark_main + pubsub ) if(ENABLE_BOOST) diff --git a/benchmarks/main.cpp b/benchmarks/main.cpp index 825bf59..fc44465 100644 --- a/benchmarks/main.cpp +++ b/benchmarks/main.cpp @@ -1,95 +1,82 @@ #include -#include #include +#include #include +#include +#include -// ========== pubsub-lib ========== -#include "pubsub.h" // path to your pubsub-lib header +#include "pubsub.h" -// ======= Benchmark Setup ======= +#ifdef WITH_OMP +#include +#endif -// Simple event struct +// ========== Event Definition ========== constexpr auto MyEvent = pubsub::Event(); -// Global for pubsub-lib -pubsub::Publisher pub; -auto token = pub.subscribe([](int data) { - int dummy = data; - benchmark::DoNotOptimize(dummy); -}); - -// ================= pubsub-lib Benchmark ================= -static void BM_PubSubLib(benchmark::State& state) { - for (auto _ : state) { - pub.emit(42); - } +// ========== Simulated Heavy Work ========== +void heavy_callback_workload(int x) { + volatile uint64_t sum = x; + for (int i = 1; i <= 1000; ++i) + sum += i * i; + benchmark::DoNotOptimize(sum); } -BENCHMARK(BM_PubSubLib); -// =============== pubsub-lib async Benchmark ============== -static void BM_PubSubLib_ASYNC(benchmark::State& state) { - for (auto _ : state) { - pub.emit_async(42); +// ========== Create Publisher with N Heavy Subscribers ========== +std::unique_ptr create_publisher_with_heavy_subs(int num_subs) { + auto pub = std::make_unique(); + for (int i = 0; i < num_subs; ++i) { + pub->subscribe([](int x) { + heavy_callback_workload(x); + }); } + return pub; } -BENCHMARK(BM_PubSubLib_ASYNC); -#ifdef WITH_OMP -// =============== pubsub-lib async using OpenMP Benchmark ============== -static void BM_PubSubLib_OMP_ASYNC(benchmark::State& state) { - omp_set_num_threads(state.range(0)); // Set the number of OpenMP threads dynamically - for (auto _ : state) { - pub.emit_omp_async(42); - } -} -// Pass the thread count as a "range" argument to the benchmark -BENCHMARK(BM_PubSubLib_OMP_ASYNC)->Arg(1)->Arg(2)->Arg(4)->Arg(8)->Arg(16); +// ========== Global Unordered Map of Prebuilt Publishers ========== +std::vector subscriber_counts = {1, 10, 100, 500, 1000}; +std::unordered_map> heavy_publishers; + +// ========== Benchmark Macro ========== +#define DEFINE_HEAVY_EMIT_BENCH(name, emit_method) \ + static void name(benchmark::State& state) { \ + int subs = state.range(0); \ + auto it = heavy_publishers.find(subs); \ + if (it == heavy_publishers.end()) state.SkipWithError("Missing pub"); \ + auto& pub = it->second; \ + for (auto _ : state) { \ + pub->emit_method; \ + } \ + } \ + BENCHMARK(name)->Args({1})->Args({10})->Args({100})->Args({500})->Args({1000}); + +// ========== Emit Variants ========== +DEFINE_HEAVY_EMIT_BENCH(BM_PubSub_Emit_Sync, emit(42)) + +DEFINE_HEAVY_EMIT_BENCH(BM_PubSub_Emit_StdAsync, emit_thread_async(42)) + +#if defined(__cpp_lib_execution) +DEFINE_HEAVY_EMIT_BENCH(BM_PubSub_Emit_StdExec_seq, emit_async(std::execution::seq, 42)) +DEFINE_HEAVY_EMIT_BENCH(BM_PubSub_Emit_StdExec_par, emit_async(std::execution::par, 42)) +DEFINE_HEAVY_EMIT_BENCH(BM_PubSub_Emit_StdExec_par_unseq, emit_async(std::execution::par_unseq, 42)) +DEFINE_HEAVY_EMIT_BENCH(BM_PubSub_Emit_StdExec_unseq, emit_async(std::execution::unseq, 42)) #endif -// ================= Boost.Signals2 Benchmark ================= -#ifdef USE_BOOST -#include - -static void BM_BoostSignals2(benchmark::State& state) { - boost::signals2::signal signal; - signal.connect([](int data) { - int dummy = data; - benchmark::DoNotOptimize(dummy); - }); - - for (auto _ : state) { - signal(42); - } -} -BENCHMARK(BM_BoostSignals2); +#ifdef WITH_OMP +DEFINE_HEAVY_EMIT_BENCH(BM_PubSub_Emit_OpenMP, emit_omp_async(42)) #endif -// ================= Qt Signals Benchmark ================= -#ifdef USE_QT -#include - -class QtEmitter : public QObject { - Q_OBJECT -signals: - void mySignal(int); -}; - -static void BM_QtSignals(benchmark::State& state) { - QtEmitter emitter; - QObject::connect(&emitter, &QtEmitter::mySignal, [](int val) { - int dummy = val; - benchmark::DoNotOptimize(dummy); - }); - - for (auto _ : state) { - emit emitter.mySignal(42); - } -} -BENCHMARK(BM_QtSignals); +#ifdef WITH_TBB +DEFINE_HEAVY_EMIT_BENCH(BM_PubSub_Emit_TBB, emit_tbb_async(42)) #endif -BENCHMARK_MAIN(); +// ========== Manual Main ========== +int main(int argc, char** argv) { + for (int count : subscriber_counts) { + heavy_publishers[count] = create_publisher_with_heavy_subs(count); + } -#ifdef USE_QT -#include "main.moc" -#endif \ No newline at end of file + benchmark::Initialize(&argc, argv); + benchmark::RunSpecifiedBenchmarks(); + return 0; +} diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index d6f76f2..118c699 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -3,5 +3,6 @@ file(GLOB EXAMPLE_SOURCES "*.cpp") foreach(example ${EXAMPLE_SOURCES}) get_filename_component(example_name ${example} NAME_WE) add_executable(${example_name} ${example}) - target_include_directories(${example_name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include) + target_include_directories(${example_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include) + target_link_libraries(${example_name} PUBLIC pubsub) endforeach() diff --git a/include/pubsub.h b/include/pubsub.h index a1c46cb..57063df 100644 --- a/include/pubsub.h +++ b/include/pubsub.h @@ -9,11 +9,17 @@ #include #include #include +#include +#include #ifdef WITH_OMP #include #endif +#ifdef WITH_TBB + #include +#endif + #include "unique_couter.h" /** @@ -110,8 +116,8 @@ namespace pubsub { template class EventHandler : public IEventHandler { using function_type = std::function; - std::list callbacks; - std::unordered_map::iterator> ptrs; + std::vector callbacks; + std::unordered_map::iterator> ptrs; public: /** @@ -161,7 +167,7 @@ namespace pubsub { * a queue and calls them when a thread in the pool is free */ template - void emit_async(Args... args) { + void emit_thread_async(Args... args) { for (const auto& cb : callbacks) { (void)std::async(std::launch::async, cb, args...); } @@ -179,6 +185,32 @@ namespace pubsub { } } #endif + +#ifdef WITH_TBB + /** + * @brief Emit an event asynchronously using oneTBB. + */ + template + void emit_tbb_async(Args... args) { + tbb::parallel_for_each(callbacks.begin(), callbacks.end(), [&](const auto& cb) { + cb(args...); + }); + } +#endif + +#if defined(__cpp_lib_execution) + /** + * @brief Emit an event asynchronously using . + */ + template> + void emit_async(ExecutionPolicy policy, Args... args) { + std::for_each(policy, callbacks.begin(), callbacks.end(), + [&](const auto& cb) { + cb(args...); + } + ); + } +#endif }; /** @@ -234,8 +266,8 @@ namespace pubsub { * @brief Emit an event asynchronously to all listeners. */ template requires IsEvent - void emit_async(Args... args) { - get_handler()->emit_async(args...); + void emit_thread_async(Args... args) { + get_handler()->emit_thread_async(args...); } #ifdef WITH_OMP @@ -248,6 +280,26 @@ namespace pubsub { } #endif +#ifdef WITH_TBB + /** + * @brief Emit an event asynchronously using oneTBB to all listeners. + */ + template requires IsEvent + void emit_tbb_async(Args... args) { + get_handler()->emit_tbb_async(args...); + } +#endif + +#if defined(__cpp_lib_execution) + /** + * @brief Emit an event asynchronously to all listeners. + */ + template requires IsEvent + void emit_async(Args... args) { + get_handler()->emit_async(args...); + } +#endif + /** * @brief Unsubscribe an object from the event. */ diff --git a/tests/test_pubsub.cpp b/tests/test_pubsub.cpp index 426d983..f4ad96f 100644 --- a/tests/test_pubsub.cpp +++ b/tests/test_pubsub.cpp @@ -93,7 +93,7 @@ TEST_CASE("Async event delivery still invokes subscribers") { TestSubscriber sub; sub.subscribe_to(pub); - pub.emit_async(99); + pub.emit_thread_async(99); std::this_thread::sleep_for(std::chrono::milliseconds(100)); REQUIRE(sub.data_sum == 99); } From 8f6987d8aa4d54449149d57f6e9a0e05c35b0236 Mon Sep 17 00:00:00 2001 From: Alex Tsvetanov Date: Thu, 1 May 2025 02:13:28 +0300 Subject: [PATCH 12/13] Update ci.yaml --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4feb196..28dc2a7 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,4 +1,4 @@ -name: Verify Parallelization Libraries for C++ +name: CI on: push: From cd4fa30be172fc616267a5d8a676568d1d566313 Mon Sep 17 00:00:00 2001 From: Alex Tsvetanov Date: Thu, 1 May 2025 03:08:58 +0300 Subject: [PATCH 13/13] Update pubsub.h --- include/pubsub.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/pubsub.h b/include/pubsub.h index 57063df..dabb5e4 100644 --- a/include/pubsub.h +++ b/include/pubsub.h @@ -116,8 +116,8 @@ namespace pubsub { template class EventHandler : public IEventHandler { using function_type = std::function; - std::vector callbacks; - std::unordered_map::iterator> ptrs; + std::list callbacks; + std::unordered_map::iterator> ptrs; public: /**