Skip to content

Commit 2cf6968

Browse files
authored
Merge pull request #3 from CExA-project/simd-backends
SIMD backends for math functions
2 parents e411042 + 8b7bf1d commit 2cf6968

12 files changed

Lines changed: 1094 additions & 0 deletions

File tree

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
# SPDX-FileCopyrightText: 2026 CExA-project
2+
# SPDX-License-Identifier: MIT or Apache-2.0 with LLVM-exception
3+
4+
name: SIMD Backends Tests
5+
6+
on:
7+
pull_request:
8+
paths:
9+
- '.github/workflows/simd-backends.yml'
10+
- 'simd-backends/**'
11+
- '!simd-backends/README.md'
12+
push:
13+
branches:
14+
- main
15+
16+
concurrency:
17+
group: ${{ github.event_name }}-${{ github.workflow }}-${{ github.ref }}
18+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
19+
20+
jobs:
21+
unit-tests:
22+
continue-on-error: true
23+
24+
strategy:
25+
matrix:
26+
kokkos-version: [4.6.00, 5.1.0]
27+
28+
runs-on: ubuntu-latest
29+
30+
env:
31+
CMAKE_GENERATOR: Ninja
32+
Kokkos_ROOT: ${{ github.workspace }}/opt/kokkos
33+
sleef_ROOT: ${{ github.workspace }}/opt/sleef
34+
CexaSimdBackends_ROOT: ${{ github.workspace }}/simd-backends/install
35+
steps:
36+
- name: Checkout Code
37+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
38+
- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
39+
id: cache-sleef
40+
with:
41+
path: opt/sleef
42+
key: simd-backends-sleef-ubuntu-latest
43+
- name: Checkout Sleef
44+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
45+
if: steps.cache-sleef.outputs.cache-hit != 'true'
46+
with:
47+
repository: shibatch/sleef
48+
ref: 3.9.0
49+
path: sleef
50+
- name: Install Sleef
51+
if: steps.cache-sleef.outputs.cache-hit != 'true'
52+
run: |
53+
cmake \
54+
-DCMAKE_BUILD_TYPE=Release \
55+
-DCMAKE_C_COMPILER=gcc \
56+
-DCMAKE_CXX_COMPILER=g++ \
57+
-DCMAKE_INSTALL_PREFIX="$sleef_ROOT" \
58+
-DSLEEF_BUILD_GNUABI_LIBS=OFF \
59+
-DSLEEF_BUILD_TESTS=OFF \
60+
-DSLEEF_ENABLE_TLFLOAT=OFF \
61+
-DSLEEF_ENABLE_FFTW=OFF \
62+
-DSLEEF_ENABLE_MPFR=OFF \
63+
-B sleef/build -S sleef
64+
cmake --build sleef/build -j $(nproc) --target install
65+
- name: Checkout Kokkos
66+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
67+
with:
68+
repository: kokkos/kokkos
69+
ref: ${{ matrix.kokkos-version }}
70+
path: kokkos
71+
- name: Install kokkos
72+
run: |
73+
cmake \
74+
-DCMAKE_CXX_COMPILER=g++ \
75+
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
76+
-DCMAKE_INSTALL_PREFIX="$Kokkos_ROOT" \
77+
-DKokkos_ARCH_NATIVE=ON \
78+
-B kokkos/build -S kokkos
79+
cmake --build kokkos/build -j $(nproc) --target install
80+
- name: Configure
81+
working-directory: ${{ github.workspace }}/simd-backends
82+
run:
83+
cmake
84+
-DCMAKE_CXX_COMPILER=g++
85+
-DCMAKE_BUILD_TYPE=RelWithDebInfo
86+
-DCMAKE_INSTALL_PREFIX="$CexaSimdBackends_ROOT"
87+
-DCEXA_SIMD_ENABLE_SLEEF=ON
88+
-DCEXA_SIMD_ENABLE_TESTS=ON
89+
-B build -S .
90+
- name: Build
91+
working-directory: ${{ github.workspace }}/simd-backends
92+
run: cmake --build build -j $(nproc)
93+
- name: Install
94+
working-directory: ${{ github.workspace }}/simd-backends
95+
run: cmake --install build
96+
- name: Test install
97+
working-directory: ${{ github.workspace }}/simd-backends/test/install_test
98+
run: |
99+
cmake \
100+
-DCMAKE_CXX_COMPILER=g++ \
101+
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
102+
-B build -S .
103+
cmake --build build -j $(nproc)
104+
./build/main
105+
- name: Patch the Kokkos SIMD unit tests to use the Sleef backend
106+
working-directory: ${{ github.workspace }}/kokkos/simd/unit_tests
107+
run: |
108+
cp "$CexaSimdBackends_ROOT/include/CEXA_SIMD_SLEEF.hpp" include
109+
sed -i '/kokkos_add_executable_and_test/a find_package(sleef REQUIRED)\ntarget_link_libraries(Kokkos_UnitTest_SIMD PRIVATE sleef::sleef)' CMakeLists.txt
110+
sed -i '/include <Kokkos_SIMD.hpp>/a #include <CEXA_SIMD_SLEEF.hpp>' include/TestSIMD_MathOps.hpp
111+
- name: Run the Kokkos SIMD unit tests using the Sleef backend
112+
working-directory: ${{ github.workspace }}/kokkos
113+
run: |
114+
cmake \
115+
-DCMAKE_CXX_COMPILER=g++ \
116+
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
117+
-DKokkos_ARCH_NATIVE=ON \
118+
-DKokkos_ENABLE_TESTS=ON \
119+
-B build -S .
120+
cmake --build build -j $(nproc) --target Kokkos_UnitTest_SIMD
121+
ctest --test-dir build --output-on-failure -R SIMD
122+
123+
performance-tests:
124+
continue-on-error: true
125+
126+
runs-on: ubuntu-latest
127+
128+
env:
129+
CMAKE_GENERATOR: Ninja
130+
sleef_ROOT: ${{ github.workspace }}/opt/sleef
131+
compare_ROOT: ${{ github.workspace }}/opt/compare
132+
benchmark_VERSION: v1.9.5
133+
steps:
134+
- name: Checkout Code
135+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
136+
- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
137+
id: cache-sleef
138+
with:
139+
path: opt/sleef
140+
key: simd-backends-sleef-ubuntu-latest
141+
- name: Checkout Sleef
142+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
143+
if: steps.cache-sleef.outputs.cache-hit != 'true'
144+
with:
145+
repository: shibatch/sleef
146+
ref: 3.9.0
147+
path: sleef
148+
- name: Install Sleef
149+
if: steps.cache-sleef.outputs.cache-hit != 'true'
150+
run: |
151+
cmake \
152+
-DCMAKE_BUILD_TYPE=Release \
153+
-DCMAKE_C_COMPILER=gcc \
154+
-DCMAKE_CXX_COMPILER=g++ \
155+
-DCMAKE_INSTALL_PREFIX="$sleef_ROOT" \
156+
-DSLEEF_BUILD_GNUABI_LIBS=OFF \
157+
-DSLEEF_BUILD_TESTS=OFF \
158+
-DSLEEF_ENABLE_TLFLOAT=OFF \
159+
-DSLEEF_ENABLE_FFTW=OFF \
160+
-DSLEEF_ENABLE_MPFR=OFF \
161+
-B sleef/build -S sleef
162+
cmake --build sleef/build -j $(nproc) --target install
163+
- run: echo "PYTHON_VERSION=$(python3 --version | sed 's/ /_/')" >> $GITHUB_ENV
164+
- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
165+
id: cache-gbench-compare
166+
with:
167+
path: ${{ env.compare_ROOT }}
168+
key: simd-backends-gbench-ubuntu-latest-${{ env.benchmark_VERSION }}-${{ env.PYTHON_VERSION }}
169+
- name: Checkout google benchmark
170+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
171+
if: steps.cache-gbench-compare.outputs.cache-hit != 'true'
172+
with:
173+
repository: google/benchmark
174+
ref: ${{ env.benchmark_VERSION }}
175+
path: benchmark
176+
- name: Get the compare script from google benchmark
177+
if: steps.cache-gbench-compare.outputs.cache-hit != 'true'
178+
run: |
179+
mkdir -p ${{ env.compare_ROOT }}
180+
cp -r benchmark/tools/* ${{ env.compare_ROOT }}
181+
- name: Install python dependencies
182+
working-directory: ${{ env.compare_ROOT }}
183+
if: steps.cache-gbench-compare.outputs.cache-hit != 'true'
184+
run: |
185+
python3 -m venv ./venv
186+
source ./venv/bin/activate
187+
pip3 install -r ./requirements.txt
188+
- name: Checkout Kokkos
189+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
190+
with:
191+
repository: kokkos/kokkos
192+
ref: 5.1.0
193+
path: kokkos
194+
- name: Run the Kokkos SIMD perf tests
195+
# We use "math .[^c]" as benchmark_filter to only run benchmarks for
196+
# math functions and to exclude the scalar ones, ".[^c]" will exclude
197+
# "scalar" but not "avx", "neon" or "sve".
198+
# We also increase the number of iterations to get more stable results,
199+
# we can afford it since we don't run the scalar benchmarks.
200+
working-directory: ${{ github.workspace }}/kokkos
201+
run: |
202+
sed -i 's/Iterations(3)/Iterations(300)/' simd/perf_tests/include/PerfTest_Host.hpp
203+
cmake \
204+
-DCMAKE_CXX_COMPILER=g++ \
205+
-DCMAKE_BUILD_TYPE=Release \
206+
-DKokkos_ARCH_NATIVE=ON \
207+
-DKokkos_ENABLE_BENCHMARKS=ON \
208+
-B build -S .
209+
cmake --build build -j $(nproc) --target Kokkos_PerformanceTest_SIMD_Host
210+
./build/simd/perf_tests/Kokkos_PerformanceTest_SIMD_Host --benchmark_out=baseline.json --benchmark_filter="math .[^c]"
211+
- name: Patch the Kokkos SIMD perf tests to use the Sleef backend
212+
working-directory: ${{ github.workspace }}/kokkos/simd/perf_tests
213+
run: |
214+
cp "${{ github.workspace }}/simd-backends/src/CEXA_SIMD_SLEEF.hpp" include
215+
sed -i '/KOKKOS_IMPL_SIMD_DEVICE_PERFTEST/a find_package(sleef REQUIRED)\ntarget_link_libraries(Kokkos_PerformanceTest_SIMD_Host PRIVATE sleef::sleef)' CMakeLists.txt
216+
sed -i '/include <Kokkos_SIMD.hpp>/a #include <CEXA_SIMD_SLEEF.hpp>' include/PerfTest_Host.hpp
217+
- name: Run the Kokkos SIMD perf tests using the Sleef backend
218+
working-directory: ${{ github.workspace }}/kokkos
219+
run: |
220+
cmake --build build -j $(nproc) --target Kokkos_PerformanceTest_SIMD_Host
221+
./build/simd/perf_tests/Kokkos_PerformanceTest_SIMD_Host --benchmark_out=sleef.json --benchmark_filter="math .[^c]"
222+
- name: Compare the perf test results
223+
working-directory: ${{ github.workspace }}/kokkos
224+
run: |
225+
source ${{ env.compare_ROOT }}/venv/bin/activate
226+
${{ env.compare_ROOT }}/compare.py benchmarks baseline.json sleef.json

simd-backends/CMakeLists.txt

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# SPDX-FileCopyrightText: 2026 CExA-project
2+
# SPDX-License-Identifier: MIT or Apache-2.0 with LLVM-exception
3+
4+
cmake_minimum_required(VERSION 3.23)
5+
6+
project(simd-backends VERSION 0.1.0)
7+
8+
find_package(Kokkos 4.6 REQUIRED)
9+
10+
option(
11+
CEXA_SIMD_ENABLE_SLEEF
12+
"Use the sleef library to implement the simd math functions"
13+
OFF
14+
)
15+
option(CEXA_SIMD_ENABLE_SVML "Use the svml to implement the simd math functions" OFF)
16+
option(CEXA_SIMD_ENABLE_TESTS "Enable accuracy tests" OFF)
17+
18+
if(CEXA_SIMD_ENABLE_SLEEF AND CEXA_SIMD_ENABLE_SVML)
19+
message(FATAL_ERROR "Only one backend can be enabled at a time")
20+
endif()
21+
22+
if(CEXA_SIMD_ENABLE_SLEEF)
23+
find_package(sleef 3.6 QUIET)
24+
if(NOT sleef_FOUND)
25+
include(FetchContent)
26+
27+
set(SLEEF_BUILD_GNUABI_LIBS OFF)
28+
set(SLEEF_BUILD_TESTS OFF)
29+
set(SLEEF_ENABLE_TLFLOAT OFF)
30+
set(SLEEF_ENABLE_FFTW OFF)
31+
set(SLEEF_ENABLE_MPFR OFF)
32+
list(APPEND CMAKE_MESSAGE_INDENT "[sleef] ")
33+
FetchContent_Declare(
34+
sleef
35+
URL https://github.com/shibatch/sleef/archive/refs/tags/3.9.0.tar.gz
36+
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
37+
DOWNLOAD_NO_PROGRESS TRUE
38+
)
39+
FetchContent_MakeAvailable(sleef)
40+
list(POP_BACK CMAKE_MESSAGE_INDENT)
41+
endif()
42+
endif()
43+
44+
if(CEXA_SIMD_ENABLE_SVML AND NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL IntelLLVM)
45+
message(
46+
FATAL_ERROR
47+
"The SVML simd backend is only available with Intel compilers"
48+
)
49+
endif()
50+
51+
add_subdirectory(src)
52+
53+
if(CEXA_SIMD_ENABLE_TESTS)
54+
add_subdirectory(test)
55+
endif()
56+
57+
# Install
58+
include(GNUInstallDirs)
59+
60+
include(CMakePackageConfigHelpers)
61+
write_basic_package_version_file(
62+
CexaSimdBackendsConfigVersion.cmake
63+
COMPATIBILITY AnyNewerVersion
64+
)
65+
66+
install(
67+
TARGETS simd-backends
68+
EXPORT CexaSimdBackends
69+
FILE_SET HEADERS
70+
)
71+
72+
install(
73+
EXPORT CexaSimdBackends
74+
FILE CexaSimdBackendsTargets.cmake
75+
NAMESPACE cexa::
76+
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CexaSimdBackends"
77+
)
78+
79+
configure_package_config_file(
80+
cmake/CexaSimdBackendsConfig.cmake.in
81+
"${CMAKE_CURRENT_BINARY_DIR}/CexaSimdBackendsConfig.cmake"
82+
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CexaSimdBackends"
83+
)
84+
85+
install(
86+
FILES
87+
"${CMAKE_CURRENT_BINARY_DIR}/CexaSimdBackendsConfig.cmake"
88+
"${CMAKE_CURRENT_BINARY_DIR}/CexaSimdBackendsConfigVersion.cmake"
89+
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CexaSimdBackends"
90+
)

simd-backends/README.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<!--
2+
SPDX-FileCopyrightText: 2026 CExA-project
3+
4+
SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
5+
-->
6+
7+
# SIMD backends
8+
9+
This header only library provides an interface to replace the Kokkos math
10+
functions for SIMD types with calls to different external libraries.
11+
12+
## Build
13+
14+
The available cmake configuration options are:
15+
- `CEXA_SIMD_ENABLE_SLEEF`: use the sleef library
16+
- `CEXA_SIMD_ENABLE_SVML`: use the Intel SVML library (only available with intel compilers)
17+
- `CEXA_SIMD_ENABLE_TESTS`: build the tests
18+
19+
The sleef backend requires sleef v3.6.0 or later.
20+
21+
## Usage
22+
23+
With CMake, you can use the `find_package` command as shown in the
24+
example below. If not installed to a system location, you should provide the
25+
path to the library using the `-DCexaSimdBackends_ROOT=<path to the install location>`
26+
option.
27+
28+
```cmake
29+
cmake_minimum_required(VERSION 3.23)
30+
31+
project(test)
32+
33+
find_package(Kokkos REQUIRED)
34+
find_package(CexaSimdBackends REQUIRED)
35+
36+
add_executable(main main.cpp)
37+
target_link_libraries(main PRIVATE Kokkos::kokkos cexa::simd-backends)
38+
```
39+
40+
You can then include `CEXA_SIMD_Backends.hpp` in your code and use the Kokkos simd math
41+
functions as usual.
42+
43+
```cpp
44+
#include <Kokkos_Core.hpp>
45+
#include <Kokkos_SIMD.hpp>
46+
#include <CEXA_SIMD_Backends.hpp>
47+
48+
int main(int argc, char* argv[]) {
49+
Kokkos::ScopeGuard kokkos_scope(argc, argv);
50+
51+
Kokkos::Experimental::simd<float> vec(1.f);
52+
vec = Kokkos::exp(vec);
53+
54+
return 0;
55+
}
56+
```
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# SPDX-FileCopyrightText: 2026 CExA-project
2+
# SPDX-License-Identifier: MIT or Apache-2.0 with LLVM-exception
3+
4+
@PACKAGE_INIT@
5+
6+
include(CMakeFindDependencyMacro)
7+
8+
find_dependency(Kokkos)
9+
10+
set(CEXA_SIMD_ENABLE_SLEEF @CEXA_SIMD_ENABLE_SLEEF@)
11+
if(CEXA_SIMD_ENABLE_SLEEF)
12+
find_dependency(sleef)
13+
endif()
14+
15+
include("${CMAKE_CURRENT_LIST_DIR}/CexaSimdBackendsTargets.cmake")
16+
17+
check_required_components(CexaSimdBackends)

0 commit comments

Comments
 (0)