mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2026-10-13 00:08:26 +08:00
CUDA 13.4 samples update - v13.4-public
Release 13.4 of the CUDA Samples supported by CUDA Toolkit 13.4. See Changelog for more information.
This commit is contained in:
@@ -71,8 +71,8 @@ find_file(LIBNVVM_HOME nvvm PATHS "$ENV{LIBNVVM_HOME}" "${CUDA_HOME}")
|
||||
message(STATUS "Using LIBNVVM_HOME: ${LIBNVVM_HOME}")
|
||||
|
||||
# Find libNVVM and nvvm.h.
|
||||
# (Linux: nvvm/lib64, windows: nvvm/lib/x64)
|
||||
find_library(NVVM_LIB nvvm PATHS "${LIBNVVM_HOME}/lib64" "${LIBNVVM_HOME}/lib/x64")
|
||||
# (Linux: nvvm/lib64, windows: nvvm/lib/x64, windows on arm:nvvm/lib/arm64)
|
||||
find_library(NVVM_LIB nvvm PATHS "${LIBNVVM_HOME}/lib64" "${LIBNVVM_HOME}/lib/x64" "${LIBNVVM_HOME}/lib/arm64")
|
||||
find_file(NVVM_H nvvm.h PATH "${LIBNVVM_HOME}/include")
|
||||
get_filename_component(NVVM_INCLUDE_DIR ${NVVM_H} DIRECTORY)
|
||||
include_directories(${NVVM_INCLUDE_DIR})
|
||||
@@ -110,7 +110,9 @@ include_directories("${CMAKE_CURRENT_SOURCE_DIR}/common/include")
|
||||
# invocation. See the note about "cuda-c-linking" in README.md.
|
||||
if (ENABLE_CUDA_C_LINKING_SAMPLE)
|
||||
# Include the LLVM dev package which is required to build cuda-c-linking.
|
||||
find_package(LLVM CONFIG PATHS "$ENV{LLVM_HOME}")
|
||||
# LLVM_HOME is a HINTS entry rather than a PATHS one so that it is searched
|
||||
# before the system directories, letting it select among installed LLVMs.
|
||||
find_package(LLVM CONFIG HINTS "$ENV{LLVM_HOME}")
|
||||
if (LLVM_FOUND)
|
||||
add_subdirectory(cuda-c-linking)
|
||||
else ()
|
||||
|
||||
@@ -71,27 +71,50 @@ update the CMake invocation in utils/build.sh or build.bat by adding
|
||||
A Note About the cuda-c-linking Sample
|
||||
--------------------------------------
|
||||
|
||||
This sample requires a development package (or locally-built) LLVM library
|
||||
between versions 7 to 14 inclusive. LLVM 15 defaults to using opaque pointers,
|
||||
which are not supported in libNVVM for pre-Blackwell architectures.
|
||||
This sample requires a development package (or locally-built) LLVM library,
|
||||
version 7 or newer.
|
||||
|
||||
The LLVM_HOME environment variable is required for users who wish to build the
|
||||
cuda-c-linking sample and have a locally built copy of LLVM that they wish to
|
||||
use. That sample requires the development package of LLVM with the LLVM header
|
||||
files and libraries.
|
||||
Which LLVM versions are usable depends on the GPU the sample runs on. LLVM 15
|
||||
and newer emit opaque pointers, and libNVVM accepts those only for Blackwell
|
||||
and later architectures; older architectures require the typed pointers that
|
||||
LLVM 14 and older emit. The sample queries libNVVM for the LLVM IR version its
|
||||
target accepts, so building against a newer LLVM and running on a pre-Blackwell
|
||||
device reports the requirement and exits with code 2 rather than failing. Use
|
||||
LLVM 7 to 14 if you need a single build that runs on any supported device.
|
||||
|
||||
The LLVM_HOME environment variable selects which LLVM to build against. It is
|
||||
required for users who have a locally built copy of LLVM they wish to use, and
|
||||
it also picks between installed versions: several LLVM versions install side by
|
||||
side, so a newer default LLVM does not prevent building this sample against an
|
||||
older one. With more than one installed and LLVM_HOME unset, which of them is
|
||||
found is unspecified, so set it explicitly. Whichever copy is used has to be a
|
||||
development install, with the LLVM header files and libraries.
|
||||
|
||||
If the LLVM dependencies are met, the user can enable the building of this
|
||||
sample by setting the CMake variable "ENABLE_CUDA_C_LINKING_SAMPLE" from either
|
||||
the command line invocation of CMake or by modifying the CMakeLists.txt in this
|
||||
directory.
|
||||
|
||||
Windows users should download LLVM 14 sources from llvm.org and build+install
|
||||
Windows users should download LLVM sources from llvm.org and build+install
|
||||
LLVM locally. Using the llvm.org provided Windows installer lacks some of
|
||||
the required components the cuda-c-linking sample depends on.
|
||||
|
||||
For Ubuntu users, the "llvm-dev" package contains the LLVM headers and libraries
|
||||
this sample requires, the user should not have to explicitly define an LLVM_HOME
|
||||
in this case.
|
||||
For Ubuntu users, the "llvm-dev" package contains the LLVM headers and
|
||||
libraries this sample requires, and is found without any further configuration.
|
||||
Note that "llvm-dev" is an unversioned metapackage that tracks the
|
||||
distribution's current LLVM: on Ubuntu 24.04 it installs "llvm-18-dev", which
|
||||
runs only on Blackwell and later. To build for an older device, add the
|
||||
versioned package and select it explicitly:
|
||||
|
||||
```bash
|
||||
sudo apt install llvm-14-dev
|
||||
LLVM_HOME=/usr/lib/llvm-14 cmake -S . -B build -DENABLE_CUDA_C_LINKING_SAMPLE=1
|
||||
```
|
||||
|
||||
LLVM 15 and newer reference zstd from their CMake package, which the Ubuntu
|
||||
"llvm-*-dev" packages do not pull in. Install "libzstd-dev" alongside them,
|
||||
or CMake fails while loading the LLVM package with a missing
|
||||
"zstd::libzstd_shared" target.
|
||||
|
||||
Windows users will want to build this sample using the same CMake build mode
|
||||
as they built LLVM with. For instance if they built LLVM in Release mode,
|
||||
|
||||
@@ -25,26 +25,46 @@
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
message(STATUS "Found LLVM Version ${LLVM_PACKAGE_VERSION}")
|
||||
if (LLVM_PACKAGE_VERSION VERSION_GREATER_EQUAL "15" OR
|
||||
LLVM_PACKAGE_VERSION VERSION_LESS "7")
|
||||
message(STATUS "The cuda-c-linking sample is expected to build with "
|
||||
"LLVM development libraries v7 to v14, opaque pointers are "
|
||||
"not supported in libNVVM for pre-Blackwell architectures.")
|
||||
if (LLVM_PACKAGE_VERSION VERSION_LESS "7")
|
||||
message(STATUS "The cuda-c-linking sample requires LLVM development "
|
||||
"libraries v7 or newer.")
|
||||
return()
|
||||
endif ()
|
||||
if (LLVM_PACKAGE_VERSION VERSION_GREATER_EQUAL "15")
|
||||
message(STATUS "LLVM 15 and newer emit opaque pointers, which libNVVM "
|
||||
"accepts only for Blackwell and later architectures. The "
|
||||
"cuda-c-linking sample will build, and reports the "
|
||||
"requirement at run time if the device is older. Build "
|
||||
"against LLVM 14 or older to run on pre-Blackwell devices.")
|
||||
endif ()
|
||||
|
||||
add_executable(cuda-c-linking cuda-c-linking.cpp)
|
||||
|
||||
# LLVM 16 and newer headers use C++17 constructs, so build the sample as C++17
|
||||
# when they are in use. Older LLVM versions keep the compiler default.
|
||||
if (LLVM_PACKAGE_VERSION VERSION_GREATER_EQUAL "16")
|
||||
target_compile_features(cuda-c-linking PRIVATE cxx_std_17)
|
||||
endif ()
|
||||
|
||||
add_test(NAME cuda-c-linking
|
||||
COMMAND cuda-c-linking
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
# The sample exits with 2 when the device cannot accept the IR this build
|
||||
# emits, which is a requirement it does not meet rather than a failure.
|
||||
set_tests_properties(cuda-c-linking PROPERTIES SKIP_RETURN_CODE 2)
|
||||
target_link_libraries(cuda-c-linking ${NVVM_LIB} ${CUDA_LIB})
|
||||
|
||||
# See https://llvm.org/docs/CMake.html#developing-llvm-passes-out-of-source
|
||||
separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS})
|
||||
add_definitions(${LLVM_DEFINITIONS_LIST})
|
||||
include_directories(${LLVM_INCLUDE_DIRS})
|
||||
llvm_map_components_to_libnames(llvm_libs core support)
|
||||
# Distributions often ship LLVM only as one shared library instead of the
|
||||
# per-component static libraries, so link that library when it is in use.
|
||||
if (LLVM_LINK_LLVM_DYLIB)
|
||||
set(llvm_libs LLVM)
|
||||
else ()
|
||||
llvm_map_components_to_libnames(llvm_libs core support)
|
||||
endif ()
|
||||
target_link_libraries(cuda-c-linking ${llvm_libs})
|
||||
|
||||
if (UNIX)
|
||||
|
||||
@@ -27,6 +27,21 @@ This sample is optionally built as part of the libnvvm samples from the CUDA
|
||||
samples tree. Please see the README file at the root of the libnvvm samples
|
||||
for build instructions.
|
||||
|
||||
It requires the LLVM development headers and libraries, version 7 or newer.
|
||||
LLVM 15 and newer emit opaque pointers, which libNVVM accepts only for
|
||||
Blackwell and later architectures, so such a build cannot run on an older GPU:
|
||||
|
||||
$ ./cuda-c-linking
|
||||
Using CUDA Device [0]: NVIDIA L4
|
||||
Device Compute Capability: 8.9
|
||||
This sample was built against LLVM 18, which emits opaque pointers, but
|
||||
libNVVM accepts only LLVM 7 IR for compute_89. Build against LLVM 14 or
|
||||
older to run on this device, or run on a Blackwell or later device.
|
||||
|
||||
The sample exits with code 2 in that case, reporting an unmet requirement
|
||||
rather than a failure. Building against LLVM 7 to 14 produces a binary that
|
||||
runs on any device this sample supports.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <cassert>
|
||||
#include <cuda.h>
|
||||
#include <llvm/ADT/StringExtras.h>
|
||||
#include <llvm/Config/llvm-config.h>
|
||||
#include <llvm/IR/IRBuilder.h>
|
||||
#include <llvm/IR/LLVMContext.h>
|
||||
#include <llvm/IR/Module.h>
|
||||
@@ -35,6 +36,9 @@
|
||||
#include <llvm/Support/Path.h>
|
||||
#include <llvm/Support/Program.h>
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
#if LLVM_VERSION_MAJOR >= 21
|
||||
#include <llvm/TargetParser/Triple.h>
|
||||
#endif
|
||||
#include <memory>
|
||||
#include <nvvm.h>
|
||||
#include <string>
|
||||
@@ -67,7 +71,9 @@ static void __checkCudaErrors(CUresult err, const char *filename, int line)
|
||||
((CUDA_SUCCESS == res) ? ename : "Unknown"),
|
||||
filename,
|
||||
line);
|
||||
exit(err);
|
||||
// Exit with EXIT_FAILURE rather than the error code, which 'main'
|
||||
// reserves to report an unmet requirement.
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,10 +82,14 @@ void checkNVVMCall(nvvmResult res)
|
||||
{
|
||||
if (res != NVVM_SUCCESS) {
|
||||
errs() << "libnvvm call failed\n";
|
||||
exit(res);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
// The libNVVM architecture string for a compute capability, e.g. 10.0 becomes
|
||||
// "compute_100".
|
||||
std::string computeArch(int devMajor, int devMinor) { return "compute_" + utostr(devMajor) + utostr(devMinor); }
|
||||
|
||||
/// generateModule - Generate and LLVM IR module that calls an
|
||||
/// externally-defined function
|
||||
std::unique_ptr<Module> generateModule(LLVMContext &context)
|
||||
@@ -89,13 +99,22 @@ std::unique_ptr<Module> generateModule(LLVMContext &context)
|
||||
mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-i128:128:128-"
|
||||
"f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:"
|
||||
"64");
|
||||
#if LLVM_VERSION_MAJOR >= 21
|
||||
// LLVM 21 dropped the overload that takes the triple as a string.
|
||||
mod->setTargetTriple(Triple("nvptx64-nvidia-cuda"));
|
||||
#else
|
||||
mod->setTargetTriple("nvptx64-nvidia-cuda");
|
||||
#endif
|
||||
|
||||
// Get pointers to some commonly-used types.
|
||||
Type *voidTy = Type::getVoidTy(context);
|
||||
Type *floatTy = Type::getFloatTy(context);
|
||||
Type *i32Ty = Type::getInt32Ty(context);
|
||||
Type *floatGenericPtrTy = PointerType::get(floatTy, /* address space */ 0);
|
||||
Type *voidTy = Type::getVoidTy(context);
|
||||
#if LLVM_VERSION_MAJOR >= 17
|
||||
// Pointers are opaque from LLVM 15 on, and LLVM 17 dropped the overload
|
||||
// that takes a pointee type. The resulting IR spells this type 'ptr'.
|
||||
Type *floatGenericPtrTy = PointerType::get(context, /* address space */ 0);
|
||||
#else
|
||||
Type *floatGenericPtrTy = PointerType::get(Type::getFloatTy(context), /* address space */ 0);
|
||||
#endif
|
||||
|
||||
// void @mandelbrot(float*)
|
||||
Type *mandelbrotParamTys[] = {floatGenericPtrTy};
|
||||
@@ -139,7 +158,7 @@ std::unique_ptr<Module> generateModule(LLVMContext &context)
|
||||
}
|
||||
|
||||
// Use libNVVM to compile an NVVM IR module to PTX.
|
||||
std::string generatePtx(const std::string &module, int devMajor, int devMinor, const char *moduleName)
|
||||
std::string generatePtx(const std::string &module, const std::string &arch, const char *moduleName)
|
||||
{
|
||||
assert(moduleName);
|
||||
|
||||
@@ -149,9 +168,7 @@ std::string generatePtx(const std::string &module, int devMajor, int devMinor, c
|
||||
|
||||
// Create a libNVVM compilation unit from the NVVM IR.
|
||||
checkNVVMCall(nvvmAddModuleToProgram(compileUnit, module.c_str(), module.size(), moduleName));
|
||||
std::string computeArg = "-arch=compute_";
|
||||
computeArg += utostr(devMajor);
|
||||
computeArg += utostr(devMinor);
|
||||
std::string computeArg = "-arch=" + arch;
|
||||
|
||||
// Compile the NVVM IR into PTX.
|
||||
const char *options[] = {computeArg.c_str()};
|
||||
@@ -216,9 +233,36 @@ int main(int argc, char **argv)
|
||||
checkCudaErrors(cuDeviceGetAttribute(&devMajor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, device));
|
||||
checkCudaErrors(cuDeviceGetAttribute(&devMinor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, device));
|
||||
outs() << "Device Compute Capability: " << devMajor << "." << devMinor << "\n";
|
||||
if (devMajor < 7 && devMinor < 5) {
|
||||
errs() << "ERROR: Device 0 is not sm_75 or later.\n";
|
||||
return 1;
|
||||
if (devMajor < 7 || (devMajor == 7 && devMinor < 5)) {
|
||||
outs() << "Device 0 is not sm_75 or later.\n";
|
||||
// 2 reports an unmet hardware/toolchain requirement rather than a failure.
|
||||
return 2;
|
||||
}
|
||||
|
||||
const std::string arch = computeArch(devMajor, devMinor);
|
||||
|
||||
// The LLVM IR that libNVVM accepts depends on the target architecture:
|
||||
// pre-Blackwell targets take LLVM 7 IR, which spells pointers with their
|
||||
// pointee type ('float*'), while Blackwell and later take a much newer IR
|
||||
// that also accepts the opaque pointers ('ptr') LLVM 15 and later emit.
|
||||
// Ask libNVVM which one applies to this device rather than assuming.
|
||||
int nvvmLLVMMajor = 0;
|
||||
const nvvmResult archSupported = nvvmLLVMVersion(arch.c_str(), &nvvmLLVMMajor);
|
||||
if (archSupported == NVVM_ERROR_INVALID_INPUT) {
|
||||
// The device is newer than the toolkit this sample builds against.
|
||||
outs() << "The libNVVM of this CUDA toolkit does not support " << arch
|
||||
<< ". Use a toolkit that supports this device.\n";
|
||||
// 2 reports an unmet hardware/toolchain requirement rather than a failure.
|
||||
return 2;
|
||||
}
|
||||
checkNVVMCall(archSupported);
|
||||
if (LLVM_VERSION_MAJOR >= 15 && nvvmLLVMMajor < 15) {
|
||||
outs() << "This sample was built against LLVM " << LLVM_VERSION_MAJOR
|
||||
<< ", which emits opaque pointers, but libNVVM accepts only LLVM " << nvvmLLVMMajor << " IR for " << arch
|
||||
<< ". Build against LLVM 14 or older to run on this device, or run on a "
|
||||
"Blackwell or later device.\n";
|
||||
// 2 reports an unmet hardware/toolchain requirement rather than a failure.
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Generate the IR module
|
||||
@@ -239,7 +283,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
// Generate PTX.
|
||||
std::string ptx = generatePtx(moduleStr, devMajor, devMinor, module->getModuleIdentifier().c_str());
|
||||
std::string ptx = generatePtx(moduleStr, arch, module->getModuleIdentifier().c_str());
|
||||
if (SavePTX) {
|
||||
std::error_code err;
|
||||
raw_fd_ostream out("cuda-c-linking.kernel.ptx", err);
|
||||
|
||||
@@ -10,8 +10,8 @@ This document assumes the CUDA runtime is used. The method for device-side
|
||||
launch using the OpenCL runtime is similar but different.
|
||||
|
||||
This document is written after the "Device-Side Launch from PTX"
|
||||
section from CUDA C Programming Guide
|
||||
(http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#device-side-launch-from-ptx).
|
||||
section from CUDA Programming Guide
|
||||
(https://docs.nvidia.com/cuda/cuda-programming-guide/04-special-topics/dynamic-parallelism.html#device-side-launch-from-ptx).
|
||||
|
||||
Kernel Launch APIs
|
||||
------------------
|
||||
|
||||
Reference in New Issue
Block a user