Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions .github/workflows/celerity_ci_windows.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
name: Celerity Windows CI

on:
push:
branches:
- master
pull_request:
workflow_dispatch:

jobs:
build-and-test-windows:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
compiler: [clang-cl] # future proofing: potentially add more compilers in the future like msvc...
build_type: [Debug, Release]
defaults:
run:
shell: pwsh
env:
SIMSYCL_DIR: ${{ github.workspace }}\SimSYCL
SIMSYCL_INSTALL_DIR: ${{ github.workspace }}\simsycl-install
SIMSYCL_SYSTEM: ${{ github.workspace }}\ci\simsycl-system.json
EXTRA_LINKER_FLAGS: ""
steps:
- uses: actions/checkout@v4
with:
submodules: true

- name: Set up MSVC developer environment
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64

- name: Locate preinstalled LLVM
if: matrix.compiler == 'clang-cl'
run: |
$llvmDir = "C:\Program Files\LLVM"
$clangMajor = (Get-ChildItem "$llvmDir\lib\clang").Name
clang-cl.exe --version
"LIB=$llvmDir\lib\clang\$clangMajor\lib\windows;$env:LIB" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
"EXTRA_LINKER_FLAGS=clang_rt.builtins-x86_64.lib" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

- name: Locate preinstalled vcpkg
run: |
"BOOST_PREFIX_PATH=$env:VCPKG_INSTALLATION_ROOT\installed\x64-windows-static-md" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
$commit = git -C "$env:VCPKG_INSTALLATION_ROOT" rev-parse --short HEAD
"VCPKG_COMMIT=$commit" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

- name: Cache vcpkg-built Boost.Context
id: cache-boost
uses: actions/cache@v4
with:
path: ${{ env.BOOST_PREFIX_PATH }}
key: windows-vcpkg-boost-context-${{ env.VCPKG_COMMIT }}

- name: Build Boost.Context via vcpkg
if: steps.cache-boost.outputs.cache-hit != 'true'
run: '& "$env:VCPKG_INSTALLATION_ROOT\vcpkg.exe" install boost-context:x64-windows-static-md'

- name: Resolve SimSYCL commit
run: |
$sha = (git ls-remote https://github.com/celerity/SimSYCL.git HEAD).Split("`t")[0]
"SIMSYCL_COMMIT=$sha" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

- name: Cache SimSYCL install
id: cache-simsycl
uses: actions/cache@v4
with:
path: ${{ env.SIMSYCL_INSTALL_DIR }}
key: windows-simsycl-${{ matrix.compiler }}-${{ matrix.build_type }}-${{ env.SIMSYCL_COMMIT }}

- name: Clone SimSYCL
if: steps.cache-simsycl.outputs.cache-hit != 'true'
run: git clone --depth 1 https://github.com/celerity/SimSYCL.git "${{ env.SIMSYCL_DIR }}"

- name: Configure SimSYCL
if: steps.cache-simsycl.outputs.cache-hit != 'true'
run: >
cmake -S "${{ env.SIMSYCL_DIR }}" -B "${{ env.SIMSYCL_DIR }}\build" -G Ninja
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
-DCMAKE_C_COMPILER=${{ matrix.compiler }}.exe
-DCMAKE_CXX_COMPILER=${{ matrix.compiler }}.exe
-DCMAKE_PREFIX_PATH="${{ env.BOOST_PREFIX_PATH }}"
-DCMAKE_INSTALL_PREFIX="${{ env.SIMSYCL_INSTALL_DIR }}"
"-DCMAKE_EXE_LINKER_FLAGS=${{ env.EXTRA_LINKER_FLAGS }}"
"-DCMAKE_SHARED_LINKER_FLAGS=${{ env.EXTRA_LINKER_FLAGS }}"
"-DCMAKE_MODULE_LINKER_FLAGS=${{ env.EXTRA_LINKER_FLAGS }}"

- name: Build SimSYCL
if: steps.cache-simsycl.outputs.cache-hit != 'true'
run: cmake --build "${{ env.SIMSYCL_DIR }}\build"

- name: Run SimSYCL's own test suite
if: steps.cache-simsycl.outputs.cache-hit != 'true'
run: '& "${{ env.SIMSYCL_DIR }}\build\test\tests.exe" --reporter compact'

- name: Install SimSYCL
if: steps.cache-simsycl.outputs.cache-hit != 'true'
run: cmake --install "${{ env.SIMSYCL_DIR }}\build"

- name: Configure Celerity
run: >
cmake -S "${{ github.workspace }}" -B "${{ github.workspace }}\build" -G Ninja
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
-DCMAKE_C_COMPILER=${{ matrix.compiler }}.exe
-DCMAKE_CXX_COMPILER=${{ matrix.compiler }}.exe
-DCMAKE_PREFIX_PATH="${{ env.SIMSYCL_INSTALL_DIR }};${{ env.BOOST_PREFIX_PATH }}"
-DCELERITY_SYCL_IMPL=SimSYCL
-DCELERITY_ENABLE_MPI=OFF
-DCELERITY_USE_MIMALLOC=OFF
"-DCMAKE_EXE_LINKER_FLAGS=${{ env.EXTRA_LINKER_FLAGS }}"
"-DCMAKE_SHARED_LINKER_FLAGS=${{ env.EXTRA_LINKER_FLAGS }}"
"-DCMAKE_MODULE_LINKER_FLAGS=${{ env.EXTRA_LINKER_FLAGS }}"

- name: Build Celerity
run: cmake --build "${{ github.workspace }}\build"

- name: Run unit tests
run: '& "${{ github.workspace }}\build\test\all_tests.exe" --reporter compact'

- name: Upload build logs (on failure)
if: failure()
uses: actions/upload-artifact@v4
with:
name: windows-${{ matrix.compiler }}-${{ matrix.build_type }}-simsycl-build-logs
path: |
${{ github.workspace }}\build\CMakeFiles\CMakeError.log
${{ github.workspace }}\build\CMakeFiles\CMakeOutput.log
${{ env.SIMSYCL_DIR }}\build\CMakeFiles\CMakeError.log
${{ env.SIMSYCL_DIR }}\build\CMakeFiles\CMakeOutput.log
if-no-files-found: ignore
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ This release is WIP
### Internal

- Adapt tests for Windows by disabling implementation-dependent graph printing tests and increasing tolerances for executor timing tests (#337)
- Add automated CI compilation and testing of Celerity for Windows with clang-cl (#341)

## [0.7.0] - 2025-08-18

Expand Down
31 changes: 30 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,35 @@ macro(fetch_content_from_submodule DEPNAME RELPATH)
endif()
endmacro()

function(mark_include_dirs_system TARGET_NAME)
if(TARGET ${TARGET_NAME})
set(CELERITY_DETAIL_REAL_TARGET ${TARGET_NAME})
get_target_property(CELERITY_DETAIL_ALIASED_TARGET ${TARGET_NAME} ALIASED_TARGET)
if(CELERITY_DETAIL_ALIASED_TARGET)
set(CELERITY_DETAIL_REAL_TARGET ${CELERITY_DETAIL_ALIASED_TARGET})
endif()
get_target_property(CELERITY_DETAIL_SYSTEM_INCLUDES ${CELERITY_DETAIL_REAL_TARGET} INTERFACE_INCLUDE_DIRECTORIES)
if(CELERITY_DETAIL_SYSTEM_INCLUDES)
set_target_properties(${CELERITY_DETAIL_REAL_TARGET} PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${CELERITY_DETAIL_SYSTEM_INCLUDES}")
endif()
endif()
endfunction()

if (CELERITY_SYCL_IMPL STREQUAL "SimSYCL")
mark_include_dirs_system(SimSYCL::simsycl)
endif()

set(FMT_INSTALL ON CACHE BOOL "" FORCE)
fetch_content_from_submodule(fmt vendor/fmt)
mark_include_dirs_system(fmt::fmt)

set(SPDLOG_INSTALL ON CACHE BOOL "" FORCE)
set(SPDLOG_FMT_EXTERNAL ON CACHE BOOL "" FORCE)
fetch_content_from_submodule(spdlog vendor/spdlog)
mark_include_dirs_system(spdlog::spdlog)

fetch_content_from_submodule(small_vector vendor/small_vector)
mark_include_dirs_system(gch::small_vector)

if(WIN32)
# Catch2 uses custom top-level exception filters that conflict with MSMPI, which also uses their own filters.
Expand All @@ -174,9 +195,12 @@ if(WIN32)
endif()
fetch_content_from_submodule(Catch2 vendor/Catch2)
list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras)
mark_include_dirs_system(Catch2::Catch2)
mark_include_dirs_system(Catch2::Catch2WithMain)

set(LIBENVPP_INSTALL ON CACHE BOOL "" FORCE)
fetch_content_from_submodule(libenvpp vendor/libenvpp)
mark_include_dirs_system(libenvpp::libenvpp)

if(CELERITY_USE_MIMALLOC)
set(MI_OVERRIDE ON CACHE BOOL "" FORCE)
Expand All @@ -185,6 +209,7 @@ if(CELERITY_USE_MIMALLOC)
set(MI_BUILD_OBJECT OFF CACHE BOOL "" FORCE)
set(MI_BUILD_TESTS OFF CACHE BOOL "" FORCE)
fetch_content_from_submodule(mimalloc vendor/mimalloc)
mark_include_dirs_system(mimalloc)
endif()

if(CELERITY_TRACY_SUPPORT)
Expand All @@ -200,6 +225,7 @@ if(CELERITY_TRACY_SUPPORT)
endif()
fetch_content_from_submodule(Tracy vendor/tracy)
set(CMAKE_CXX_FLAGS "${PREVIOUS_CMAKE_CXX_FLAGS}")
mark_include_dirs_system(Tracy::TracyClient)
endif()

# Deprecated feature flags
Expand Down Expand Up @@ -404,7 +430,10 @@ add_sycl_to_target(
)

if(MSVC)
target_compile_options(celerity_runtime PRIVATE /MP /W3)
target_compile_options(celerity_runtime PRIVATE /W4 /wd4100 /we4715 /we4700)
if(CMAKE_GENERATOR MATCHES "Visual Studio")
target_compile_options(celerity_runtime PRIVATE /MP)
endif()
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
target_compile_options(celerity_runtime PRIVATE -Wall -Wextra -Wno-unused-parameter -Werror=return-type -Werror=init-self -Werror=undef)
endif()
Expand Down
1 change: 1 addition & 0 deletions docs/platform-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Those are (CRT = Intel Compute Runtime, L0 = oneAPI Level Zero):
| AdaptiveCpp | [`v24.06.0`](https://github.com/AdaptiveCpp/AdaptiveCpp/tree/v24.06.0) (Clang 14.0, CUDA 11.8.0) | Ubuntu 22.04 | NVIDIA RTX 2070 | Debug, Release |
| AdaptiveCpp | [`HEAD`](https://github.com/AdaptiveCpp/AdaptiveCpp) (Clang 18.0, CUDA 12.5.0)\* | Ubuntu 24.04 | NVIDIA RTX 2070 | Debug, Release |
| SimSYCL | [`HEAD`](https://github.com/celerity/SimSYCL) (GCC 13.2) | Ubuntu 24.04 | (None) | Debug, Release |
| SimSYCL | [`HEAD`](https://github.com/celerity/SimSYCL) (Clang 20.1.8) | Windows | (None) | Debug, Release |

\* currently requires a patch for an illegal macro definition in CUDA:

Expand Down
5 changes: 4 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ function(add_example NAME)
)

if(MSVC)
target_compile_options("${NAME}" PRIVATE /D_CRT_SECURE_NO_WARNINGS /MP /W3)
target_compile_options("${NAME}" PRIVATE /D_CRT_SECURE_NO_WARNINGS /W4 /wd4100 /we4715 /we4700)
if(CMAKE_GENERATOR MATCHES "Visual Studio")
target_compile_options("${NAME}" PRIVATE /MP)
endif()
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
target_compile_options("${NAME}" PRIVATE -Wall -Wextra -Wno-unused-parameter)
endif()
Expand Down
2 changes: 1 addition & 1 deletion src/backend/sycl_backend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ sycl_backend::sycl_backend(const std::vector<sycl::device>& devices, const confi
for(device_id did = 0; did < m_impl->system.devices.size(); ++did) {
m_impl->devices[did].submission_thread.emplace(named_threads::task_type_device_submitter(did.value), m_impl->config.profiling);
// no need to wait for the event -> will happen before the first task is submitted
(void)m_impl->devices[did].submission_thread->submit([did] { closure_hydrator::make_available(); });
(void)m_impl->devices[did].submission_thread->submit([] { closure_hydrator::make_available(); });
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ function(set_test_target_parameters TARGET SOURCE)
set_property(TARGET ${TARGET} PROPERTY POSITION_INDEPENDENT_CODE ON)

if(MSVC)
target_compile_options(${TARGET} PRIVATE /D_CRT_SECURE_NO_WARNINGS /MP /W3 /bigobj)
target_compile_options(${TARGET} PRIVATE /D_CRT_SECURE_NO_WARNINGS /W4 /wd4100 /wd4189 /we4715 /we4700 /bigobj)
if(CMAKE_GENERATOR MATCHES "Visual Studio")
target_compile_options(${TARGET} PRIVATE /MP)
endif()
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
target_compile_options(${TARGET} PRIVATE -Wall -Wextra -Wextra -Wno-unused-parameter -Wno-unused-variable)
endif()
Expand Down
14 changes: 12 additions & 2 deletions test/affinity_tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,25 @@ TEST_CASE("a warning is emitted if insufficient cores are available", "[affinity
}

TEST_CASE("a warning is emitted if hardcoded threads are not available to this process", "[affinity]") {
const core_set process_mask = {0, 1, 2, 3, 4};
if(!have_cores(process_mask)) {
SKIP("Skipping test because not all needed cores are available");
return;
}
test_utils::allow_max_log_level(detail::log_level::warn);
raii_affinity_masking mask({0, 1, 2, 3, 4});
raii_affinity_masking mask(process_mask);

detail::thread_pinning::thread_pinner pinner({.enabled = true, .use_backend_device_submission_threads = false, .hardcoded_core_ids = {4, 5, 6}});
CHECK(test_utils::log_contains_substring(detail::log_level::warn, "Not all hardcoded core IDs are available, downgrading to auto-pinning."));
}

TEST_CASE("do not plan for device submission threads if they are unused", "[affinity]") {
raii_affinity_masking mask({1, 2, 3, 4});
const core_set process_mask = {1, 2, 3, 4};
if(!have_cores(process_mask)) {
SKIP("Skipping test because not all needed cores are available");
return;
}
raii_affinity_masking mask(process_mask);
const detail::thread_pinning::runtime_configuration cfg = {.enabled = true, .num_devices = 10, .use_backend_device_submission_threads = false};
detail::thread_pinning::thread_pinner pinner(cfg);
SUCCEED(); // no additional check, a warning will make the test fail if we do not handle this case correctly
Expand Down
2 changes: 0 additions & 2 deletions test/command_graph_general_tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,6 @@ TEST_CASE("all commands have a transitive true-dependency on the preceding epoch

TEST_CASE("fences introduce dependencies on host objects", "[command_graph_generator][command-graph][fence]") {
const size_t num_nodes = 2;
const range<1> node_range{num_nodes};

cdag_test_context cctx(num_nodes);

Expand All @@ -362,7 +361,6 @@ TEST_CASE("fences introduce dependencies on host objects", "[command_graph_gener

TEST_CASE("fences introduce dependencies on buffers", "[command_graph_generator][command-graph][fence]") {
const size_t num_nodes = 2;
const range<1> node_range{num_nodes};

cdag_test_context cctx(num_nodes);

Expand Down
1 change: 0 additions & 1 deletion test/dag_benchmarks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,6 @@ template <typename BenchmarkContext>
step(up, u);

auto t = 0.0;
size_t i = 0;
while(t < T) {
step(up, u);
std::swap(u, up);
Expand Down
2 changes: 1 addition & 1 deletion test/out_of_order_engine_tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ TEST_CASE("eagerly-assignable instructions become immediately assignable once th
out_of_order_test_context octx(1);
auto k1 = octx.device_kernel({}, device_id(0), /* priority */ 0);
auto k2 = octx.device_kernel({k1}, device_id(0), /* priority */ 1);
auto k3 = octx.device_kernel({k1}, device_id(0), /* priority */ 0);
[[maybe_unused]] auto k3 = octx.device_kernel({k1}, device_id(0), /* priority */ 0);
auto k4 = octx.device_kernel({k2}, device_id(0), /* priority */ 2);

const auto first = octx.assign_one();
Expand Down
6 changes: 4 additions & 2 deletions test/test_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,9 @@ namespace celerity::test_utils_detail {

const char* const expected_runtime_init_warnings_regex = "Celerity has detected that only .* logical cores are available to this process.*|"
"Celerity detected more than one node \\(MPI rank\\) on this host, which is not recommended.*|"
"Instrumentation for profiling with Tracy is enabled\\. Performance may be negatively impacted\\.|";
"Instrumentation for profiling with Tracy is enabled\\. Performance may be negatively impacted\\.|"
"Insufficient logical cores available for thread pinning \\(required .* starting from .*, .* "
"available\\), disabling pinning\\. Performance may be negatively impacted\\.|";

const char* const expected_device_enumeration_warnings_regex = "Found fewer devices .* than local nodes .*, multiple nodes will use the same device.*";

Expand All @@ -253,7 +255,7 @@ const char* const expected_backend_fallback_warnings_regex =
const char* const expected_dry_run_executor_warnings_regex = "Encountered a \"fence\" command while \"CELERITY_DRY_RUN_NODES\" is set. The result of this "
"operation will not match the expected output of an actual run.";

const char* const expected_executor_progress_warnings_regex = "\\[executor\\] no progress for .* s, might be stuck.*";
[[maybe_unused]] const char* const expected_executor_progress_warnings_regex = "\\[executor\\] no progress for .* s, might be stuck.*";

const char* const expected_starvation_warning_regex =
"The executor was starved for instructions for [0-9]+\\.[0-9] .{0,2}s, or [0-9]+\\.[0-9]% of the total active time of [0-9]+\\.[0-9] .{0,2}s. This may "
Expand Down
Loading