Skip to content

Commit 218b148

Browse files
committed
Rebase SYCL PR onto current main
1 parent dd595d7 commit 218b148

7 files changed

Lines changed: 456 additions & 17 deletions

File tree

.github/workflows/sycl-ci.yml

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
name: SYCL CI
2+
3+
on:
4+
pull_request:
5+
workflow_dispatch:
6+
7+
concurrency:
8+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
9+
cancel-in-progress: true
10+
11+
env:
12+
ADAPTIVECPP_TAG: v25.10.0
13+
LLVM_MINGW_VERSION: "20231128"
14+
15+
jobs:
16+
build-sycl:
17+
name: ${{ matrix.platform }}
18+
runs-on: ${{ matrix.runner }}
19+
timeout-minutes: 360
20+
strategy:
21+
fail-fast: true
22+
matrix:
23+
include:
24+
- platform: linux-x86_64
25+
runner: ubuntu-latest
26+
- platform: linux-arm64
27+
runner: ubuntu-24.04-arm
28+
- platform: macos-arm64
29+
runner: macos-15
30+
- platform: windows-x86_64
31+
runner: windows-2022
32+
33+
steps:
34+
- uses: actions/checkout@v4
35+
with:
36+
submodules: true
37+
38+
- name: Setup ccache
39+
uses: hendrikmuhs/ccache-action@v1.2
40+
with:
41+
key: ccache-${{ github.job }}-${{ matrix.platform }}
42+
max-size: 4G
43+
44+
- name: Restore AdaptiveCpp toolchain cache
45+
uses: actions/cache@v4
46+
with:
47+
path: |
48+
${{ runner.temp }}/AdaptiveCpp
49+
${{ runner.temp }}/AdaptiveCpp-build
50+
${{ runner.temp }}/adaptivecpp-install
51+
${{ runner.temp }}/llvm
52+
${{ runner.temp }}/boost_1_87_0
53+
${{ runner.temp }}/ninja_install
54+
${{ runner.temp }}/archives
55+
key: sycl-toolchain-${{ matrix.platform }}-${{ env.ADAPTIVECPP_TAG }}-${{ env.LLVM_MINGW_VERSION }}-v1
56+
57+
- name: Setup MSVC environment
58+
if: runner.os == 'Windows'
59+
uses: ilammy/msvc-dev-cmd@v1
60+
61+
- name: Prepare AdaptiveCpp toolchain
62+
run: python ./scripts/ci/sycl_setup.py ${{ matrix.platform }}
63+
64+
- name: Configure, build and test
65+
if: runner.os != 'Windows'
66+
shell: bash
67+
run: |
68+
for build_type in Debug Release; do
69+
build_dir="build/${build_type}"
70+
cmake_args=(
71+
-S .
72+
-B "${build_dir}"
73+
-G Ninja
74+
-DCMAKE_BUILD_TYPE=${build_type}
75+
-DCMAKE_C_COMPILER=${ITLABAI_CC}
76+
-DCMAKE_CXX_COMPILER=${ITLABAI_CXX}
77+
-DCMAKE_PREFIX_PATH=${ITLABAI_CMAKE_PREFIX_PATH}
78+
-DITLABAI_ENABLE_SYCL=ON
79+
-DITLABAI_SYCL_IMPLEMENTATION=AdaptiveCpp
80+
-DITLABAI_ENABLE_OPENCV_APPS=OFF
81+
-DITLABAI_BUILD_TESTS=ON
82+
-DACPP_TARGETS=${ACPP_TARGETS}
83+
)
84+
if command -v ccache >/dev/null 2>&1; then
85+
cmake_args+=(
86+
-DCMAKE_C_COMPILER_LAUNCHER=ccache
87+
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
88+
)
89+
fi
90+
if [ -n "${ITLABAI_OPENMP_ROOT:-}" ]; then
91+
cmake_args+=(-DOpenMP_ROOT=${ITLABAI_OPENMP_ROOT})
92+
fi
93+
cmake "${cmake_args[@]}"
94+
cmake --build "${build_dir}" --parallel
95+
ctest --test-dir "${build_dir}" --output-on-failure -E '^SYCL\.Example$' --parallel
96+
done
97+
98+
- name: Configure, build and test
99+
if: runner.os == 'Windows'
100+
shell: pwsh
101+
run: |
102+
foreach ($buildType in 'Debug', 'Release') {
103+
$buildDir = "build/$buildType"
104+
$cmakeArgs = @(
105+
'-S', '.',
106+
'-B', $buildDir,
107+
'-G', 'Ninja',
108+
"-DCMAKE_BUILD_TYPE=$buildType",
109+
"-DCMAKE_C_COMPILER=$env:ITLABAI_CC",
110+
"-DCMAKE_CXX_COMPILER=$env:ITLABAI_CXX",
111+
"-DCMAKE_PREFIX_PATH=$env:ITLABAI_CMAKE_PREFIX_PATH",
112+
'-DITLABAI_ENABLE_SYCL=ON',
113+
'-DITLABAI_SYCL_IMPLEMENTATION=AdaptiveCpp',
114+
'-DITLABAI_ENABLE_OPENCV_APPS=OFF',
115+
'-DITLABAI_BUILD_TESTS=ON',
116+
"-DACPP_TARGETS=$env:ACPP_TARGETS"
117+
)
118+
if (Get-Command ccache -ErrorAction SilentlyContinue) {
119+
$cmakeArgs += '-DCMAKE_C_COMPILER_LAUNCHER=ccache'
120+
$cmakeArgs += '-DCMAKE_CXX_COMPILER_LAUNCHER=ccache'
121+
}
122+
if ($env:ITLABAI_OPENMP_ROOT) {
123+
$cmakeArgs += "-DOpenMP_ROOT=$env:ITLABAI_OPENMP_ROOT"
124+
}
125+
& cmake @cmakeArgs
126+
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
127+
& cmake --build $buildDir --parallel
128+
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
129+
& ctest --test-dir $buildDir --output-on-failure -E '^SYCL\.Example$' --parallel
130+
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
131+
}

CMakeLists.txt

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
cmake_minimum_required(VERSION 3.20)
22

3-
project(ITLabAI)
3+
project(ITLabAI LANGUAGES CXX)
44

55
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE)
6+
option(ITLABAI_ENABLE_SYCL "Build SYCL example and helper targets" OFF)
7+
option(ITLABAI_ENABLE_OPENCV_APPS "Build OpenCV-dependent apps" ON)
8+
option(ITLABAI_BUILD_TESTS "Build unit tests" ON)
9+
set(ITLABAI_SYCL_IMPLEMENTATION "AdaptiveCpp" CACHE STRING
10+
"SYCL implementation to use")
11+
set_property(CACHE ITLABAI_SYCL_IMPLEMENTATION PROPERTY STRINGS AdaptiveCpp)
12+
set(ITLABAI_SYCL_TARGETS "" CACHE STRING
13+
"Optional SYCL targets; forwarded to AdaptiveCpp as ACPP_TARGETS")
614

715
option(ENABLE_STATISTIC_TENSORS "Enable statistic tensors" OFF)
816

@@ -21,52 +29,81 @@ option(ENABLE_STATISTIC_WEIGHTS "Enable statistic weights" OFF)
2129
if(ENABLE_STATISTIC_WEIGHTS)
2230
add_definitions(-DENABLE_STATISTIC_WEIGHTS)
2331
endif()
24-
2532
set(CMAKE_CXX_STANDARD 20)
2633

2734
enable_testing()
2835

29-
find_package(OpenMP REQUIRED)
36+
find_package(OpenMP REQUIRED COMPONENTS CXX)
3037

3138
if(OpenMP_FOUND)
3239
message(STATUS "OpenMP found - enabling parallel support")
33-
add_definitions(-DHAS_OPENMP)
34-
link_libraries(OpenMP::OpenMP_CXX)
3540
else()
3641
message(STATUS "OpenMP not found - parallel features disabled")
3742
endif()
3843

44+
if(ITLABAI_ENABLE_SYCL)
45+
if(NOT ITLABAI_SYCL_IMPLEMENTATION STREQUAL "AdaptiveCpp")
46+
message(FATAL_ERROR
47+
"ITLABAI_ENABLE_SYCL=ON currently supports only "
48+
"ITLABAI_SYCL_IMPLEMENTATION=AdaptiveCpp")
49+
endif()
50+
51+
if(ITLABAI_SYCL_TARGETS)
52+
set(ACPP_TARGETS "${ITLABAI_SYCL_TARGETS}" CACHE STRING
53+
"AdaptiveCpp targets" FORCE)
54+
endif()
55+
find_package(AdaptiveCpp CONFIG REQUIRED)
56+
function(itlabai_add_sycl_to_target)
57+
add_sycl_to_target(${ARGN})
58+
endfunction()
59+
endif()
60+
3961
include_directories("include")
4062

4163
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
4264

4365
add_subdirectory(3rdparty)
4466

45-
include(cmake/opencv_config.cmake)
67+
if(ITLABAI_ENABLE_OPENCV_APPS)
68+
include(cmake/opencv_config.cmake)
69+
endif()
4670
include(cmake/kokkos_config.cmake)
4771

48-
include_directories("${KOKKOS_INSTALL_DIR}/include")
72+
include_directories(SYSTEM "${KOKKOS_INSTALL_DIR}/include")
4973

5074
add_library(Kokkos_imported INTERFACE)
5175
add_dependencies(Kokkos_imported kokkos_external)
5276

53-
target_include_directories(Kokkos_imported INTERFACE
77+
target_include_directories(Kokkos_imported SYSTEM INTERFACE
5478
"${KOKKOS_INSTALL_DIR}/include"
5579
)
56-
57-
target_link_directories(Kokkos_imported INTERFACE
80+
target_link_directories(Kokkos_imported INTERFACE
5881
"${KOKKOS_INSTALL_DIR}/lib"
5982
)
60-
61-
6283
target_link_libraries(Kokkos_imported INTERFACE kokkoscore kokkoscontainers)
6384

6485

6586
if(MSVC)
6687
add_compile_options(/wd4267 /wd4244 /wd4127 /wd4324)
6788
endif()
6889

69-
if (NOT WIN32)
90+
get_filename_component(ITLABAI_C_COMPILER_NAME "${CMAKE_C_COMPILER}" NAME)
91+
get_filename_component(ITLABAI_CXX_COMPILER_NAME "${CMAKE_CXX_COMPILER}" NAME)
92+
string(TOLOWER "${ITLABAI_C_COMPILER_NAME}" ITLABAI_C_COMPILER_NAME_LOWER)
93+
string(TOLOWER "${ITLABAI_CXX_COMPILER_NAME}" ITLABAI_CXX_COMPILER_NAME_LOWER)
94+
95+
set(ITLABAI_WINDOWS_USES_MSVC_FRONTEND OFF)
96+
if(WIN32 AND (
97+
ITLABAI_C_COMPILER_NAME_LOWER MATCHES "(^|-)cl(\\.exe)?$"
98+
OR ITLABAI_C_COMPILER_NAME_LOWER MATCHES "clang-cl(\\.exe)?$"
99+
OR ITLABAI_C_COMPILER_NAME_LOWER MATCHES "icx-cl(\\.exe)?$"
100+
OR ITLABAI_CXX_COMPILER_NAME_LOWER MATCHES "(^|-)cl(\\.exe)?$"
101+
OR ITLABAI_CXX_COMPILER_NAME_LOWER MATCHES "clang-cl(\\.exe)?$"
102+
OR ITLABAI_CXX_COMPILER_NAME_LOWER MATCHES "icx-cl(\\.exe)?$"))
103+
set(ITLABAI_WINDOWS_USES_MSVC_FRONTEND ON)
104+
endif()
105+
106+
if(NOT WIN32 OR NOT ITLABAI_WINDOWS_USES_MSVC_FRONTEND)
70107
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror")
71108
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror")
72109
else()
@@ -83,4 +120,7 @@ endforeach()
83120
add_subdirectory(app)
84121
add_subdirectory(include)
85122
add_subdirectory(src)
86-
add_subdirectory(test)
123+
124+
if(ITLABAI_BUILD_TESTS)
125+
add_subdirectory(test)
126+
endif()

app/CMakeLists.txt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
add_subdirectory(ReaderImage)
2-
add_subdirectory(Accuracy)
1+
if(ITLABAI_ENABLE_SYCL)
2+
add_subdirectory(SYCL)
3+
endif()
4+
35
add_subdirectory(Converters)
4-
add_subdirectory(Graph)
6+
7+
if(ITLABAI_ENABLE_OPENCV_APPS)
8+
add_subdirectory(ReaderImage)
9+
add_subdirectory(Accuracy)
10+
add_subdirectory(Graph)
11+
endif()

app/SYCL/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
add_executable(SYCL_Example
2+
sycl_example.cpp
3+
)
4+
target_link_libraries(SYCL_Example PRIVATE layers_lib AdaptiveCpp::acpp-rt)
5+
6+
add_library(SYCL_Example_kernel OBJECT sycl_kernel.cpp)
7+
itlabai_add_sycl_to_target(TARGET SYCL_Example_kernel SOURCES
8+
sycl_kernel.cpp
9+
)
10+
target_sources(SYCL_Example PRIVATE $<TARGET_OBJECTS:SYCL_Example_kernel>)
11+
12+
add_test(NAME SYCL.Example COMMAND SYCL_Example)
13+
set_tests_properties(SYCL.Example PROPERTIES
14+
LABELS "sycl;smoke"
15+
TIMEOUT 60
16+
)

app/SYCL/sycl_example.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#include <cmath>
2+
#include <iostream>
3+
#include <sycl/sycl.hpp>
4+
#include <vector>
5+
6+
#include "graph/runtime_options.hpp"
7+
#include "layers/EWLayer.hpp"
8+
#include "layers/Tensor.hpp"
9+
10+
namespace {
11+
12+
bool almost_equal(float lhs, float rhs) {
13+
return std::fabs(lhs - rhs) < 1.0e-6F;
14+
}
15+
16+
} // namespace
17+
18+
void run_sycl_kernel(sycl::queue& queue, const float* input, float* output,
19+
std::size_t count);
20+
21+
int main() {
22+
try {
23+
using namespace it_lab_ai;
24+
25+
std::vector<float> input_values = {-2.0F, -1.0F, 0.0F, 1.0F, 2.0F};
26+
Tensor input = make_tensor(input_values);
27+
std::vector<Tensor> inputs = {input};
28+
std::vector<Tensor> outputs(1);
29+
30+
EWLayer relu("relu");
31+
RuntimeOptions options;
32+
relu.run(inputs, outputs, options);
33+
34+
const std::vector<float>& relu_output = *outputs.front().as<float>();
35+
const std::vector<float> expected_relu = {0.0F, 0.0F, 0.0F, 1.0F, 2.0F};
36+
37+
if (relu_output != expected_relu) {
38+
std::cerr << "ITLabAI EWLayer produced an unexpected result" << '\n';
39+
return 1;
40+
}
41+
42+
const std::size_t count = relu_output.size();
43+
sycl::queue queue(sycl::default_selector_v);
44+
std::cout << "SYCL device: "
45+
<< queue.get_device().get_info<sycl::info::device::name>()
46+
<< '\n';
47+
48+
std::vector<float> sycl_output(count);
49+
run_sycl_kernel(queue, relu_output.data(), sycl_output.data(), count);
50+
51+
const std::vector<float> expected_sycl = {1.0F, 1.0F, 1.0F, 3.0F, 5.0F};
52+
for (std::size_t i = 0; i < count; ++i) {
53+
if (!almost_equal(sycl_output[i], expected_sycl[i])) {
54+
std::cerr << "SYCL kernel verification failed at index " << i << '\n';
55+
return 1;
56+
}
57+
}
58+
59+
std::cout << "SYCL example completed successfully" << '\n';
60+
return 0;
61+
} catch (const std::exception& exception) {
62+
std::cerr << "Error: " << exception.what() << '\n';
63+
return 1;
64+
}
65+
}

app/SYCL/sycl_kernel.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <cstddef>
2+
#include <sycl/sycl.hpp>
3+
class SyclExampleTransformKernel;
4+
5+
void run_sycl_kernel(sycl::queue& queue, const float* input, float* output,
6+
std::size_t count) {
7+
sycl::buffer<const float, 1> input_buffer(input, sycl::range<1>(count));
8+
sycl::buffer<float, 1> output_buffer(output, sycl::range<1>(count));
9+
10+
queue.submit([&](sycl::handler& handler) {
11+
auto input_acc = input_buffer.get_access<sycl::access::mode::read>(handler);
12+
auto output_acc =
13+
output_buffer.get_access<sycl::access::mode::write>(handler);
14+
handler.parallel_for<SyclExampleTransformKernel>(sycl::range<1>(count),
15+
[=](sycl::id<1> index) {
16+
output_acc[index] = input_acc[index] * 2.0F + 1.0F;
17+
});
18+
});
19+
queue.wait_and_throw();
20+
}

0 commit comments

Comments
 (0)