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
24 changes: 21 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,9 @@ option(CUDAQ_ENABLE_SANITIZERS "Enable Address Sanitizer (ASan) and Undefined Be

# Sub-projects that can be enabled independently, in the style of
# LLVM_ENABLE_PROJECTS. Accepts a semicolon-separated list.
set(CUDAQ_ALL_PROJECTS "cudaq;runtime;python")
set(CUDAQ_ALL_PROJECTS "cudaq;runtime;python;realtime")
set(CUDAQ_ENABLE_PROJECTS "" CACHE STRING
"Semicolon-separated list of CUDA-Q sub-projects to build. Valid values: ${CUDAQ_ALL_PROJECTS}. Defaults to 'cudaq;runtime' (plus 'python' if CUDAQ_ENABLE_PYTHON is set).")
"Semicolon-separated list of CUDA-Q sub-projects to build. Valid values: ${CUDAQ_ALL_PROJECTS}. Defaults to 'cudaq;runtime' (plus 'python' if CUDAQ_ENABLE_PYTHON is set). Include 'realtime' to build source-tree realtime; set CUDAQ_REALTIME_DIR to use an installed realtime package.")

# Back-compat: if CUDAQ_ENABLE_PROJECTS wasn't given, derive it from the
# legacy per-project flags so existing build scripts keep working, and warn
Expand Down Expand Up @@ -824,6 +824,13 @@ if (CUDAQ_REALTIME_DIR)
"CUDAQ_REALTIME_DIR requires CUDA support, but CUDA was not found.")
endif()

if ("realtime" IN_LIST CUDAQ_ENABLE_PROJECTS)
message(WARNING
"Both CUDAQ_REALTIME_DIR and 'realtime' in CUDAQ_ENABLE_PROJECTS were provided. "
"Using CUDAQ_REALTIME_DIR=${CUDAQ_REALTIME_DIR} and skipping the source-tree realtime build.")
list(REMOVE_ITEM CUDAQ_ENABLE_PROJECTS "realtime")
endif()

find_package(cudaq-realtime CONFIG REQUIRED
PATHS "${CUDAQ_REALTIME_DIR}"
NO_DEFAULT_PATH)
Expand All @@ -841,9 +848,17 @@ if (CUDAQ_REALTIME_DIR)

set(CUDAQ_ENABLE_REALTIME TRUE)
message(STATUS "CUDA-Q realtime integration enabled from: ${CUDAQ_REALTIME_DIR}")
elseif ("realtime" IN_LIST CUDAQ_ENABLE_PROJECTS)
if (NOT CUDA_FOUND)
message(FATAL_ERROR
"The \"realtime\" project requires CUDA support, but CUDA was not found.")
endif()

set(CUDAQ_ENABLE_REALTIME TRUE)
message(STATUS "CUDA-Q realtime integration enabled from the source tree.")
else()
message(STATUS
"CUDA-Q realtime integration disabled. Set CUDAQ_REALTIME_DIR to an installed cudaq-realtime prefix to enable it.")
"CUDA-Q realtime integration disabled. Include \"realtime\" in CUDAQ_ENABLE_PROJECTS to enable it.")
endif()

# Code coverage setup
Expand All @@ -868,6 +883,9 @@ endif()
if("cudaq" IN_LIST CUDAQ_ENABLE_PROJECTS)
add_subdirectory(cudaq)
endif()
if("realtime" IN_LIST CUDAQ_ENABLE_PROJECTS)
add_subdirectory(realtime)
endif()
if("runtime" IN_LIST CUDAQ_ENABLE_PROJECTS)
add_subdirectory(runtime)
endif()
Expand Down
4 changes: 3 additions & 1 deletion cmake/modules/CUDAQConfig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ if (CUDAQ_REALTIME_DIR)
else()
# Do not use find_dependency here: it inherits find_package(CUDAQ REQUIRED)
# and would make realtime mandatory for CUDA-Q installs that do not use it.
find_package(cudaq-realtime CONFIG QUIET)
find_package(cudaq-realtime CONFIG QUIET
PATHS "${CUDAQ_CMAKE_DIR}/../cudaq-realtime"
NO_DEFAULT_PATH)
endif()

get_filename_component(PARENT_DIRECTORY ${CUDAQ_CMAKE_DIR} DIRECTORY)
Expand Down
4 changes: 2 additions & 2 deletions cudaq/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,14 @@ if (CUDA_FOUND AND CUDAQ_ENABLE_REALTIME AND NOT CUDAQ_DISABLE_CPP_FRONTEND AND
cudaq-device-call-runtime
cudaq-device-call-runtime-headers
cudaq::cudaq-realtime-dispatch
CUDA::cudart)
CUDA::cudart_static)
target_compile_options(${target} PRIVATE
$<$<COMPILE_LANGUAGE:CUDA>:--expt-relaxed-constexpr>)
set_target_properties(${target}
PROPERTIES
CUDA_SEPARABLE_COMPILATION ON
CUDA_RESOLVE_DEVICE_SYMBOLS ON
CUDA_RUNTIME_LIBRARY Shared
CUDA_RUNTIME_LIBRARY Static
CUDA_STANDARD 20
CXX_STANDARD 20
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
Expand Down
2 changes: 2 additions & 0 deletions cudaq/test/lit.site.cfg.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ config.cuda_found = "@CUDA_FOUND@"
if cmake_boolvar_to_bool(config.cuda_found):
config.available_features.add('nvcc')

config.cuda_gpu_available = os.system("nvidia-smi >/dev/null 2>&1") == 0
if (cmake_boolvar_to_bool(config.cuda_found) and
config.cuda_gpu_available and
config.cudaq_device_call_realtime_libs and
all(os.path.exists(lib)
for lib in config.cudaq_device_call_realtime_libs)):
Expand Down
176 changes: 110 additions & 66 deletions realtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,29 @@ cmake_minimum_required(VERSION 3.22 FATAL_ERROR)

include(FetchContent)

# Set a default build type if none was specified. Must set this before
# project().
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel")
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(CUDAQ_REALTIME_STANDALONE_BUILD TRUE)
else()
set(CUDAQ_REALTIME_STANDALONE_BUILD FALSE)
Comment on lines +15 to +16

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: False can be set as a default outside the loop. This can help with getting rid of else.

endif()

if(CUDAQ_REALTIME_STANDALONE_BUILD)
# Set a default build type if none was specified. Must set this before
# project().
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel")

# Set a default install prefix if none was specified.
set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/.cudaq_realtime" CACHE STRING
"Install path prefix, prepended onto install directories")
# Set a default install prefix if none was specified.
set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/.cudaq_realtime" CACHE STRING
"Install path prefix, prepended onto install directories")
endif()

# Project setup
# ==============================================================================

# Check if core is built as a standalone project.
project(cudaq-realtime)
set(CUDAQ_REALTIME_STANDALONE_BUILD TRUE)
if(CUDAQ_REALTIME_STANDALONE_BUILD)
project(cudaq-realtime)
endif()

include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
Expand All @@ -45,81 +53,117 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# Options
# ==============================================================================

set(_cudaq_realtime_build_tests_default ON)
if(NOT CUDAQ_REALTIME_STANDALONE_BUILD)
set(_cudaq_realtime_build_tests_default OFF)
endif()

option(CUDAQ_REALTIME_BUILD_TESTS
"Generate build targets for the CUDAQ real-time unit tests" ON)
"Generate build targets for the CUDAQ real-time unit tests"
${_cudaq_realtime_build_tests_default})
option(CUDAQ_REALTIME_BUILD_EXAMPLES
"Generate build targets for the CUDAQ real-time example programs" ON)
option(CUDAQ_REALTIME_ENABLE_HOLOLINK_TOOLS
"Build Hololink bridge/emulator/playback tools (requires hololink)."
OFF)

set(_host_compiler_opts_list "")
if(CUDAQ_REALTIME_STANDALONE_BUILD)
list(APPEND _host_compiler_opts_list "-fPIC")
endif()

if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64" AND
CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12)
# nvcc cannot parse the GCC BF16 intrinsic headers exposed through
# <immintrin.h> on the CI toolchains.
list(APPEND _host_compiler_opts_list
"-D_AVX512BF16INTRIN_H_INCLUDED"
"-D_AVX512BF16VLINTRIN_H_INCLUDED"
"-D_AVXNECONVERTINTRIN_H_INCLUDED")
endif()

if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate (line 77) if loops condition? Can be merged into one.

# -mno-amx-tile alone is insufficient: the AMX intrinsic headers use
# #pragma GCC target("amx-*") which re-enables the builtins that nvcc
# cannot parse. Pre-define the include guards to skip those headers.
list(APPEND _host_compiler_opts_list
"-mno-amx-tile"
"-D_AMXTILEINTRIN_H_INCLUDED"
"-D_AMXBF16INTRIN_H_INCLUDED"
"-D_AMXINT8INTRIN_H_INCLUDED"
"-D_AMXFP16INTRIN_H_INCLUDED"
"-D_AMXCOMPLEXINTRIN_H_INCLUDED")
endif()
endif()

list(JOIN _host_compiler_opts_list "," _host_compiler_opts)

# Check for CUDA Support (ref: cuda-quantum/CMakeLists.txt)
# ==============================================================================
include(CheckLanguage)
check_language(CUDA)
set(CUDA_FOUND FALSE)
# Generate -gencode arch=compute_XX,code=sm_XX for list of supported
# arch values.
# List should be sorted in increasing order.
function(CUDA_get_gencode_args out_args_string arch_values)
# allow the user to pass the list like a normal variable
set(arch_list ${arch_values} ${ARGN})
set(out "")
foreach(arch IN LISTS arch_list)
set(out "${out} -gencode arch=compute_${arch},code=sm_${arch}")
endforeach(arch)

# Repeat the last one as to ensure the generation of PTX for most
# recent virtual architecture for forward compatibility
list(GET arch_list -1 last_arch)
set(out "${out} -gencode arch=compute_${last_arch},code=compute_${last_arch}")
set(${out_args_string} ${out} PARENT_SCOPE)
endfunction()

if(CMAKE_CUDA_COMPILER)
if (NOT CUDA_TARGET_ARCHS)
if (CUDAToolkit_VERSION VERSION_LESS 13.0)
# Ampere, Hopper
set(CUDA_TARGET_ARCHS "80;90")
else()
# Ampere, Hopper, Blackwell
set(CUDA_TARGET_ARCHS "80;90;100")
if(CUDAQ_REALTIME_STANDALONE_BUILD)
include(CheckLanguage)
check_language(CUDA)
set(CUDA_FOUND FALSE)
# Generate -gencode arch=compute_XX,code=sm_XX for list of supported
# arch values.
# List should be sorted in increasing order.
function(CUDA_get_gencode_args out_args_string arch_values)
# allow the user to pass the list like a normal variable
set(arch_list ${arch_values} ${ARGN})
set(out "")
foreach(arch IN LISTS arch_list)
set(out "${out} -gencode arch=compute_${arch},code=sm_${arch}")
endforeach(arch)

# Repeat the last one as to ensure the generation of PTX for most
# recent virtual architecture for forward compatibility
list(GET arch_list -1 last_arch)
set(out "${out} -gencode arch=compute_${last_arch},code=compute_${last_arch}")
set(${out_args_string} ${out} PARENT_SCOPE)
endfunction()

if(CMAKE_CUDA_COMPILER)
find_package(CUDAToolkit REQUIRED)
if (NOT CUDA_TARGET_ARCHS)
if (CUDAToolkit_VERSION VERSION_LESS 13.0)
# Ampere, Hopper
set(CUDA_TARGET_ARCHS "80;90")
else()
# Ampere, Hopper, Blackwell
set(CUDA_TARGET_ARCHS "80;90;100")
endif()
endif()
CUDA_get_gencode_args(CUDA_gencode_flags ${CUDA_TARGET_ARCHS})
# Keep realtime CUDA sources on C++17. nvcc's C++20 frontend can hit an
# internal compiler error in libstdc++ headers when compiling the standalone
# realtime tests, including test_host_dispatcher.cu, on the CI toolchain.
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -shared -std=c++17 ${CUDA_gencode_flags} --compiler-options ${_host_compiler_opts}")

enable_language(CUDA)
set(CUDA_FOUND TRUE)
set(CMAKE_CUDA_STANDARD 17)
Comment on lines +141 to +145

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I read the comment above but would like to go with C++20 here. Is it always the case that nvcc's C++20 frontend hit the internal compiler error? Or is there any workaround for the same?

set(CMAKE_CUDA_STANDARD_REQUIRED TRUE)
message(STATUS "Cuda language found.")
endif()
CUDA_get_gencode_args(CUDA_gencode_flags ${CUDA_TARGET_ARCHS})
set(_host_compiler_opts "-fPIC")
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64")
# -mno-amx-tile alone is insufficient with GCC 13+: the AMX intrinsic
# headers use #pragma GCC target("amx-tile") which re-enables the
# builtins that nvcc cannot parse. Pre-define the include guards to
# prevent these headers from being processed at all.
string(APPEND _host_compiler_opts ",-mno-amx-tile")
foreach(_amx_guard _AMXTILEINTRIN_H_INCLUDED
_AMXBF16INTRIN_H_INCLUDED
_AMXINT8INTRIN_H_INCLUDED
_AMXFP16INTRIN_H_INCLUDED
_AMXCOMPLEXINTRIN_H_INCLUDED)
string(APPEND _host_compiler_opts ",-D${_amx_guard}")
endforeach()
endif()
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -shared -std=c++17 ${CUDA_gencode_flags} --compiler-options ${_host_compiler_opts}")

enable_language(CUDA)
set(CUDA_FOUND TRUE)
set(CMAKE_CUDA_STANDARD 17)
set(CMAKE_CUDA_STANDARD_REQUIRED TRUE)
elseif(CUDA_FOUND)
find_package(CUDAToolkit REQUIRED)
message(STATUS "Cuda language found.")
if(_host_compiler_opts)
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -ccbin=${CMAKE_CXX_COMPILER} --compiler-options ${_host_compiler_opts}")
endif()
endif()

# External Dependencies
# ==============================================================================

find_package(Threads REQUIRED)

# Enable static linking of the C++ standard library to avoid dependency issues when distributing the library.
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++ -static-libgcc")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++ -static-libgcc")
if(CUDAQ_REALTIME_STANDALONE_BUILD)
# Standalone realtime owns its distribution linker policy. Integrated CUDA-Q
# builds inherit the top-level CUDA-Q runtime/dependency link settings.
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++ -static-libgcc")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++ -static-libgcc")
endif()

add_subdirectory(lib)

Expand Down
3 changes: 3 additions & 0 deletions realtime/lib/cpu_transport/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ add_library(cudaq-realtime-cpu-transport STATIC
roce_transceiver.cpp # class CpuRoceTransceiver: ibv setup, RX/TX threads, ring lifecycle
roce_wrapper.cpp # extern-C shim used by bridge tools and CpuRoceChannel
)
# Source-tree CUDA-Q integration uses the same cudaq:: target names
# that installed exports provide.
add_library(cudaq::cudaq-realtime-cpu-transport ALIAS cudaq-realtime-cpu-transport)

target_include_directories(cudaq-realtime-cpu-transport
PUBLIC
Expand Down
9 changes: 9 additions & 0 deletions realtime/lib/daemon/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ if(CUDA_FOUND)
)

add_library(cudaq-realtime SHARED ${CUDAQ_REALTIME_SOURCES})
# Source-tree CUDA-Q integration uses the same cudaq:: target names
# that installed exports provide.
add_library(cudaq::cudaq-realtime ALIAS cudaq-realtime)

target_include_directories(cudaq-realtime
PUBLIC
Expand Down Expand Up @@ -54,6 +57,9 @@ if(CUDA_FOUND)
add_library(cudaq-realtime-dispatch STATIC
dispatcher/dispatch_kernel.cu
)
# Source-tree CUDA-Q integration uses the same cudaq:: target names
# that installed exports provide.
add_library(cudaq::cudaq-realtime-dispatch ALIAS cudaq-realtime-dispatch)
set_target_properties(cudaq-realtime-dispatch
PROPERTIES
LINK_FLAGS_RELEASE "-Wl,--exclude-libs=ALL")
Expand Down Expand Up @@ -97,6 +103,9 @@ if(CUDA_FOUND)
dispatcher/host_dispatcher.cu
dispatcher/host_dispatcher_capi.cu
)
# Source-tree CUDA-Q integration uses the same cudaq:: target names
# that installed exports provide.
add_library(cudaq::cudaq-realtime-host-dispatch ALIAS cudaq-realtime-host-dispatch)

target_include_directories(cudaq-realtime-host-dispatch
PUBLIC
Expand Down
5 changes: 3 additions & 2 deletions realtime/unittests/utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,10 @@ if (GPU_ROCE_TRANSCEIVER_LIB AND
message(STATUS "Building hololink_bridge (generic increment)")
message(STATUS " GPU RoCE Transceiver: ${GPU_ROCE_TRANSCEIVER_LIB}")

# Hololink wrapper static library (compiled by g++, isolates fmt)
# Hololink wrapper static library (compiled by g++, isolates fmt).
# Use the realtime source root so this path works when nested in CUDA-Q.
add_library(hololink_wrapper_generic STATIC
${CMAKE_SOURCE_DIR}/lib/daemon/bridge/hololink/hololink_wrapper.cpp)
${CUDAQ_REALTIME_SOURCE_DIR}/lib/daemon/bridge/hololink/hololink_wrapper.cpp)

target_include_directories(hololink_wrapper_generic
PRIVATE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,5 +167,12 @@ using DeviceCallServicePluginInfoFn = DeviceCallServicePluginInfo (*)();
// Default service discovery entry point. Service artifacts may also expose
// suffixed variants with the same signature for tests or multi-service
// deployments, e.g. cudaqGetDeviceCallServicePluginInfo_<name>.
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
#endif
extern "C" cudaq_internal::device_call::DeviceCallServicePluginInfo
cudaqGetDeviceCallServicePluginInfo();
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
1 change: 1 addition & 0 deletions unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ create_tests_with_backend(stim backends/StimTester.cpp)

if (CUDA_FOUND AND CUDAQ_ENABLE_REALTIME)
add_executable(test_device_call_dispatch
device_call/DeviceCallDispatchTester.cpp
device_call/DeviceCallDispatchTester.cu)
set_target_properties(test_device_call_dispatch PROPERTIES
CUDA_SEPARABLE_COMPILATION ON
Expand Down
Loading
Loading