From 883f1bad33b692d796967e736fb401d1c54ba00d Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Fri, 1 May 2026 22:48:36 +0200 Subject: [PATCH 1/9] Add SYCL backend integration --- .../actions/setup-sycl-toolchain/action.yml | 185 ++++++++++++++++++ .github/workflows/sycl-ci.yml | 151 ++++++++++++++ CMakeLists.txt | 4 + app/Graph/graph_build.cpp | 2 + app/SYCL/CMakeLists.txt | 25 +++ app/SYCL/sycl_example.cpp | 65 ++++++ app/SYCL/sycl_kernel.cpp | 7 + include/parallel/backends.hpp | 42 +++- include/parallel/parallel.hpp | 5 +- src/layers/CMakeLists.txt | 16 ++ test/CMakeLists.txt | 9 + test/benchmarking/test_layers_time.cpp | 18 ++ test/parallel/test_sycl_parallel.cpp | 34 ++++ test/parallel_backends.hpp | 55 ++++++ test/single_layer/test_convlayer.cpp | 19 +- test/single_layer/test_ewlayer.cpp | 57 +++--- test/single_layer/test_poolinglayer.cpp | 19 +- .../test_binaryoplayer_parall.cpp | 5 +- .../test_convlayer_parall.cpp | 25 +-- .../test_ewlayer_parall.cpp | 45 +++-- .../test_poolinglayer_parall.cpp | 37 +--- .../test_reducelayer_parall.cpp | 5 +- 22 files changed, 710 insertions(+), 120 deletions(-) create mode 100644 .github/actions/setup-sycl-toolchain/action.yml create mode 100644 .github/workflows/sycl-ci.yml create mode 100644 app/SYCL/CMakeLists.txt create mode 100644 app/SYCL/sycl_example.cpp create mode 100644 app/SYCL/sycl_kernel.cpp create mode 100644 test/parallel/test_sycl_parallel.cpp create mode 100644 test/parallel_backends.hpp diff --git a/.github/actions/setup-sycl-toolchain/action.yml b/.github/actions/setup-sycl-toolchain/action.yml new file mode 100644 index 000000000..a88415680 --- /dev/null +++ b/.github/actions/setup-sycl-toolchain/action.yml @@ -0,0 +1,185 @@ +name: Setup SYCL toolchain +description: Prepare AdaptiveCpp and compiler settings for ITLabAI SYCL CI. + +inputs: + phase: + description: Either prepare or build. + required: true + cache-hit: + description: actions/cache cache-hit output for the AdaptiveCpp toolchain. + default: "false" + +runs: + using: composite + steps: + - name: Setup MSVC environment + if: ${{ runner.os == 'Windows' }} + uses: ilammy/msvc-dev-cmd@v1 + + - name: Install macOS toolchain dependencies + if: ${{ runner.os == 'macOS' && inputs.phase == 'build' }} + shell: bash + run: brew install adaptivecpp libomp ninja + + - name: Configure macOS toolchain environment + if: ${{ runner.os == 'macOS' && inputs.phase == 'build' }} + shell: bash + run: | + { + echo "ITLABAI_CC=$(xcrun --find clang)" + echo "ITLABAI_CXX=$(xcrun --find clang++)" + echo "ITLABAI_CMAKE_PREFIX_PATH=$(brew --prefix adaptivecpp);$(brew --prefix libomp)" + echo "ITLABAI_OPENMP_ROOT=$(brew --prefix libomp)" + } >> "${GITHUB_ENV}" + + - name: Install Linux toolchain dependencies + if: ${{ runner.os == 'Linux' && (inputs.phase == 'build' || inputs.cache-hit != 'true') }} + shell: bash + run: | + sudo apt-get update + sudo apt-get install -y \ + build-essential \ + ccache \ + clang-18 \ + cmake \ + libboost-context-dev \ + libboost-fiber-dev \ + libboost-filesystem-dev \ + libboost-system-dev \ + libboost-test-dev \ + libclang-18-dev \ + libomp-18-dev \ + llvm-18-dev \ + ninja-build \ + python3 + + - name: Build Linux AdaptiveCpp + if: ${{ runner.os == 'Linux' && inputs.phase == 'prepare' && inputs.cache-hit != 'true' }} + shell: bash + env: + ACPP_INSTALL_DIR: ${{ runner.temp }}/adaptivecpp-install + ACPP_SOURCE_DIR: ${{ runner.temp }}/AdaptiveCpp + ACPP_BUILD_DIR: ${{ runner.temp }}/AdaptiveCpp-build + ACPP_ARCHIVE_DIR: ${{ runner.temp }}/archives + run: | + mkdir -p "${ACPP_ARCHIVE_DIR}" "${ACPP_BUILD_DIR}" "${ACPP_INSTALL_DIR}" + archive="${ACPP_ARCHIVE_DIR}/AdaptiveCpp-${ADAPTIVECPP_TAG}.tar.gz" + curl -L "https://github.com/AdaptiveCpp/AdaptiveCpp/archive/refs/tags/${ADAPTIVECPP_TAG}.tar.gz" -o "${archive}" + + tar -xzf "${archive}" -C "${RUNNER_TEMP}" + extracted_dir="$(find "${RUNNER_TEMP}" -maxdepth 2 -type f -path '*/AdaptiveCpp-*/CMakeLists.txt' -print | head -n 1)" + rm -rf "${ACPP_SOURCE_DIR}" "${ACPP_BUILD_DIR}" + mv "$(dirname "${extracted_dir}")" "${ACPP_SOURCE_DIR}" + mkdir -p "${ACPP_BUILD_DIR}" + + cmake -S "${ACPP_SOURCE_DIR}" -B "${ACPP_BUILD_DIR}" -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="${ACPP_INSTALL_DIR}" \ + -DCMAKE_C_COMPILER=/usr/bin/clang-18 \ + -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 \ + -DLLVM_DIR=/usr/lib/llvm-18/lib/cmake/llvm \ + -DClang_DIR=/usr/lib/llvm-18/lib/cmake/clang \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + cmake --build "${ACPP_BUILD_DIR}" --target install --parallel + + - name: Configure Linux toolchain environment + if: ${{ runner.os == 'Linux' && inputs.phase == 'build' }} + shell: bash + run: | + { + echo "ITLABAI_CC=/usr/bin/clang-18" + echo "ITLABAI_CXX=/usr/bin/clang++-18" + echo "ITLABAI_CMAKE_PREFIX_PATH=${RUNNER_TEMP}/adaptivecpp-install" + echo "ITLABAI_OPENMP_ROOT=/usr/lib/llvm-18" + } >> "${GITHUB_ENV}" + echo "${RUNNER_TEMP}/adaptivecpp-install/bin" >> "${GITHUB_PATH}" + + - name: Locate Windows LLVM toolchain + if: ${{ runner.os == 'Windows' }} + shell: pwsh + run: | + function Get-ShortPath($Path) { + $resolvedPath = (Resolve-Path $Path).Path + $shortPath = & $env:ComSpec /d /c "for %I in (`"$resolvedPath`") do @echo %~sI" + if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($shortPath)) { + throw "Failed to resolve short path for $resolvedPath" + } + return $shortPath.Trim() + } + + $clangCl = Get-Command clang-cl.exe -ErrorAction SilentlyContinue + if (-not $clangCl -and $env:ProgramFiles) { + $programFilesClang = Join-Path $env:ProgramFiles 'LLVM/bin/clang-cl.exe' + if (Test-Path $programFilesClang) { + $clangCl = Get-Item $programFilesClang + } + } + if (-not $clangCl -and $env:VCToolsInstallDir) { + $vcToolsRoot = Resolve-Path (Join-Path $env:VCToolsInstallDir '../..') + $vsClang = Join-Path $vcToolsRoot 'Llvm/x64/bin/clang-cl.exe' + if (Test-Path $vsClang) { + $clangCl = Get-Item $vsClang + } + } + if (-not $clangCl) { + throw 'clang-cl.exe was not found. Install the Visual Studio LLVM/Clang toolset on the Windows runner.' + } + + $clangClPath = $clangCl.Source + if (-not $clangClPath) { + $clangClPath = $clangCl.FullName + } + $clangBin = Split-Path $clangClPath -Parent + $clangClShortPath = Get-ShortPath $clangClPath + + "ITLABAI_CC=$clangClShortPath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + "ITLABAI_CXX=$clangClShortPath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + "ITLABAI_ACPP_CPU_CXX=$clangClShortPath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + "$clangBin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + + - name: Configure Windows toolchain environment + if: ${{ runner.os == 'Windows' && inputs.phase == 'build' }} + shell: pwsh + run: | + "ITLABAI_CMAKE_PREFIX_PATH=$env:RUNNER_TEMP\adaptivecpp-install" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + "$env:RUNNER_TEMP\adaptivecpp-install\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + + - name: Install Windows Ninja + if: ${{ runner.os == 'Windows' && (inputs.phase == 'build' || inputs.cache-hit != 'true') }} + shell: pwsh + run: | + if (-not (Get-Command ninja.exe -ErrorAction SilentlyContinue)) { + choco install ninja --yes --no-progress + } + + - name: Build Windows AdaptiveCpp + if: ${{ runner.os == 'Windows' && inputs.phase == 'prepare' && inputs.cache-hit != 'true' }} + shell: pwsh + env: + ACPP_INSTALL_DIR: ${{ runner.temp }}\adaptivecpp-install + ACPP_SOURCE_DIR: ${{ runner.temp }}\AdaptiveCpp + ACPP_BUILD_DIR: ${{ runner.temp }}\AdaptiveCpp-build + ACPP_ARCHIVE_DIR: ${{ runner.temp }}\archives + run: | + New-Item -ItemType Directory -Force -Path $env:ACPP_ARCHIVE_DIR,$env:ACPP_BUILD_DIR,$env:ACPP_INSTALL_DIR | Out-Null + $archive = Join-Path $env:ACPP_ARCHIVE_DIR "AdaptiveCpp-$env:ADAPTIVECPP_TAG.tar.gz" + Invoke-WebRequest "https://github.com/AdaptiveCpp/AdaptiveCpp/archive/refs/tags/$env:ADAPTIVECPP_TAG.tar.gz" -OutFile $archive + + Remove-Item $env:ACPP_SOURCE_DIR,$env:ACPP_BUILD_DIR -Recurse -Force -ErrorAction SilentlyContinue + tar -xzf $archive -C $env:RUNNER_TEMP + $extractedAcpp = Get-ChildItem $env:RUNNER_TEMP -Directory | Where-Object { $_.Name -like 'AdaptiveCpp-*' } | Select-Object -First 1 + Move-Item $extractedAcpp.FullName $env:ACPP_SOURCE_DIR + New-Item -ItemType Directory -Force -Path $env:ACPP_BUILD_DIR | Out-Null + + cmake -S $env:ACPP_SOURCE_DIR -B $env:ACPP_BUILD_DIR -G Ninja ` + "-DCMAKE_BUILD_TYPE=Release" ` + "-DCMAKE_INSTALL_PREFIX=$env:ACPP_INSTALL_DIR" ` + "-DCMAKE_C_COMPILER=$env:ITLABAI_CC" ` + "-DCMAKE_CXX_COMPILER=$env:ITLABAI_CXX" ` + -DCMAKE_C_COMPILER_LAUNCHER=ccache ` + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + + cmake --build $env:ACPP_BUILD_DIR --target install --parallel + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } diff --git a/.github/workflows/sycl-ci.yml b/.github/workflows/sycl-ci.yml new file mode 100644 index 000000000..9bcb5e39e --- /dev/null +++ b/.github/workflows/sycl-ci.yml @@ -0,0 +1,151 @@ +name: SYCL CI + +on: + pull_request: + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + ADAPTIVECPP_TAG: v25.10.0 + ADAPTIVECPP_CACHE_VERSION: v4 + ACPP_TARGETS: omp.library-only + +jobs: + prepare-sycl-toolchain: + name: prepare ${{ matrix.platform }} + runs-on: ${{ matrix.runner }} + timeout-minutes: 180 + strategy: + fail-fast: true + matrix: + platform: + - linux-x86_64 + - linux-arm64 + - windows-x86_64 + include: + - platform: linux-x86_64 + runner: ubuntu-latest + - platform: linux-arm64 + runner: ubuntu-24.04-arm + - platform: windows-x86_64 + runner: windows-2022 + + steps: + - uses: actions/checkout@v4 + + - name: Setup ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ccache-${{ github.job }}-${{ matrix.platform }} + max-size: 4G + + - name: Restore or save AdaptiveCpp toolchain cache + id: sycl-toolchain-cache + uses: actions/cache@v4 + with: + path: | + ${{ runner.temp }}/AdaptiveCpp + ${{ runner.temp }}/AdaptiveCpp-build + ${{ runner.temp }}/adaptivecpp-install + ${{ runner.temp }}/archives + key: sycl-toolchain-${{ matrix.platform }}-${{ env.ADAPTIVECPP_TAG }}-${{ env.ADAPTIVECPP_CACHE_VERSION }} + + - name: Prepare SYCL toolchain + uses: ./.github/actions/setup-sycl-toolchain + with: + phase: prepare + cache-hit: ${{ steps.sycl-toolchain-cache.outputs.cache-hit }} + + build-sycl: + name: ${{ matrix.platform }} ${{ matrix.build_type }} + needs: prepare-sycl-toolchain + runs-on: ${{ matrix.runner }} + timeout-minutes: 180 + strategy: + fail-fast: true + matrix: + platform: + - linux-x86_64 + - linux-arm64 + - macos-arm64 + - windows-x86_64 + build_type: + - Debug + - Release + include: + - platform: linux-x86_64 + runner: ubuntu-latest + - platform: linux-arm64 + runner: ubuntu-24.04-arm + - platform: macos-arm64 + runner: macos-15 + - platform: windows-x86_64 + runner: windows-2022 + + steps: + - uses: actions/checkout@v4 + with: + submodules: true + + - name: Setup ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ccache-${{ github.job }}-${{ matrix.platform }}-${{ matrix.build_type }} + max-size: 4G + + - name: Restore AdaptiveCpp toolchain cache + if: runner.os != 'macOS' + uses: actions/cache/restore@v4 + with: + path: | + ${{ runner.temp }}/AdaptiveCpp + ${{ runner.temp }}/AdaptiveCpp-build + ${{ runner.temp }}/adaptivecpp-install + ${{ runner.temp }}/archives + key: sycl-toolchain-${{ matrix.platform }}-${{ env.ADAPTIVECPP_TAG }}-${{ env.ADAPTIVECPP_CACHE_VERSION }} + fail-on-cache-miss: true + + - name: Setup SYCL toolchain + uses: ./.github/actions/setup-sycl-toolchain + with: + phase: build + + - name: Configure + if: runner.os != 'Windows' + shell: bash + run: | + cmake -S . -B "build/${{ matrix.build_type }}" -G Ninja \ + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ + -DCMAKE_C_COMPILER="${ITLABAI_CC}" \ + -DCMAKE_CXX_COMPILER="${ITLABAI_CXX}" \ + -DCMAKE_PREFIX_PATH="${ITLABAI_CMAKE_PREFIX_PATH}" \ + -DOpenMP_ROOT="${ITLABAI_OPENMP_ROOT}" \ + -DITLABAI_ENABLE_SYCL=ON \ + -DACPP_TARGETS="${ACPP_TARGETS}" \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + + - name: Configure + if: runner.os == 'Windows' + shell: pwsh + run: | + cmake -S . -B "build/${{ matrix.build_type }}" -G Ninja ` + "-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}" ` + "-DCMAKE_C_COMPILER=$env:ITLABAI_CC" ` + "-DCMAKE_CXX_COMPILER=$env:ITLABAI_CXX" ` + "-DCMAKE_PREFIX_PATH=$env:ITLABAI_CMAKE_PREFIX_PATH" ` + "-DITLABAI_ENABLE_SYCL=ON" ` + "-DACPP_TARGETS=$env:ACPP_TARGETS" ` + "-DACPP_CPU_CXX=$env:ITLABAI_ACPP_CPU_CXX" ` + -DCMAKE_C_COMPILER_LAUNCHER=ccache ` + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + + - name: Build + run: cmake --build "build/${{ matrix.build_type }}" --target SYCL_Example run_test --parallel + + - name: Test + run: ctest --test-dir "build/${{ matrix.build_type }}" --output-on-failure -R '^(UnitTests|SYCL\.Example)$' diff --git a/CMakeLists.txt b/CMakeLists.txt index 6cb6861de..707e9fbcc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.20) project(ITLabAI) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE) +option(ITLABAI_ENABLE_SYCL "Build SYCL example and helper targets" OFF) option(ENABLE_STATISTIC_TENSORS "Enable statistic tensors" OFF) @@ -83,4 +84,7 @@ endforeach() add_subdirectory(app) add_subdirectory(include) add_subdirectory(src) +if(ITLABAI_ENABLE_SYCL) + add_subdirectory(app/SYCL) +endif() add_subdirectory(test) diff --git a/app/Graph/graph_build.cpp b/app/Graph/graph_build.cpp index 53389bc1d..e7512b42e 100644 --- a/app/Graph/graph_build.cpp +++ b/app/Graph/graph_build.cpp @@ -40,6 +40,8 @@ int main(int argc, char* argv[]) { options.par_backend = ParBackend::kOmp; } else if (backend_str == "kokkos") { options.par_backend = ParBackend::kKokkos; + } else if (backend_str == "sycl") { + options.par_backend = ParBackend::kSycl; } else { std::cerr << "Unknown parallel backend: " << backend_str << ". Using default (Threads)." << '\n'; diff --git a/app/SYCL/CMakeLists.txt b/app/SYCL/CMakeLists.txt new file mode 100644 index 000000000..de3de8048 --- /dev/null +++ b/app/SYCL/CMakeLists.txt @@ -0,0 +1,25 @@ +find_package(AdaptiveCpp CONFIG REQUIRED) + +add_executable(SYCL_Example + sycl_example.cpp +) +target_link_libraries(SYCL_Example PRIVATE layers_lib AdaptiveCpp::acpp-rt) + +if(WIN32) + target_sources(SYCL_Example PRIVATE sycl_kernel.cpp) + target_compile_definitions(SYCL_Example PRIVATE _USE_MATH_DEFINES ITLABAI_HAS_SYCL) +else() + add_library(SYCL_Example_kernel OBJECT sycl_kernel.cpp) + target_compile_definitions(SYCL_Example_kernel PRIVATE ITLABAI_HAS_SYCL) + target_link_libraries(SYCL_Example_kernel PRIVATE AdaptiveCpp::acpp-rt TBB_unified Kokkos_imported) + add_sycl_to_target(TARGET SYCL_Example_kernel SOURCES + sycl_kernel.cpp + ) + target_sources(SYCL_Example PRIVATE $) +endif() + +add_test(NAME SYCL.Example COMMAND SYCL_Example) +set_tests_properties(SYCL.Example PROPERTIES + LABELS "sycl;smoke" + TIMEOUT 60 +) diff --git a/app/SYCL/sycl_example.cpp b/app/SYCL/sycl_example.cpp new file mode 100644 index 000000000..2a3995831 --- /dev/null +++ b/app/SYCL/sycl_example.cpp @@ -0,0 +1,65 @@ +#include +#include +#include +#include + +#include "graph/runtime_options.hpp" +#include "layers/EWLayer.hpp" +#include "layers/Tensor.hpp" + +namespace { + +bool almost_equal(float lhs, float rhs) { + return std::fabs(lhs - rhs) < 1.0e-6F; +} + +} // namespace + +std::string sycl_device_name(); + +int main() { + try { + using namespace it_lab_ai; + + std::vector input_values = {-2.0F, -1.0F, 0.0F, 1.0F, 2.0F}; + Tensor input = make_tensor(input_values); + std::vector inputs = {input}; + std::vector outputs(1); + + EWLayer relu("relu"); + RuntimeOptions sycl_options; + sycl_options.par_backend = ParBackend::kSycl; + relu.run(inputs, outputs, sycl_options); + + const std::vector& relu_output = *outputs.front().as(); + const std::vector expected_relu = {0.0F, 0.0F, 0.0F, 1.0F, 2.0F}; + + if (relu_output != expected_relu) { + std::cerr << "ITLabAI EWLayer produced an unexpected result" << '\n'; + return 1; + } + + const std::size_t count = relu_output.size(); + std::cout << "SYCL device: " << sycl_device_name() << '\n'; + + EWLayer linear("linear", 2.0F, 1.0F); + std::vector sycl_inputs = {outputs.front()}; + std::vector sycl_outputs(1); + linear.run(sycl_inputs, sycl_outputs, sycl_options); + + const std::vector expected_sycl = {1.0F, 1.0F, 1.0F, 3.0F, 5.0F}; + const std::vector& sycl_output = *sycl_outputs.front().as(); + for (std::size_t i = 0; i < count; ++i) { + if (!almost_equal(sycl_output[i], expected_sycl[i])) { + std::cerr << "SYCL kernel verification failed at index " << i << '\n'; + return 1; + } + } + + std::cout << "SYCL example completed successfully" << '\n'; + return 0; + } catch (const std::exception& exception) { + std::cerr << "Error: " << exception.what() << '\n'; + return 1; + } +} diff --git a/app/SYCL/sycl_kernel.cpp b/app/SYCL/sycl_kernel.cpp new file mode 100644 index 000000000..4e0987309 --- /dev/null +++ b/app/SYCL/sycl_kernel.cpp @@ -0,0 +1,7 @@ +#include + +#include "parallel/parallel.hpp" + +std::string sycl_device_name() { + return it_lab_ai::parallel::sycl_device_name(); +} diff --git a/include/parallel/backends.hpp b/include/parallel/backends.hpp index 6c5bcd996..35094df98 100644 --- a/include/parallel/backends.hpp +++ b/include/parallel/backends.hpp @@ -9,9 +9,16 @@ #include #include #include +#include +#include #include +#include #include +#ifdef ITLABAI_HAS_SYCL +# include +#endif + namespace it_lab_ai { namespace parallel { @@ -20,7 +27,8 @@ enum class Backend : std::uint8_t { kThreads = 1, kTbb = 2, kOmp = 3, - kKokkos = 4 + kKokkos = 4, + kSycl = 5 }; struct Options { @@ -149,5 +157,37 @@ inline void impl_kokkos(std::size_t count, Kokkos::fence(); } +#ifdef ITLABAI_HAS_SYCL +inline sycl::queue& sycl_queue() { + static auto* queue = new sycl::queue{sycl::default_selector_v}; + return *queue; +} + +inline std::string sycl_device_name() { + return sycl_queue().get_device().get_info(); +} + +template +inline void impl_sycl(std::size_t count, Func&& func, const Options&) { + if (count == 0) { + return; + } + + auto& queue = sycl_queue(); + queue.parallel_for(sycl::range<1>(count), + [func = std::forward(func)](sycl::id<1> index) { + func(static_cast(index[0])); + }); + queue.wait_and_throw(); +} +#else +template +[[noreturn]] inline void impl_sycl(std::size_t, const Func&, const Options&) { + throw std::runtime_error( + "SYCL parallel backend was requested, but this target was not built with " + "ITLABAI_HAS_SYCL"); +} +#endif + } // namespace parallel } // namespace it_lab_ai diff --git a/include/parallel/parallel.hpp b/include/parallel/parallel.hpp index 66851fd28..9d0a427ca 100644 --- a/include/parallel/parallel.hpp +++ b/include/parallel/parallel.hpp @@ -30,7 +30,7 @@ inline Backend select_backend(const Options& opt, std::size_t n) { if (opt.backend == Backend::kSeq || opt.backend == Backend::kThreads || opt.backend == Backend::kTbb || opt.backend == Backend::kOmp || - opt.backend == Backend::kKokkos) { + opt.backend == Backend::kKokkos || opt.backend == Backend::kSycl) { return opt.backend; } @@ -62,6 +62,9 @@ inline void parallel_for(std::size_t count, Func&& func, case Backend::kKokkos: impl_kokkos(count, std::forward(func), opt); break; + case Backend::kSycl: + impl_sycl(count, std::forward(func), opt); + break; } } diff --git a/src/layers/CMakeLists.txt b/src/layers/CMakeLists.txt index 35382404f..61a118c9a 100644 --- a/src/layers/CMakeLists.txt +++ b/src/layers/CMakeLists.txt @@ -5,3 +5,19 @@ target_link_libraries(layers_lib PUBLIC TBB_unified) target_link_libraries(layers_lib PUBLIC OpenMP::OpenMP_CXX) target_link_libraries(layers_lib PUBLIC dnnl) target_link_libraries(layers_lib PUBLIC Kokkos_imported) + +if(ITLABAI_ENABLE_SYCL) + find_package(AdaptiveCpp CONFIG REQUIRED) + target_compile_definitions(layers_lib PUBLIC ITLABAI_HAS_SYCL) + if(WIN32) + target_compile_definitions(layers_lib PUBLIC + _ENABLE_EXTENDED_ALIGNED_STORAGE + _USE_MATH_DEFINES + __ACPP_ENABLE_OMPHOST_TARGET__ + ) + endif() + target_link_libraries(layers_lib PUBLIC AdaptiveCpp::acpp-rt) + if(NOT WIN32) + add_sycl_to_target(TARGET layers_lib SOURCES ${layers_src}) + endif() +endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 142773ef3..e02131028 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -10,6 +10,15 @@ target_link_libraries(run_test PUBLIC reader_lib) target_link_libraries(run_test PUBLIC graph_lib) target_link_libraries(run_test PUBLIC graphT_lib) +if(ITLABAI_ENABLE_SYCL) + find_package(AdaptiveCpp CONFIG REQUIRED) + if(WIN32 AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") + target_compile_options(run_test PRIVATE /EHsc) + endif() + if(NOT WIN32) + add_sycl_to_target(TARGET run_test SOURCES ${TEST_SRC_FILES}) + endif() +endif() target_include_directories(run_test PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") target_include_directories(run_test PRIVATE "${CMAKE_SOURCE_DIR}/app/ReaderImage") diff --git a/test/benchmarking/test_layers_time.cpp b/test/benchmarking/test_layers_time.cpp index f86f250b9..519d9cfb2 100644 --- a/test/benchmarking/test_layers_time.cpp +++ b/test/benchmarking/test_layers_time.cpp @@ -44,6 +44,15 @@ TEST(pooling_test, is_pooling_tbb_ok) { double count2 = elapsed_time(test_func, p2, input, output, options_tbb); std::cout << count1 << " vs. " << count2 << " (parallel)\n"; + +#ifdef ITLABAI_HAS_SYCL + RuntimeOptions options_sycl; + options_sycl.par_backend = ParBackend::kSycl; + PoolingLayer p3(Shape({2, 2}), "max"); + double count3 = elapsed_time(test_func, p3, input, output, + options_sycl); + std::cout << count1 << " vs. " << count3 << " (sycl)\n"; +#endif } TEST(conv_test, is_conv_stl_ok) { @@ -79,4 +88,13 @@ TEST(conv_test, is_conv_stl_ok) { double count2 = elapsed_time(test_func, p2, input, output, options_stl); std::cout << count1 << " vs. " << count2 << " (parallel)\n"; + +#ifdef ITLABAI_HAS_SYCL + RuntimeOptions options_sycl; + options_sycl.par_backend = ParBackend::kSycl; + ConvolutionalLayer p3(1, 1, 2, kernel); + double count3 = elapsed_time(test_func, p3, input, output, + options_sycl); + std::cout << count1 << " vs. " << count3 << " (sycl)\n"; +#endif } diff --git a/test/parallel/test_sycl_parallel.cpp b/test/parallel/test_sycl_parallel.cpp new file mode 100644 index 000000000..196069e37 --- /dev/null +++ b/test/parallel/test_sycl_parallel.cpp @@ -0,0 +1,34 @@ +#include "gtest/gtest.h" +#include "parallel/parallel.hpp" + +#ifdef ITLABAI_HAS_SYCL + +#include + +namespace it_lab_ai { +namespace { + +TEST(sycl_parallel, parallel_for_writes_expected_values) { + constexpr std::size_t kSize = 1024; + std::vector values(kSize, 0); + + parallel::parallel_for( + kSize, + [&](std::size_t i) { + values[i] = static_cast(i * 2); + }, + parallel::Backend::kSycl); + + for (std::size_t i = 0; i < values.size(); ++i) { + EXPECT_EQ(values[i], static_cast(i * 2)); + } +} + +TEST(sycl_parallel, reports_selected_device) { + EXPECT_FALSE(parallel::sycl_device_name().empty()); +} + +} // namespace +} // namespace it_lab_ai + +#endif diff --git a/test/parallel_backends.hpp b/test/parallel_backends.hpp new file mode 100644 index 000000000..1f4e885c0 --- /dev/null +++ b/test/parallel_backends.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include +#include + +#include "graph/runtime_options.hpp" + +namespace it_lab_ai { +namespace test_support { + +inline std::vector all_parallel_backends() { + std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, + ParBackend::kTbb, ParBackend::kOmp, + ParBackend::kKokkos}; +#ifdef ITLABAI_HAS_SYCL + backends.push_back(ParBackend::kSycl); +#endif + return backends; +} + +inline RuntimeOptions make_options(ParBackend backend) { + RuntimeOptions options; + options.backend = Backend::kNaive; + options.par_backend = backend; + return options; +} + +inline std::vector all_parallel_options() { + std::vector options; + for (ParBackend backend : all_parallel_backends()) { + options.push_back(make_options(backend)); + } + return options; +} + +inline std::string parallel_backend_name(ParBackend backend) { + switch (backend) { + case ParBackend::kTbb: + return "TBB"; + case ParBackend::kThreads: + return "STL"; + case ParBackend::kOmp: + return "OMP"; + case ParBackend::kKokkos: + return "Kokkos"; + case ParBackend::kSycl: + return "SYCL"; + case ParBackend::kSeq: + return "Seq"; + } + return "Unknown"; +} + +} // namespace test_support +} // namespace it_lab_ai diff --git a/test/single_layer/test_convlayer.cpp b/test/single_layer/test_convlayer.cpp index fb9a16e85..2d78553da 100644 --- a/test/single_layer/test_convlayer.cpp +++ b/test/single_layer/test_convlayer.cpp @@ -2,6 +2,7 @@ #include "fixture.hpp" #include "layers/ConvLayer.hpp" +#include "parallel_backends.hpp" using namespace it_lab_ai; @@ -1282,28 +1283,14 @@ INSTANTIATE_TEST_SUITE_P( .output_shape = {1, 3, 2, 2}, .expected_output = std::vector(12, 5.0f), .description = "2D_Kernel_Stride_2"}), - ::testing::Values(ConvTestFixture::setTBBOptions(), - ConvTestFixture::setOmpOptions(), - ConvTestFixture::setSeqOptions(), - ConvTestFixture::setSTLOptions(), - ConvTestFixture::setKokkosOptions())), + ::testing::ValuesIn(test_support::all_parallel_options())), [](const ::testing::TestParamInfo< std::tuple>& info) { const auto& params = std::get<0>(info.param); const auto& options = std::get<1>(info.param); std::string name = params.description + "_"; - if (options.par_backend == ParBackend::kTbb) { - name += "TBB"; - } else if (options.par_backend == ParBackend::kOmp) { - name += "OMP"; - } else if (options.par_backend == ParBackend::kThreads) { - name += "STL"; - } else if (options.par_backend == ParBackend::kKokkos) { - name += "Kokkos"; - } else { - name += "Seq"; - } + name += test_support::parallel_backend_name(options.par_backend); std::replace(name.begin(), name.end(), ' ', '_'); std::replace(name.begin(), name.end(), '-', '_'); diff --git a/test/single_layer/test_ewlayer.cpp b/test/single_layer/test_ewlayer.cpp index dc8b40fb5..e3dd0ce99 100644 --- a/test/single_layer/test_ewlayer.cpp +++ b/test/single_layer/test_ewlayer.cpp @@ -6,6 +6,7 @@ #include "fixture.hpp" #include "gtest/gtest.h" #include "layers/EWLayer.hpp" +#include "parallel_backends.hpp" using namespace it_lab_ai; @@ -229,8 +230,7 @@ TEST_F(EWLayerTest_F, parallel_for_ew) { std::vector in{input}; std::vector out{output}; - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp}; + auto backends = test_support::all_parallel_backends(); for (auto backend : backends) { auto options = createOptionsWithBackend(backend); @@ -256,11 +256,10 @@ TEST(ewlayer, parallel_for_ew_sigmoid_compact) { std::vector in{input}; std::vector out{output}; - std::vector> backends = { - {ParBackend::kSeq, "Sequential"}, - {ParBackend::kThreads, "Threads"}, - {ParBackend::kTbb, "TBB"}, - {ParBackend::kOmp, "OpenMP"}}; + std::vector> backends; + for (auto backend : test_support::all_parallel_backends()) { + backends.emplace_back(backend, test_support::parallel_backend_name(backend)); + } std::vector reference_result; bool first = true; @@ -354,6 +353,19 @@ TEST(ewlayer, parallel_for_direct) { for (int i = 0; i < SIZE * SIZE; i++) { ASSERT_EQ(result[i], 2); } + +#ifdef ITLABAI_HAS_SYCL + start = std::chrono::high_resolution_clock::now(); + parallel::parallel_for(SIZE * SIZE, [&](std::size_t i) { + result[i] = matrix1[i] + matrix2[i]; + }, ParBackend::kSycl); + end = std::chrono::high_resolution_clock::now(); + total_duration = + std::chrono::duration_cast(end - start); + for (int i = 0; i < SIZE * SIZE; i++) { + ASSERT_EQ(result[i], 2); + } +#endif } TEST(ewlayer, parallel_for_notmatrix) { @@ -410,6 +422,19 @@ TEST(ewlayer, parallel_for_notmatrix) { for (int i = 0; i < SIZE * SIZE; i++) { ASSERT_EQ(result[i], 2); } + +#ifdef ITLABAI_HAS_SYCL + start = std::chrono::high_resolution_clock::now(); + parallel::parallel_for(SIZE * SIZE, [&](std::size_t i) { + result[i] = matrix1[i] + 1; + }, ParBackend::kSycl); + end = std::chrono::high_resolution_clock::now(); + total_duration = + std::chrono::duration_cast(end - start); + for (int i = 0; i < SIZE * SIZE; i++) { + ASSERT_EQ(result[i], 2); + } +#endif } struct EWLayerTestParams { @@ -503,28 +528,14 @@ INSTANTIATE_TEST_SUITE_P( {9.0f, 0.0f, 7.0f, 0.0f, 0.0f, 4.0f, 0.0f, 2.0f, 2.0f, 0.0f, 4.0f, 0.0f, 6.0f, 0.0f, 8.0f, 0.0f}, "ReLU_2D_Mixed"}), - ::testing::Values(BaseTestFixture::setTBBOptions(), - BaseTestFixture::setSeqOptions(), - BaseTestFixture::setOmpOptions(), - BaseTestFixture::setKokkosOptions(), - BaseTestFixture::setSTLOptions())), + ::testing::ValuesIn(test_support::all_parallel_options())), [](const ::testing::TestParamInfo< std::tuple>& info) { const auto& params = std::get<0>(info.param); const auto& options = std::get<1>(info.param); std::string name = params.description + "_"; - if (options.par_backend == ParBackend::kTbb) { - name += "TBB"; - } else if (options.par_backend == ParBackend::kThreads) { - name += "STL"; - } else if (options.par_backend == ParBackend::kOmp) { - name += "OMP"; - } else if (options.par_backend == ParBackend::kKokkos) { - name += "Kokkos"; - } else { - name += "Seq"; - } + name += test_support::parallel_backend_name(options.par_backend); std::replace(name.begin(), name.end(), ' ', '_'); std::replace(name.begin(), name.end(), '-', '_'); diff --git a/test/single_layer/test_poolinglayer.cpp b/test/single_layer/test_poolinglayer.cpp index 409802af5..151b26c60 100644 --- a/test/single_layer/test_poolinglayer.cpp +++ b/test/single_layer/test_poolinglayer.cpp @@ -4,6 +4,7 @@ #include "fixture.hpp" #include "gtest/gtest.h" #include "layers/PoolingLayer.hpp" +#include "parallel_backends.hpp" using namespace it_lab_ai; @@ -664,28 +665,14 @@ INSTANTIATE_TEST_SUITE_P( "max", {9.0f, 8.0f, 8.0f, 9.0f}, "2D_Max_Dilation2"}), - ::testing::Values(BaseTestFixture::setTBBOptions(), - BaseTestFixture::setOmpOptions(), - BaseTestFixture::setSeqOptions(), - BaseTestFixture::setSTLOptions(), - BaseTestFixture::setKokkosOptions())), + ::testing::ValuesIn(test_support::all_parallel_options())), [](const ::testing::TestParamInfo< std::tuple>& info) { const auto& params = std::get<0>(info.param); const auto& options = std::get<1>(info.param); std::string name = params.description + "_"; - if (options.par_backend == ParBackend::kTbb) { - name += "TBB"; - } else if (options.par_backend == ParBackend::kOmp) { - name += "OMP"; - } else if (options.par_backend == ParBackend::kThreads) { - name += "STL"; - } else if (options.par_backend == ParBackend::kKokkos) { - name += "Kokkos"; - } else { - name += "Seq"; - } + name += test_support::parallel_backend_name(options.par_backend); std::replace(name.begin(), name.end(), ' ', '_'); std::replace(name.begin(), name.end(), '-', '_'); diff --git a/test/single_layer_parall_version/test_binaryoplayer_parall.cpp b/test/single_layer_parall_version/test_binaryoplayer_parall.cpp index 84fe05e59..fb36edcf8 100644 --- a/test/single_layer_parall_version/test_binaryoplayer_parall.cpp +++ b/test/single_layer_parall_version/test_binaryoplayer_parall.cpp @@ -6,6 +6,7 @@ #include "gtest/gtest.h" #include "layers/BinaryOpLayer.hpp" +#include "parallel_backends.hpp" #define ENABLE_TIMING_OUTPUT 1 @@ -64,9 +65,7 @@ static Tensor RunBinary(BinaryOpLayer& layer, const Tensor& a, const Tensor& b, static void RunAllBackendsAndCompare(BinaryOpLayer& layer, const Tensor& a, const Tensor& b, const std::string& label, float tolerance = 1e-5f) { - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); Tensor baseline = RunBinary(layer, a, b, ParBackend::kSeq); diff --git a/test/single_layer_parall_version/test_convlayer_parall.cpp b/test/single_layer_parall_version/test_convlayer_parall.cpp index 7b4759f71..e14839037 100644 --- a/test/single_layer_parall_version/test_convlayer_parall.cpp +++ b/test/single_layer_parall_version/test_convlayer_parall.cpp @@ -6,6 +6,7 @@ #include "gtest/gtest.h" #include "layers/ConvLayer.hpp" +#include "parallel_backends.hpp" #define ENABLE_TIMING_OUTPUT 1 @@ -37,9 +38,7 @@ TEST(convlayer_parall, parallel_conv_basic) { std::vector in{input}; std::vector out{output}; - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (auto backend : backends) { RuntimeOptions options; @@ -79,9 +78,7 @@ TEST(convlayer_parall, parallel_conv_stride2) { std::vector in{input}; std::vector out{output}; - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (auto backend : backends) { RuntimeOptions options; @@ -123,9 +120,7 @@ TEST(convlayer_parall, parallel_depthwise_conv) { std::vector in{input}; std::vector out{output}; - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (auto backend : backends) { RuntimeOptions options; @@ -169,9 +164,7 @@ TEST(convlayer_parall, parallel_conv_with_bias) { std::vector in{input}; std::vector out{output}; - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (auto backend : backends) { RuntimeOptions options; @@ -213,9 +206,7 @@ TEST(convlayer_parall, parallel_conv_large_kernel) { std::vector in{input}; std::vector out{output}; - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (auto backend : backends) { RuntimeOptions options; @@ -255,9 +246,7 @@ TEST(convlayer_parall, parallel_conv_single_image) { std::vector in{input}; std::vector out{output}; - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (auto backend : backends) { RuntimeOptions options; diff --git a/test/single_layer_parall_version/test_ewlayer_parall.cpp b/test/single_layer_parall_version/test_ewlayer_parall.cpp index 7a6311841..590b93d46 100644 --- a/test/single_layer_parall_version/test_ewlayer_parall.cpp +++ b/test/single_layer_parall_version/test_ewlayer_parall.cpp @@ -6,6 +6,7 @@ #include "gtest/gtest.h" #include "layers/EWLayer.hpp" +#include "parallel_backends.hpp" #define ENABLE_TIMING_OUTPUT 1 @@ -26,9 +27,7 @@ TEST(ewlayer_parall, parallel_for_ew_relu) { std::vector in{input}; std::vector out{output}; - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (auto backend : backends) { RuntimeOptions options; @@ -55,9 +54,7 @@ TEST(ewlayer_parall, parallel_for_sigmoid) { std::vector in{input}; std::vector out{output}; - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (auto backend : backends) { RuntimeOptions options; @@ -84,9 +81,7 @@ TEST(ewlayer_parall, parallel_for_minus) { std::vector in{input}; std::vector out{output}; - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (auto backend : backends) { RuntimeOptions options; @@ -113,9 +108,7 @@ TEST(ewlayer_parall, parallel_for_linear) { std::vector in{input}; std::vector out{output}; - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (auto backend : backends) { RuntimeOptions options; @@ -205,6 +198,20 @@ TEST(ewlayer_parall, parallel_for_direct) { for (int i = 0; i < SIZE * SIZE; i++) { ASSERT_EQ(result[i], 2); } + +#ifdef ITLABAI_HAS_SYCL + start = std::chrono::high_resolution_clock::now(); + parallel::parallel_for(SIZE * SIZE, [&](std::size_t i) { + result[i] = matrix1[i] + matrix2[i]; + }, ParBackend::kSycl); + end = std::chrono::high_resolution_clock::now(); + total_duration = + std::chrono::duration_cast(end - start); + PRINT_TIMING(" time: " << total_duration.count() << " ms"); + for (int i = 0; i < SIZE * SIZE; i++) { + ASSERT_EQ(result[i], 2); + } +#endif } TEST(ewlayer_parall, parallel_for_notmatrix) { @@ -277,4 +284,18 @@ TEST(ewlayer_parall, parallel_for_notmatrix) { for (int i = 0; i < SIZE * SIZE; i++) { ASSERT_EQ(result[i], 2); } + +#ifdef ITLABAI_HAS_SYCL + start = std::chrono::high_resolution_clock::now(); + parallel::parallel_for(SIZE * SIZE, [&](std::size_t i) { + result[i] = matrix1[i] + 1; + }, ParBackend::kSycl); + end = std::chrono::high_resolution_clock::now(); + total_duration = + std::chrono::duration_cast(end - start); + PRINT_TIMING(" time: " << total_duration.count() << " ms"); + for (int i = 0; i < SIZE * SIZE; i++) { + ASSERT_EQ(result[i], 2); + } +#endif } diff --git a/test/single_layer_parall_version/test_poolinglayer_parall.cpp b/test/single_layer_parall_version/test_poolinglayer_parall.cpp index 4ea198fbb..312529cac 100644 --- a/test/single_layer_parall_version/test_poolinglayer_parall.cpp +++ b/test/single_layer_parall_version/test_poolinglayer_parall.cpp @@ -7,6 +7,7 @@ #include "gtest/gtest.h" #include "layers/PoolingLayer.hpp" +#include "parallel_backends.hpp" #define ENABLE_TIMING_OUTPUT 1 @@ -61,9 +62,7 @@ TEST(poolinglayer_parall, max_pooling_single_image_float) { PoolingLayer layer(Shape({2, 2}), {2, 2}, {0, 0, 0, 0}, {1, 1}, false, "max"); Tensor baseline = RunPooling(layer, input, ParBackend::kSeq); - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (auto backend : backends) { Tensor result = RunPooling(layer, input, backend); @@ -82,9 +81,7 @@ TEST(poolinglayer_parall, avg_pooling_single_image_float) { "average"); Tensor baseline = RunPooling(layer, input, ParBackend::kSeq); - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (auto backend : backends) { Tensor result = RunPooling(layer, input, backend); @@ -101,9 +98,7 @@ TEST(poolinglayer_parall, max_pooling_single_image_int) { PoolingLayer layer(Shape({2, 2}), {2, 2}, {0, 0, 0, 0}, {1, 1}, false, "max"); Tensor baseline = RunPooling(layer, input, ParBackend::kSeq); - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (auto backend : backends) { Tensor result = RunPooling(layer, input, backend); @@ -120,9 +115,7 @@ TEST(poolinglayer_parall, pooling_with_padding_and_stride) { "average"); Tensor baseline = RunPooling(layer, input, ParBackend::kSeq); - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (auto backend : backends) { Tensor result = RunPooling(layer, input, backend); @@ -141,9 +134,7 @@ TEST(poolinglayer_parall, pooling_with_dilation) { PoolingLayer layer(Shape({2, 2}), {1, 1}, {0, 0, 0, 0}, {2, 2}, false, "max"); Tensor baseline = RunPooling(layer, input, ParBackend::kSeq); - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (auto backend : backends) { Tensor result = RunPooling(layer, input, backend); @@ -153,9 +144,7 @@ TEST(poolinglayer_parall, pooling_with_dilation) { TEST(poolinglayer_parall, max_pooling_batch_scaling) { std::vector batch_sizes = {1, 16, 32, 64}; - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (size_t batch_size : batch_sizes) { Shape input_shape({batch_size, 16, 56, 56}); @@ -185,9 +174,7 @@ TEST(poolinglayer_parall, max_pooling_batch_scaling) { TEST(poolinglayer_parall, avg_pooling_batch_scaling) { std::vector batch_sizes = {1, 16, 32, 64}; - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (size_t batch_size : batch_sizes) { Shape input_shape({batch_size, 32, 28, 28}); @@ -217,9 +204,7 @@ TEST(poolinglayer_parall, avg_pooling_batch_scaling) { TEST(poolinglayer_parall, multichannel_max_pooling) { std::vector batch_sizes = {8, 32, 128}; - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (size_t batch_size : batch_sizes) { Shape input_shape({batch_size, 64, 14, 14}); @@ -255,9 +240,7 @@ TEST(poolinglayer_parall, multichannel_max_pooling) { TEST(poolinglayer_parall, large_kernel_pooling) { std::vector batch_sizes = {4, 16, 32}; - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); for (size_t batch_size : batch_sizes) { Shape input_shape({batch_size, 3, 224, 224}); diff --git a/test/single_layer_parall_version/test_reducelayer_parall.cpp b/test/single_layer_parall_version/test_reducelayer_parall.cpp index 423befacb..b2731d681 100644 --- a/test/single_layer_parall_version/test_reducelayer_parall.cpp +++ b/test/single_layer_parall_version/test_reducelayer_parall.cpp @@ -6,6 +6,7 @@ #include "gtest/gtest.h" #include "layers/ReduceLayer.hpp" +#include "parallel_backends.hpp" #define ENABLE_TIMING_OUTPUT 1 @@ -53,9 +54,7 @@ static Tensor RunReduce(ReduceLayer& layer, const Tensor& input, static void RunBackendsAndCompare(ReduceLayer& layer, const Tensor& input, const std::string& label, float tolerance = 1e-5f) { - std::vector backends = {ParBackend::kSeq, ParBackend::kThreads, - ParBackend::kTbb, ParBackend::kOmp, - ParBackend::kKokkos}; + auto backends = test_support::all_parallel_backends(); Tensor baseline = RunReduce(layer, input, ParBackend::kSeq); From d779a3df2cad843a491c0ad23e77541f535c2854 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Sat, 2 May 2026 10:05:46 +0200 Subject: [PATCH 2/9] Auto-enable SYCL when AdaptiveCpp is available --- .github/workflows/sycl-ci.yml | 2 -- CMakeLists.txt | 8 ++++++-- app/SYCL/CMakeLists.txt | 2 -- src/layers/CMakeLists.txt | 3 +-- test/CMakeLists.txt | 3 +-- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.github/workflows/sycl-ci.yml b/.github/workflows/sycl-ci.yml index 9bcb5e39e..47f1be621 100644 --- a/.github/workflows/sycl-ci.yml +++ b/.github/workflows/sycl-ci.yml @@ -123,7 +123,6 @@ jobs: -DCMAKE_CXX_COMPILER="${ITLABAI_CXX}" \ -DCMAKE_PREFIX_PATH="${ITLABAI_CMAKE_PREFIX_PATH}" \ -DOpenMP_ROOT="${ITLABAI_OPENMP_ROOT}" \ - -DITLABAI_ENABLE_SYCL=ON \ -DACPP_TARGETS="${ACPP_TARGETS}" \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache @@ -137,7 +136,6 @@ jobs: "-DCMAKE_C_COMPILER=$env:ITLABAI_CC" ` "-DCMAKE_CXX_COMPILER=$env:ITLABAI_CXX" ` "-DCMAKE_PREFIX_PATH=$env:ITLABAI_CMAKE_PREFIX_PATH" ` - "-DITLABAI_ENABLE_SYCL=ON" ` "-DACPP_TARGETS=$env:ACPP_TARGETS" ` "-DACPP_CPU_CXX=$env:ITLABAI_ACPP_CPU_CXX" ` -DCMAKE_C_COMPILER_LAUNCHER=ccache ` diff --git a/CMakeLists.txt b/CMakeLists.txt index 707e9fbcc..8e7886eae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,6 @@ cmake_minimum_required(VERSION 3.20) project(ITLabAI) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE) -option(ITLABAI_ENABLE_SYCL "Build SYCL example and helper targets" OFF) option(ENABLE_STATISTIC_TENSORS "Enable statistic tensors" OFF) @@ -41,6 +40,11 @@ include_directories("include") list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") +find_package(AdaptiveCpp CONFIG QUIET) +if(TARGET AdaptiveCpp::acpp-rt) + message(STATUS "AdaptiveCpp found - enabling SYCL parallel support") +endif() + add_subdirectory(3rdparty) include(cmake/opencv_config.cmake) @@ -84,7 +88,7 @@ endforeach() add_subdirectory(app) add_subdirectory(include) add_subdirectory(src) -if(ITLABAI_ENABLE_SYCL) +if(TARGET AdaptiveCpp::acpp-rt) add_subdirectory(app/SYCL) endif() add_subdirectory(test) diff --git a/app/SYCL/CMakeLists.txt b/app/SYCL/CMakeLists.txt index de3de8048..a10b1cfb9 100644 --- a/app/SYCL/CMakeLists.txt +++ b/app/SYCL/CMakeLists.txt @@ -1,5 +1,3 @@ -find_package(AdaptiveCpp CONFIG REQUIRED) - add_executable(SYCL_Example sycl_example.cpp ) diff --git a/src/layers/CMakeLists.txt b/src/layers/CMakeLists.txt index 61a118c9a..a14ee4a6e 100644 --- a/src/layers/CMakeLists.txt +++ b/src/layers/CMakeLists.txt @@ -6,8 +6,7 @@ target_link_libraries(layers_lib PUBLIC OpenMP::OpenMP_CXX) target_link_libraries(layers_lib PUBLIC dnnl) target_link_libraries(layers_lib PUBLIC Kokkos_imported) -if(ITLABAI_ENABLE_SYCL) - find_package(AdaptiveCpp CONFIG REQUIRED) +if(TARGET AdaptiveCpp::acpp-rt) target_compile_definitions(layers_lib PUBLIC ITLABAI_HAS_SYCL) if(WIN32) target_compile_definitions(layers_lib PUBLIC diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e02131028..8bb353f68 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -10,8 +10,7 @@ target_link_libraries(run_test PUBLIC reader_lib) target_link_libraries(run_test PUBLIC graph_lib) target_link_libraries(run_test PUBLIC graphT_lib) -if(ITLABAI_ENABLE_SYCL) - find_package(AdaptiveCpp CONFIG REQUIRED) +if(TARGET AdaptiveCpp::acpp-rt) if(WIN32 AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") target_compile_options(run_test PRIVATE /EHsc) endif() From 636510009815b8cb66d5161521e62c00bd9b45f1 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Sat, 2 May 2026 11:44:43 +0200 Subject: [PATCH 3/9] Fix Windows SYCL OpenCV build with clang-cl --- cmake/opencv_config.cmake | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmake/opencv_config.cmake b/cmake/opencv_config.cmake index b5d20bc69..bc33c9cff 100644 --- a/cmake/opencv_config.cmake +++ b/cmake/opencv_config.cmake @@ -1,6 +1,11 @@ set(OPENCV_BUILD_DIR "${CMAKE_BINARY_DIR}/3rdparty/opencv_build") file(MAKE_DIRECTORY "${OPENCV_BUILD_DIR}") +set(OPENCV_SYCL_TOOLCHAIN_ARGS) +if(TARGET AdaptiveCpp::acpp-rt AND MSVC AND CMAKE_CXX_COMPILER_ID MATCHES "Clang") + list(APPEND OPENCV_SYCL_TOOLCHAIN_ARGS -DWITH_WEBP=OFF) +endif() + execute_process( COMMAND ${CMAKE_COMMAND} -S "${CMAKE_SOURCE_DIR}/3rdparty/opencv" @@ -14,6 +19,7 @@ execute_process( -DBUILD_TESTS=OFF -DBUILD_opencv_apps=OFF -DBUILD_JAVA=OFF + ${OPENCV_SYCL_TOOLCHAIN_ARGS} WORKING_DIRECTORY "${OPENCV_BUILD_DIR}" ) From 9a468ec8e4c5eb5b0494884a10b9bc9a9c492158 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Sun, 3 May 2026 00:04:21 +0200 Subject: [PATCH 4/9] Fix SYCL static analysis issues --- app/SYCL/sycl_kernel.cpp | 8 ++++++-- test/parallel/test_sycl_parallel.cpp | 11 ++++------- test/single_layer/test_ewlayer.cpp | 3 ++- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/app/SYCL/sycl_kernel.cpp b/app/SYCL/sycl_kernel.cpp index 4e0987309..7e7c94a5e 100644 --- a/app/SYCL/sycl_kernel.cpp +++ b/app/SYCL/sycl_kernel.cpp @@ -1,7 +1,11 @@ -#include +#ifdef ITLABAI_HAS_SYCL -#include "parallel/parallel.hpp" +# include + +# include "parallel/parallel.hpp" std::string sycl_device_name() { return it_lab_ai::parallel::sycl_device_name(); } + +#endif diff --git a/test/parallel/test_sycl_parallel.cpp b/test/parallel/test_sycl_parallel.cpp index 196069e37..ee9f25b63 100644 --- a/test/parallel/test_sycl_parallel.cpp +++ b/test/parallel/test_sycl_parallel.cpp @@ -3,7 +3,7 @@ #ifdef ITLABAI_HAS_SYCL -#include +# include namespace it_lab_ai { namespace { @@ -12,12 +12,9 @@ TEST(sycl_parallel, parallel_for_writes_expected_values) { constexpr std::size_t kSize = 1024; std::vector values(kSize, 0); - parallel::parallel_for( - kSize, - [&](std::size_t i) { - values[i] = static_cast(i * 2); - }, - parallel::Backend::kSycl); + parallel::parallel_for(kSize, [&](std::size_t i) { + values[i] = static_cast(i * 2); + }, parallel::Backend::kSycl); for (std::size_t i = 0; i < values.size(); ++i) { EXPECT_EQ(values[i], static_cast(i * 2)); diff --git a/test/single_layer/test_ewlayer.cpp b/test/single_layer/test_ewlayer.cpp index e3dd0ce99..9532a8ec4 100644 --- a/test/single_layer/test_ewlayer.cpp +++ b/test/single_layer/test_ewlayer.cpp @@ -258,7 +258,8 @@ TEST(ewlayer, parallel_for_ew_sigmoid_compact) { std::vector> backends; for (auto backend : test_support::all_parallel_backends()) { - backends.emplace_back(backend, test_support::parallel_backend_name(backend)); + backends.emplace_back(backend, + test_support::parallel_backend_name(backend)); } std::vector reference_result; From 750e0dfabe4a8e574d92b84a30458d6769792aba Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Sun, 3 May 2026 11:44:40 +0200 Subject: [PATCH 5/9] Limit CI push trigger to main --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7655a1e6f..875ff7ae3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,6 +2,8 @@ name: CI on: push: + branches: + - main pull_request: schedule: - cron: '0 8 * * *' From 8a4fd6815877fcc90cb4965af411cd9e97a54d88 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Sun, 3 May 2026 19:16:32 +0200 Subject: [PATCH 6/9] Add SYCL coverage upload --- .github/workflows/ci.yml | 4 +- .github/workflows/sycl-ci.yml | 71 ++++++++++++++++++++++++++++ test/parallel/test_sycl_parallel.cpp | 17 +++++-- 3 files changed, 87 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 875ff7ae3..66829cbab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,8 +2,6 @@ name: CI on: push: - branches: - - main pull_request: schedule: - cron: '0 8 * * *' @@ -228,6 +226,8 @@ jobs: - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v4.0.1 with: + files: coverage.xml + fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} slug: embedded-dev-research/ITLabAI diff --git a/.github/workflows/sycl-ci.yml b/.github/workflows/sycl-ci.yml index 47f1be621..fd3b7ee2c 100644 --- a/.github/workflows/sycl-ci.yml +++ b/.github/workflows/sycl-ci.yml @@ -147,3 +147,74 @@ jobs: - name: Test run: ctest --test-dir "build/${{ matrix.build_type }}" --output-on-failure -R '^(UnitTests|SYCL\.Example)$' + + codecov-sycl: + name: codecov sycl + needs: prepare-sycl-toolchain + runs-on: ubuntu-latest + timeout-minutes: 180 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + + - name: Setup ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ccache-${{ github.job }}-linux-x86_64 + max-size: 4G + + - name: Restore AdaptiveCpp toolchain cache + uses: actions/cache/restore@v4 + with: + path: | + ${{ runner.temp }}/AdaptiveCpp + ${{ runner.temp }}/AdaptiveCpp-build + ${{ runner.temp }}/adaptivecpp-install + ${{ runner.temp }}/archives + key: sycl-toolchain-linux-x86_64-${{ env.ADAPTIVECPP_TAG }}-${{ env.ADAPTIVECPP_CACHE_VERSION }} + fail-on-cache-miss: true + + - name: Setup SYCL toolchain + uses: ./.github/actions/setup-sycl-toolchain + with: + phase: build + + - name: Install coverage tools + shell: bash + run: sudo apt-get update && sudo apt-get install -y gcovr + + - name: Configure + shell: bash + run: | + cmake -S . -B build/sycl-coverage -G Ninja \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_C_COMPILER="${ITLABAI_CC}" \ + -DCMAKE_CXX_COMPILER="${ITLABAI_CXX}" \ + -DCMAKE_PREFIX_PATH="${ITLABAI_CMAKE_PREFIX_PATH}" \ + -DOpenMP_ROOT="${ITLABAI_OPENMP_ROOT}" \ + -DACPP_TARGETS="${ACPP_TARGETS}" \ + -DCMAKE_C_FLAGS="--coverage" \ + -DCMAKE_CXX_FLAGS="--coverage" \ + -DCMAKE_EXE_LINKER_FLAGS="--coverage" \ + -DCMAKE_SHARED_LINKER_FLAGS="--coverage" \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + + - name: Build + run: cmake --build build/sycl-coverage --target SYCL_Example run_test --parallel + + - name: Test + run: ctest --test-dir build/sycl-coverage --output-on-failure -R '^(UnitTests|SYCL\.Example)$' + + - name: Generate SYCL coverage data + run: gcovr -r . --xml -o sycl-coverage.xml --gcov-executable "llvm-cov-18 gcov" --gcov-ignore-parse-errors + + - name: Upload SYCL coverage report to Codecov + uses: codecov/codecov-action@v4.0.1 + with: + files: sycl-coverage.xml + flags: sycl + fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} + slug: embedded-dev-research/ITLabAI diff --git a/test/parallel/test_sycl_parallel.cpp b/test/parallel/test_sycl_parallel.cpp index ee9f25b63..ce15e56a6 100644 --- a/test/parallel/test_sycl_parallel.cpp +++ b/test/parallel/test_sycl_parallel.cpp @@ -1,13 +1,16 @@ +#include + #include "gtest/gtest.h" #include "parallel/parallel.hpp" #ifdef ITLABAI_HAS_SYCL - # include +#endif namespace it_lab_ai { namespace { +#ifdef ITLABAI_HAS_SYCL TEST(sycl_parallel, parallel_for_writes_expected_values) { constexpr std::size_t kSize = 1024; std::vector values(kSize, 0); @@ -25,7 +28,15 @@ TEST(sycl_parallel, reports_selected_device) { EXPECT_FALSE(parallel::sycl_device_name().empty()); } -} // namespace -} // namespace it_lab_ai +#else + +TEST(sycl_parallel, throws_when_backend_is_unavailable) { + EXPECT_THROW(parallel::parallel_for(1024, [](std::size_t) {}, + parallel::Backend::kSycl), + std::runtime_error); +} #endif + +} // namespace +} // namespace it_lab_ai From bcdc27336b84c6f28fb1e16f902263f7c0a58322 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Sun, 3 May 2026 23:53:46 +0200 Subject: [PATCH 7/9] Fix SYCL coverage reporting --- .github/workflows/ci.yml | 1 + .github/workflows/sycl-ci.yml | 12 +++++++++++- codecov.yml | 5 +++++ test/parallel/test_sycl_parallel.cpp | 7 +++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 66829cbab..446e49c54 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -227,6 +227,7 @@ jobs: uses: codecov/codecov-action@v4.0.1 with: files: coverage.xml + disable_search: true fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} slug: embedded-dev-research/ITLabAI diff --git a/.github/workflows/sycl-ci.yml b/.github/workflows/sycl-ci.yml index fd3b7ee2c..e407c9784 100644 --- a/.github/workflows/sycl-ci.yml +++ b/.github/workflows/sycl-ci.yml @@ -208,12 +208,22 @@ jobs: run: ctest --test-dir build/sycl-coverage --output-on-failure -R '^(UnitTests|SYCL\.Example)$' - name: Generate SYCL coverage data - run: gcovr -r . --xml -o sycl-coverage.xml --gcov-executable "llvm-cov-18 gcov" --gcov-ignore-parse-errors + run: | + gcovr -r . --xml -o sycl-coverage.xml \ + --gcov-executable "llvm-cov-18 gcov" \ + --gcov-ignore-parse-errors \ + --exclude-throw-branches \ + --exclude-unreachable-branches \ + --filter "include/.*" \ + --filter "src/.*" \ + --filter "app/.*" \ + --filter "test/.*" - name: Upload SYCL coverage report to Codecov uses: codecov/codecov-action@v4.0.1 with: files: sycl-coverage.xml + disable_search: true flags: sycl fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} diff --git a/codecov.yml b/codecov.yml index ce42675a3..244bb3683 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,3 +1,8 @@ +codecov: + notify: + after_n_builds: 2 + wait_for_ci: true + ignore: - app - test diff --git a/test/parallel/test_sycl_parallel.cpp b/test/parallel/test_sycl_parallel.cpp index ce15e56a6..4bb57e8c2 100644 --- a/test/parallel/test_sycl_parallel.cpp +++ b/test/parallel/test_sycl_parallel.cpp @@ -24,6 +24,13 @@ TEST(sycl_parallel, parallel_for_writes_expected_values) { } } +TEST(sycl_parallel, zero_count_does_not_invoke_kernel) { + bool invoked = false; + parallel::impl_sycl(std::size_t{0}, [&](std::size_t) { invoked = true; }, + parallel::Options{}); + EXPECT_FALSE(invoked); +} + TEST(sycl_parallel, reports_selected_device) { EXPECT_FALSE(parallel::sycl_device_name().empty()); } From ee17d26c074b97c8321f2a163c6b71a898354059 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Mon, 4 May 2026 00:15:14 +0200 Subject: [PATCH 8/9] Wait for SYCL coverage upload --- .github/workflows/ci.yml | 2 +- .github/workflows/sycl-ci.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 446e49c54..330f2bfda 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -226,7 +226,7 @@ jobs: - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v4.0.1 with: - files: coverage.xml + file: coverage.xml disable_search: true fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/sycl-ci.yml b/.github/workflows/sycl-ci.yml index e407c9784..61c6e8b93 100644 --- a/.github/workflows/sycl-ci.yml +++ b/.github/workflows/sycl-ci.yml @@ -222,7 +222,7 @@ jobs: - name: Upload SYCL coverage report to Codecov uses: codecov/codecov-action@v4.0.1 with: - files: sycl-coverage.xml + file: sycl-coverage.xml disable_search: true flags: sycl fail_ci_if_error: true From b95d51851c6e06b6ed33ee67aa22cc22262ec7bc Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Mon, 4 May 2026 00:45:38 +0200 Subject: [PATCH 9/9] Keep regular coverage upload complete --- .github/workflows/ci.yml | 2 -- .github/workflows/sycl-ci.yml | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 330f2bfda..094876bf0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -226,8 +226,6 @@ jobs: - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v4.0.1 with: - file: coverage.xml - disable_search: true fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} slug: embedded-dev-research/ITLabAI diff --git a/.github/workflows/sycl-ci.yml b/.github/workflows/sycl-ci.yml index 61c6e8b93..f0320d953 100644 --- a/.github/workflows/sycl-ci.yml +++ b/.github/workflows/sycl-ci.yml @@ -212,8 +212,7 @@ jobs: gcovr -r . --xml -o sycl-coverage.xml \ --gcov-executable "llvm-cov-18 gcov" \ --gcov-ignore-parse-errors \ - --exclude-throw-branches \ - --exclude-unreachable-branches \ + --exclude-branches-by-pattern ".*" \ --filter "include/.*" \ --filter "src/.*" \ --filter "app/.*" \