Skip to content

[cling] Prototype SYCL support in ROOT #17209

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ builtin_zstd=ON
builtin_zlib=ON
builtin_vdt=On
ccache=On
experimental_adaptivecpp=ON
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
builtin_zlib=ON
builtin_zstd=ON
ccache=ON
experimental_adaptivecpp=ON
vdt=OFF
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
ccache=ON
experimental_adaptivecpp=ON
pythia8=OFF
tmva-sofie=ON
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
experimental_adaptivecpp=ON
ccache=ON
pythia8=OFF
3 changes: 3 additions & 0 deletions bindings/pyroot/pythonizations/test/import_load_libs.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class ImportLoadLibs(unittest.TestCase):
"librt",
"libncurses.*",
"libtinfo", # by libncurses (on some older platforms)
# adaptivecpp and dependencies
"libacpp-rt",
"libgomp",
# libTree and dependencies
"libTree",
"libThread",
Expand Down
1 change: 1 addition & 0 deletions cmake/modules/RootBuildOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ ROOT_BUILD_OPTION(davix ON "Enable support for Davix (HTTP/WebDAV access)")
ROOT_BUILD_OPTION(dcache OFF "Enable support for dCache (requires libdcap from DESY)")
ROOT_BUILD_OPTION(dev OFF "Enable recommended developer compilation flags, reduce exposed includes")
ROOT_BUILD_OPTION(distcc OFF "Enable distcc usage for speeding up builds (ccache is called first if enabled)")
ROOT_BUILD_OPTION(experimental_adaptivecpp OFF "Build AdaptiveCPP for SYCL support")
ROOT_BUILD_OPTION(fcgi OFF "Enable FastCGI support in HTTP server")
ROOT_BUILD_OPTION(fftw3 OFF "Enable support for FFTW3 [GPL]")
ROOT_BUILD_OPTION(fitsio ON "Enable support for reading FITS images")
Expand Down
30 changes: 30 additions & 0 deletions cmake/modules/SearchInstalledSoftware.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -1592,6 +1592,36 @@ if (vecgeom)
endif()
endif()

if(experimental_adaptivecpp)
# Building adaptivecpp requires an internet connection, if we're not side-loading the source directory
if(NOT DEFINED ADAPTIVECPP_SOURCE_DIR)
ROOT_CHECK_CONNECTION_AND_DISABLE_OPTION("experimental_adaptivecpp")
endif()
include(SetupAdaptiveCpp)

add_compile_definitions(CLING_WITH_ADAPTIVECPP)

set(HIPSYCL_NO_FIBERS ON)
set(WITH_OPENCL_BACKEND OFF)
set(WITH_LEVEL_ZERO_BACKEND OFF)

find_package(AdaptiveCpp REQUIRED)
if (AdaptiveCpp_FOUND)
set(sycl ON)
set(SYCL_COMPILER_FLAGS "-ffast-math ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${_BUILD_TYPE_UPPER}}")
message(STATUS "SYCL compiler flags: ${SYCL_COMPILER_FLAGS}")
separate_arguments(SYCL_COMPILER_FLAGS NATIVE_COMMAND ${SYCL_COMPILER_FLAGS})
message(STATUS "AdaptiveCpp sycl enabled")
else()
if(fail-on-missing)
message(FATAL_ERROR "AdaptiveCpp library not found")
else()
message(STATUS "AdaptiveCpp library not found")
set(sycl OFF CACHE BOOL "Disabled because no SYCL implementation is not found" FORCE)
endif()
endif()
endif()

#---Check for protobuf-------------------------------------------------------------------

if(tmva-sofie)
Expand Down
116 changes: 116 additions & 0 deletions cmake/modules/SetupAdaptiveCpp.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
message(STATUS "Building AdaptiveCpp for SYCL support.")

include(FetchContent)

if(NOT DEFINED ADAPTIVE_CPP_SOURCE_DIR)
FetchContent_Declare(
AdaptiveCpp
GIT_REPOSITORY https://github.com/root-project/AdaptiveCpp.git
GIT_TAG ROOT-acpp-v25.02.0-20250615-01)
FetchContent_GetProperties(AdaptiveCpp)
if(NOT AdaptiveCpp_POPULATED)
FetchContent_Populate(AdaptiveCpp)
endif()
set(ADAPTIVE_CPP_SOURCE_DIR ${adaptivecpp_SOURCE_DIR})
message(STATUS "Fetched AdaptiveCpp source to: ${ADAPTIVE_CPP_SOURCE_DIR}")
else()
message(
STATUS "ADAPTIVE_CPP_SOURCE_DIR already defined: ${ADAPTIVE_CPP_SOURCE_DIR}"
)
endif()

set(LLVM_BINARY_DIR ${CMAKE_BINARY_DIR}/interpreter/llvm-project/llvm)
set(CLANG_EXECUTABLE_PATH ${LLVM_BINARY_DIR}/bin/clang${CMAKE_EXECUTABLE_SUFFIX})

set(ACPP_CLANG
${CLANG_EXECUTABLE_PATH}
CACHE STRING "Clang compiler executable used for compilation." FORCE)

set(ADAPTIVE_CPP_BINARY_DIR ${CMAKE_BINARY_DIR})
message(STATUS "AdaptiveCpp will be built in: ${ADAPTIVE_CPP_BINARY_DIR}")

set(ADAPTIVECPP_INSTALL_CMAKE_DIR
lib/cmake/AdaptiveCpp
CACHE PATH "Install path for CMake config files")

# Set relative paths for install root in the following variables so that
# configure_package_config_file will generate paths relative whatever is the
# future install root
set(ADAPTIVECPP_INSTALL_COMPILER_DIR bin)
set(ACPP_CONFIG_FILE_INSTALL_DIR etc/AdaptiveCpp)
set(ADAPTIVECPP_INSTALL_LAUNCHER_DIR ${ADAPTIVECPP_INSTALL_CMAKE_DIR})
set(ADAPTIVECPP_INSTALL_LAUNCHER_RULE_DIR ${ADAPTIVECPP_INSTALL_CMAKE_DIR})

install(FILES ${ADAPTIVE_CPP_BINARY_DIR}/lib/libacpp-rt.so DESTINATION lib)
install(DIRECTORY ${ADAPTIVE_CPP_BINARY_DIR}/lib/hipSYCL/bitcode/
DESTINATION lib/hipSYCL/bitcode)
install(DIRECTORY ${ADAPTIVE_CPP_BINARY_DIR}/include/AdaptiveCpp/
DESTINATION include/AdaptiveCpp)

file(
COPY ${ADAPTIVE_CPP_SOURCE_DIR}/cmake/syclcc-launcher
DESTINATION ${ADAPTIVE_CPP_BINARY_DIR}/${ADAPTIVECPP_INSTALL_LAUNCHER_DIR})
file(
COPY ${ADAPTIVE_CPP_SOURCE_DIR}/cmake/syclcc-launch.rule.in
DESTINATION ${ADAPTIVE_CPP_BINARY_DIR}/${ADAPTIVECPP_INSTALL_LAUNCHER_RULE_DIR})

list(APPEND CMAKE_PREFIX_PATH ${ADAPTIVE_CPP_BINARY_DIR}/${ADAPTIVECPP_INSTALL_CMAKE_DIR})
message(STATUS "Added ${ADAPTIVE_CPP_BINARY_DIR}/${ADAPTIVECPP_INSTALL_CMAKE_DIR} to CMAKE_PREFIX_PATH.")

install(PROGRAMS ${ADAPTIVE_CPP_BINARY_DIR}/bin/acpp
DESTINATION ${ADAPTIVECPP_INSTALL_COMPILER_DIR})
install(FILES ${ADAPTIVE_CPP_SOURCE_DIR}/cmake/syclcc-launcher
DESTINATION ${ADAPTIVECPP_INSTALL_LAUNCHER_DIR})
install(FILES ${ADAPTIVE_CPP_SOURCE_DIR}/cmake/syclcc-launch.rule.in
DESTINATION ${ADAPTIVECPP_INSTALL_LAUNCHER_RULE_DIR})

file(GLOB CLANG_EXECUTABLES "${LLVM_BINARY_DIR}/bin/clang*")
install(PROGRAMS ${CLANG_EXECUTABLES}
DESTINATION ${ADAPTIVECPP_INSTALL_COMPILER_DIR})

file(GLOB CONFIG_FILES "${ADAPTIVE_CPP_BINARY_DIR}/etc/AdaptiveCpp/*")
install(FILES ${CONFIG_FILES} DESTINATION ${ACPP_CONFIG_FILE_INSTALL_DIR})

# Create imported target AdaptiveCpp::acpp-common
add_library(AdaptiveCpp::acpp-common STATIC IMPORTED)

set_target_properties(AdaptiveCpp::acpp-common PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${ADAPTIVE_CPP_BINARY_DIR}/include;${ADAPTIVE_CPP_BINARY_DIR}/include/AdaptiveCpp"
INTERFACE_LINK_LIBRARIES "-Wl,-Bsymbolic-functions;\$<LINK_ONLY:dl>"
)

# Create imported target AdaptiveCpp::acpp-rt
add_library(AdaptiveCpp::acpp-rt SHARED IMPORTED)

set_target_properties(AdaptiveCpp::acpp-rt PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${ADAPTIVE_CPP_BINARY_DIR}/include;${ADAPTIVE_CPP_BINARY_DIR}/include/AdaptiveCpp"
INTERFACE_LINK_LIBRARIES "AdaptiveCpp::acpp-common"
)

# Import target "AdaptiveCpp::acpp-common" for configuration "Release"
set_property(TARGET AdaptiveCpp::acpp-common APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(AdaptiveCpp::acpp-common PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX"
IMPORTED_LOCATION_RELEASE "${ADAPTIVE_CPP_BINARY_DIR}/lib/libacpp-common.a"
)

# Import target "AdaptiveCpp::acpp-rt" for configuration "Release"
set_property(TARGET AdaptiveCpp::acpp-rt APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(AdaptiveCpp::acpp-rt PROPERTIES
IMPORTED_LOCATION_RELEASE "${ADAPTIVE_CPP_BINARY_DIR}/lib/libacpp-rt.so"
IMPORTED_SONAME_RELEASE "libacpp-rt.so"
)

# Make a config file to make this usable as a CMake Package
# Start by adding the version in a CMake understandable way
include(CMakePackageConfigHelpers)

configure_package_config_file(
${ADAPTIVE_CPP_SOURCE_DIR}/cmake/adaptivecpp-config.cmake.in
${ADAPTIVE_CPP_BINARY_DIR}/lib/cmake/AdaptiveCpp/adaptivecpp-config.cmake
INSTALL_DESTINATION ${ADAPTIVECPP_INSTALL_CMAKE_DIR}
PATH_VARS
ADAPTIVECPP_INSTALL_COMPILER_DIR
ADAPTIVECPP_INSTALL_LAUNCHER_DIR
ADAPTIVECPP_INSTALL_LAUNCHER_RULE_DIR
)
3 changes: 2 additions & 1 deletion core/metacling/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ if (clad)
else()
set(CLING_PLUGIN_LINK_LIBS -Wl,--whole-archive cladPlugin cladDifferentiator -Wl,--no-whole-archive)
endif()
if(TARGET clang)
# This will cause a cyclic dependency in adaptiveCpp, as it requires clang to build
if(TARGET clang AND NOT experimental_adaptivecpp)
# Link our clad libraries to clang. If users use the clang from ROOT they will
# also be able to use clad out of the box.
add_dependencies(clang clad)
Expand Down
9 changes: 9 additions & 0 deletions core/metacling/src/TCling.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1418,6 +1418,15 @@ TCling::TCling(const char *name, const char *title, const char* const argv[], vo
clingArgsStorage.push_back("-mllvm");
clingArgsStorage.push_back("-optimize-regalloc=0");
#endif

#ifdef CLING_WITH_ADAPTIVECPP
std::string acppInclude(TROOT::GetIncludeDir() + "/AdaptiveCpp");

clingArgsStorage.push_back("-isystem");
clingArgsStorage.push_back(acppInclude);
clingArgsStorage.push_back("-mllvm");
clingArgsStorage.push_back("-acpp-sscp");
#endif
}

// Process externally passed arguments if present.
Expand Down
12 changes: 11 additions & 1 deletion interpreter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ set(LLVM_FORCE_USE_OLD_TOOLCHAIN ON CACHE BOOL "")
# found before (because the user turned on cuda or tmva-gpu), this will not have
# an effect, which is fine.
# (Note that the option is very counter-intuitive: We turn *on* disabling it...)
set(CMAKE_DISABLE_FIND_PACKAGE_CUDA ON)
# Special case when we want to build cling with adaptiveCpp
if(NOT experimental_adaptivecpp)
set(CMAKE_DISABLE_FIND_PACKAGE_CUDA ON)
endif()

# will be set again in case NOT builtin_llvm
set(LLVM_DIR "${CMAKE_CURRENT_BINARY_DIR}/llvm-project/llvm")
Expand Down Expand Up @@ -214,6 +217,13 @@ if(builtin_llvm)

set(LLVM_ENABLE_PROJECTS "clang" CACHE STRING "")

if(experimental_adaptivecpp)
# Register AdaptiveCpp as an external project
set(LLVM_EXTERNAL_PROJECTS "AdaptiveCpp" CACHE STRING "")
set(LLVM_EXTERNAL_ADAPTIVECPP_SOURCE_DIR "${ADAPTIVE_CPP_SOURCE_DIR}" CACHE STRING "")
set(LLVM_ADAPTIVECPP_LINK_INTO_TOOLS ON CACHE BOOL "") # To force-link the plugin into clang
endif()

# Always build LLVM with C++17. It is not necessary to compile with the same
# C++ standard as the rest of ROOT and sometimes it doesn't even work.
set(_cxx_standard ${CMAKE_CXX_STANDARD})
Expand Down
8 changes: 8 additions & 0 deletions interpreter/cling/lib/Interpreter/BackendPasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@

#include <optional>

#ifdef CLING_WITH_ADAPTIVECPP
llvm::PassPluginLibraryInfo getAdaptiveCppPluginInfo();
#endif

using namespace cling;
using namespace clang;
using namespace llvm;
Expand Down Expand Up @@ -511,6 +515,10 @@ void BackendPasses::CreatePasses(int OptLevel, llvm::ModulePassManager& MPM,
std::optional<PGOOptions> PGOOpt;
PassBuilder PB(&m_TM, PTO, PGOOpt, &PIC);

#ifdef CLING_WITH_ADAPTIVECPP
getAdaptiveCppPluginInfo().RegisterPassBuilderCallbacks(PB);
#endif

// Attempt to load pass plugins and register their callbacks with PB.
for (auto& PluginFN : m_CGOpts.PassPlugins) {
auto PassPlugin = PassPlugin::Load(PluginFN);
Expand Down
7 changes: 7 additions & 0 deletions interpreter/cling/lib/Interpreter/CIFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1399,6 +1399,13 @@ namespace {
argvCompile.push_back("-fno-omit-frame-pointer");
}

#ifdef CLING_WITH_ADAPTIVECPP
argvCompile.push_back("-D__ACPP_ENABLE_LLVM_SSCP_TARGET__");
argvCompile.push_back("-Xclang");
argvCompile.push_back("-disable-O0-optnone");
if (!debuggingEnabled)
argvCompile.push_back("-ffp-contract=fast");
#endif
// Add host specific includes, -resource-dir if necessary, and -isysroot
std::string ClingBin = GetExecutablePath(argv[0]);
AddHostArguments(ClingBin, argvCompile, LLVMDir, COpts);
Expand Down
12 changes: 12 additions & 0 deletions interpreter/cling/lib/Interpreter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ set(LIBS
clangLex
)

if(experimental_adaptivecpp)
list(APPEND LIBS AdaptiveCpp acpp-rt)

set(ACPP_EXPORTS acpp-rt acpp-common)

foreach(target IN LISTS ACPP_EXPORTS)
install(TARGETS ${target} EXPORT ClingTargets)
endforeach()

set_property(GLOBAL APPEND PROPERTY CLING_EXPORTS ${ACPP_EXPORTS})
endif()

set(LLVM_LINK_COMPONENTS
analysis
core
Expand Down
2 changes: 2 additions & 0 deletions interpreter/cling/lib/Interpreter/IncrementalParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1033,9 +1033,11 @@ namespace cling {
// Don't protect against crashes if we cannot run anything.
// cling might also be in a PCH-generation mode; don't inject our Sema
// pointer into the PCH.
#ifndef CLING_WITH_ADAPTIVECPP
if (!isCUDADevice && m_Interpreter->getOptions().PtrCheck)
ASTTransformers.emplace_back(
new NullDerefProtectionTransformer(m_Interpreter));
#endif
if (isCUDADevice)
ASTTransformers.emplace_back(
new DeviceKernelInliner(TheSema));
Expand Down
4 changes: 2 additions & 2 deletions roottest/cling/exception/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
if(NOT MSVC OR win_broken_tests)
if((NOT MSVC OR win_broken_tests) AND NOT experimental_adaptivecpp)
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64.*|x86.*|amd64.*|AMD64.*|i686.*|i386.*")
# All platforms except of ARM/AARCH64
set(RootExeOptions "--ptrcheck")
Expand All @@ -9,7 +9,7 @@ if(NOT MSVC OR win_broken_tests)
endif()
endif()

if(NOT (APPLE AND CMAKE_SYSTEM_PROCESSOR MATCHES arm64) OR M1_BROKEN_TESTS)
if((NOT (APPLE AND CMAKE_SYSTEM_PROCESSOR MATCHES arm64) OR M1_BROKEN_TESTS) AND NOT experimental_adaptivecpp)
ROOTTEST_ADD_TEST(nullderef-e
COMMAND ${ROOT_root_CMD} -l -b -q --ptrcheck -e "int*p=nullptr" -e "*p"
PASSRC 1
Expand Down
7 changes: 7 additions & 0 deletions roottest/cling/sycl/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
if(experimental_adaptivecpp)
ROOTTEST_ADD_TEST(syclbasic
MACRO syclbasic.C
LABELS roottest regression cling sycl)
set_property(TEST roottest-cling-sycl-syclbasic PROPERTY ENVIRONMENT "ACPP_DEBUG_LEVEL=1")
endif()

16 changes: 16 additions & 0 deletions roottest/cling/sycl/syclbasic.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <sycl/sycl.hpp>
#include <iostream>

void syclbasic()
{
sycl::queue q{sycl::cpu_selector_v}; // Only openMP CPU backend is supported right now
std::cout << "Running on: " << q.get_device().get_info<sycl::info::device::name>() << "\n";

int a = 2, b = 3;
int *sum = sycl::malloc_shared<int>(1, q);

q.single_task([=] { *sum = a + b; }).wait();
std::cout << "Sum = " << *sum << '\n';

sycl::free(sum, q);
}
3 changes: 3 additions & 0 deletions roottest/cling/sycl/syclbasic.ref
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

Running on: AdaptiveCpp OpenMP host device
Sum = 5
2 changes: 1 addition & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ ROOT_EXECUTABLE(guitest guitest.cxx LIBRARIES RIO Gui Gpad Hist)
#ROOT_ADD_TEST(test-hsimple COMMAND hsimple)

#---invalid pointer checks---------------------------------------------------------------------
if(NOT (APPLE AND CMAKE_SYSTEM_PROCESSOR MATCHES arm64) OR M1_BROKEN_TESTS)
if((NOT (APPLE AND CMAKE_SYSTEM_PROCESSOR MATCHES arm64) OR M1_BROKEN_TESTS) AND NOT experimental_adaptivecpp)
ROOT_ADD_TEST(test-check-nullptr
COMMAND ${ROOT_root_CMD} -b -q -l --ptrcheck -e "int*ptr=(int*)0" -e "*ptr"
PASSREGEX "dereference null pointer")
Expand Down
Loading