CUDA 13.2 samples update (#432)

- Added Python samples for CUDA Python 1.0 release
- Renamed top-level `Samples` directory to `cpp` to accommodate Python samples.
This commit is contained in:
Dheemanth
2026-05-13 15:13:18 -07:00
committed by GitHub
parent a4526d5229
commit aeab82ff30
2072 changed files with 15077 additions and 1970 deletions

View File

@@ -0,0 +1,69 @@
# Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of NVIDIA CORPORATION nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
set(CMAKE_INSTALL_RPATH ${LIBNVVM_HOME})
set(CMAKE_INCLUDE_CURRENT_DIR YES)
set_property(SOURCE dsl.c
PROPERTY COMPILE_DEFINITIONS LIBCUDADEVRT="${CUDADEVRT_LIB}")
add_executable(dsl dsl.c)
add_test(NAME device-side-launch COMMAND dsl
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
target_link_libraries(dsl ${NVVM_LIB} ${CUDA_LIB})
if (WIN32)
set_target_properties(dsl PROPERTIES COMPILE_FLAGS "/wd4996")
else (WIN32)
set_target_properties(dsl PROPERTIES LINK_FLAGS "-Wl,-rpath,${LIBNVVM_RPATH}")
endif (WIN32)
# Install to CUDA_SAMPLES_INSTALL_DIR if defined (for unified installation),
# otherwise install to bin (for standalone libNVVM build)
if(DEFINED CUDA_SAMPLES_INSTALL_DIR)
install(TARGETS dsl DESTINATION ${CUDA_SAMPLES_INSTALL_DIR})
install(FILES dsl-gpu64.ll DESTINATION ${CUDA_SAMPLES_INSTALL_DIR})
else()
install(TARGETS dsl DESTINATION bin)
install(FILES dsl-gpu64.ll DESTINATION bin)
endif()
# 'dsl' will load dsl-gpu64.ll from the current working directory. That
# .ll file should be present where tests are executed (the build directory).
add_custom_command(
TARGET dsl
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/dsl-gpu64.ll" "$<TARGET_FILE_DIR:dsl>"
)
if (WIN32)
add_custom_command(
TARGET dsl
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_BINARY_DIR}/nvvm64_40_0.dll" "$<TARGET_FILE_DIR:dsl>"
)
endif ()

View File

@@ -0,0 +1,80 @@
Device-Side Launch From NVVM IR
===============================
This document is for the programming language and compiler implementers who
target NVVM IR and plan to support Dynamic Parallelism in their langauge.
It provides the low-level details related to supporting kernel launches at
the NVVM IR level.
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).
Kernel Launch APIs
------------------
Device-side kernel launches can be implemented using the following two APIs
in an NVVM IR program: cudaLaunchDevice() and cudaGetParameterBuffer().
cudaLaunchDevice() launches the specified kernel with the parameter buffer
that is obtained by calling cudaGetParameterBuffer() and filled with the
parameters to the launched kernel. The parameter buffer can be NULL, i.e.,
no need to invoke cudaGetParameterBuffer(), if the launched kernel does not
take any parameters.
cudaLaunchDevice
----------------
At the NVVM IR level, cudaLaunchDeviceV2() needs to be declared in the
form shown below before it is used.
; NVVM IR level declaration of cudaLaunchDeviceV2
declare i32 @cudaLaunchDeviceV2(i8*, %struct.CUstream_st*)
The CUDA-level declaration below is mapped to one of the aftorementioned NVVM
IR level declarations and is found in the system header file
cuda_device_runtime_api.h. The function is defined in the cudadevrt system
library, which must be linked with a program in order to use device-side
kernel launch functionality.
extern __device__ __cudart_builtin__ cudaError_t CUDARTAPI
cudaLaunchDeviceV2(void *parameterBuffer, cudaStream_t stream);
The first parameter is a pointer to the parameter buffer, and the
second parameter is the stream associated with the launch. The layout
of the parameter buffer is explained in "Parameter Buffer Layout"
below.
cudaGetParameterBuffer
----------------------
cudaGetParameterBufferV2() needs to be declared at the NVVM IR level
before it's used. The NVVM IR level declaration must be in the form
given below:
; NVVM IR level declaration of cudaGetParameterBufferV2
declare i8* @cudaGetParameterBufferV2(i8*, %struct.dim3, %struct.dim3, i32)
The following CUDA-level declaration of cudaGetParameterBufferV2() is
mapped to the aforementioned NVVM IR level declaration:
extern __device__ __cudart_builtin__ void * CUDARTAPI
cudaGetParameterBufferV2(void *func, dim3 gridDimension,
dim3 blockDimension,
unsigned int sharedMemSize);
The first parameter is a pointer to the kernel to be launched, and the
other parameters specify the launch configuration, i.e., as grid
dimension, block dimension, and shared memory size.
Parameter Buffer Layout
-----------------------
Parameter reordering in the parameter buffer is prohibited, and each individual
parameter placed in the parameter buffer is required to be aligned. That is,
each parameter must be placed at the n-th byte in the parameter buffer, where n
is the smallest multiple of the parameter size that is greater than the offset
of the last byte taken by the preceding parameter. The maximum size of the
parameter buffer is 4KB.

View File

@@ -0,0 +1,103 @@
; Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions
; are met:
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; * Neither the name of NVIDIA CORPORATION nor the names of its
; contributors may be used to endorse or promote products derived
; from this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
; OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
; This NVVM IR program shows how to call cudaGetParameterBuffer and cudaLaunchDevice functions.
; What it does is similar to the following CUDA C code.
;
; __global__ void kernel(int depth)
; {
; if (threadIdx.x == 0) {
; printf("kernel launched, depth = %d\n", depth);
; }
;
; __syncthreads();
;
; if (++depth > 3)
; return;
;
; kernel<<<1,1>>>(depth);
;
; }
target datalayout = "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"
target triple = "nvptx64-nvidia-cuda"
%struct.dim3 = type { i32, i32, i32 }
%struct.CUstream_st = type opaque
@"$str" = private addrspace(1) constant [29 x i8] c"kernel launched, depth = %d\0A\00"
define void @kernel(i32 %depth) {
entry:
%tmp31 = alloca i32, align 8
%gen2local = addrspacecast i32* %tmp31 to i32 addrspace(5)*
%tmp31.sub = bitcast i32* %tmp31 to i8*
%0 = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
%cmp = icmp eq i32 %0, 0
br i1 %cmp, label %if.then, label %if.end
if.then: ; preds = %entry
%1 = addrspacecast i8 addrspace(1)* getelementptr inbounds ([29 x i8], [29 x i8] addrspace(1)* @"$str", i64 0, i64 0) to i8 addrspace(0)*
store i32 %depth, i32 addrspace(5)* %gen2local, align 8
%call = call i32 @vprintf(i8* %1, i8* %tmp31.sub)
br label %if.end
if.end: ; preds = %if.then, %entry
call void @llvm.cuda.syncthreads()
%inc = add nsw i32 %depth, 1
%cmp5 = icmp sgt i32 %inc, 3
br i1 %cmp5, label %return, label %if.end7
if.end7: ; preds = %if.end
%call15 = call i8* @cudaGetParameterBufferV2(i8* bitcast (void (i32)* @kernel to i8*), %struct.dim3 { i32 1, i32 1, i32 1 }, %struct.dim3 { i32 1, i32 1, i32 1 }, i32 0)
%tobool = icmp eq i8* %call15, null
br i1 %tobool, label %return, label %cond.true
cond.true: ; preds = %if.end7
%conv = bitcast i8* %call15 to i32*
store i32 %inc, i32* %conv, align 4
%call20 = call i32 @cudaLaunchDeviceV2(i8* %call15, %struct.CUstream_st* null)
br label %return
return: ; preds = %cond.true, %if.end7, %if.end
ret void
}
declare i32 @llvm.nvvm.read.ptx.sreg.tid.x() nounwind readnone
declare i32 @vprintf(i8* nocapture, i8*) nounwind
declare void @llvm.cuda.syncthreads() nounwind
declare i8* @cudaGetParameterBufferV2(i8*, %struct.dim3, %struct.dim3, i32)
declare i32 @cudaLaunchDeviceV2(i8*, %struct.CUstream_st*)
!nvvm.annotations = !{!0}
!0 = !{void (i32)* @kernel, !"kernel", i32 1}
!nvvmir.version = !{!1}
!1 = !{i32 2, i32 0}

View File

@@ -0,0 +1,260 @@
// Copyright (c) 2014-2025, NVIDIA CORPORATION. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assert.h>
#include <builtin_types.h>
#include <cuda.h>
#include <math.h>
#include <nvvm.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
// The full path to the libcudadevrt.a is determined by the build environment.
const char *_libCudaDevRt = LIBCUDADEVRT;
static const char *getLibCudaDevRtName(void)
{
// Check that the library exists.
FILE *fh = fopen(_libCudaDevRt, "rb");
if (fh == NULL) {
fprintf(stderr, "Error locating the libcudadevrt runtime: %s\n", _libCudaDevRt);
exit(EXIT_FAILURE);
}
fclose(fh);
return _libCudaDevRt;
}
// If 'err' is non-zero, emit an error message and exit.
#define checkCudaErrors(err) __checkCudaErrors(err, __FILE__, __LINE__)
static void __checkCudaErrors(CUresult err, const char *filename, int line)
{
assert(filename);
if (CUDA_SUCCESS != err) {
const char *ename = NULL;
const CUresult res = cuGetErrorName(err, &ename);
fprintf(stderr,
"CUDA API Error %04d: \"%s\" from file <%s>, "
"line %i.\n",
err,
((CUDA_SUCCESS == res) ? ename : "Unknown"),
filename,
line);
exit(err);
}
}
static char *loadProgramSource(const char *filename, size_t *size)
{
assert(filename && size);
char *source = NULL;
*size = 0;
FILE *fh = fopen(filename, "rb");
if (fh) {
struct stat statbuf;
stat(filename, &statbuf);
source = (char *)malloc(statbuf.st_size + 1);
if (source) {
fread(source, statbuf.st_size, 1, fh);
source[statbuf.st_size] = 0;
*size = statbuf.st_size + 1;
}
}
else {
fprintf(stderr, "Error reading file %s\n", filename);
exit(EXIT_FAILURE);
}
return source;
}
// Compile the NVVM IR into PTX.
static char *generatePTX(const char *ll, size_t size, const char *filename, int devMajor, int devMinor)
{
assert(ll && filename);
// Create a program instance for libNVVM.
nvvmProgram program;
nvvmResult result = nvvmCreateProgram(&program);
if (result != NVVM_SUCCESS) {
fprintf(stderr, "nvvmCreateProgram: Failed\n");
exit(EXIT_FAILURE);
}
// Add the NVVM IR as a module to our libNVVM program.
result = nvvmAddModuleToProgram(program, ll, size, filename);
if (result != NVVM_SUCCESS) {
fprintf(stderr, "nvvmAddModuleToProgram: Failed\n");
exit(EXIT_FAILURE);
}
// Dynamically construct the compute capability.
char arch[32] = {0};
snprintf(arch, sizeof(arch) - 1, "-arch=compute_%d%d", devMajor, devMinor);
// Compile the IR into PTX.
const char *options[] = {arch};
result = nvvmCompileProgram(program, 1, options);
if (result != NVVM_SUCCESS) {
char *Msg = NULL;
size_t LogSize;
fprintf(stderr, "nvvmCompileProgram: Failed\n");
nvvmGetProgramLogSize(program, &LogSize);
Msg = (char *)malloc(LogSize);
nvvmGetProgramLog(program, Msg);
fprintf(stderr, "%s\n", Msg);
free(Msg);
exit(EXIT_FAILURE);
}
size_t ptxSize = 0;
result = nvvmGetCompiledResultSize(program, &ptxSize);
if (result != NVVM_SUCCESS) {
fprintf(stderr, "nvvmGetCompiledResultSize: Failed\n");
exit(EXIT_FAILURE);
}
char *ptx = malloc(ptxSize);
assert(ptx);
result = nvvmGetCompiledResult(program, ptx);
if (result != NVVM_SUCCESS) {
fprintf(stderr, "nvvmGetCompiledResult: Failed\n");
free(ptx);
exit(EXIT_FAILURE);
}
result = nvvmDestroyProgram(&program);
if (result != NVVM_SUCCESS) {
fprintf(stderr, "nvvmDestroyProgram: Failed\n");
free(ptx);
exit(EXIT_FAILURE);
}
return ptx;
}
// Return the device compute capability in major and minor.
static CUdevice cudaDeviceInit(int *major, int *minor)
{
assert(major && minor);
// Count the number of CUDA compute capable devices..
CUresult err = cuInit(0);
int deviceCount = 0;
if (CUDA_SUCCESS == err)
checkCudaErrors(cuDeviceGetCount(&deviceCount));
if (deviceCount == 0) {
fprintf(stderr, "cudaDeviceInit error: no devices supporting CUDA\n");
exit(EXIT_FAILURE);
}
// Get the first device discovered (device 0) and print its name.
CUdevice cuDevice = 0;
checkCudaErrors(cuDeviceGet(&cuDevice, 0));
char name[128] = {0};
checkCudaErrors(cuDeviceGetName(name, sizeof(name), cuDevice));
printf("Using CUDA Device [0]: %s\n", name);
// Get and test the compute capability.
checkCudaErrors(cuDeviceGetAttribute(major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, cuDevice));
checkCudaErrors(cuDeviceGetAttribute(minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, cuDevice));
printf("compute capability = %d.%d\n", *major, *minor);
if (*major < 7 && *minor < 5) {
fprintf(stderr, "Device 0 is not sm_75 or later\n");
exit(EXIT_FAILURE);
}
return cuDevice;
}
static CUresult buildKernel(CUcontext *phContext, CUdevice *phDevice, CUmodule *phModule, CUfunction *phKernel)
{
assert(phContext && phDevice && phModule && phKernel);
// Initialize CUDA and obtain the device's compute capability.
int major = 0, minor = 0;
*phDevice = cudaDeviceInit(&major, &minor);
checkCudaErrors(cuCtxCreate(phContext, NULL, 0, *phDevice));
// Get the NVVM IR from file.
size_t size = 0;
const char *filename = "dsl-gpu64.ll";
char *ll = loadProgramSource(filename, &size);
fprintf(stdout, "NVVM IR ll file loaded\n");
// Use libNVVM to generate PTX.
char *ptx = generatePTX(ll, size, filename, major, minor);
fprintf(stdout, "PTX generated:\n");
fprintf(stdout, "%s\n", ptx);
// Create a context and link the PTX and device library.
const char *libCudaDevRtName = getLibCudaDevRtName();
void *cubin = NULL;
size_t cubinSize = 0;
CUlinkState linkState;
checkCudaErrors(cuLinkCreate(0, NULL, NULL, &linkState));
checkCudaErrors(cuLinkAddData(linkState, CU_JIT_INPUT_PTX, (void *)ptx, strlen(ptx) + 1, 0, 0, 0, 0));
checkCudaErrors(cuLinkAddFile(linkState, CU_JIT_INPUT_LIBRARY, libCudaDevRtName, 0, NULL, NULL));
checkCudaErrors(cuLinkComplete(linkState, &cubin, &cubinSize));
// Load the linked binary.
checkCudaErrors(cuModuleLoadData(phModule, cubin));
// Locate the kernel entry point.
checkCudaErrors(cuModuleGetFunction(phKernel, *phModule, "kernel"));
checkCudaErrors(cuLinkDestroy(linkState));
free(ll);
free(ptx);
return CUDA_SUCCESS;
}
int main(int argc, char **argv)
{
const unsigned int nThreads = 1;
const unsigned int nBlocks = 1;
// Initialize the device and get a handle to the kernel.
CUcontext hContext = 0;
CUdevice hDevice = 0;
CUmodule hModule = 0;
CUfunction hKernel = 0;
checkCudaErrors(buildKernel(&hContext, &hDevice, &hModule, &hKernel));
// Launch the kernel.
int depth = 0;
void *params[] = {&depth};
checkCudaErrors(cuLaunchKernel(hKernel, nBlocks, 1, 1, nThreads, 1, 1, 0, NULL, params, NULL));
if (hModule) {
checkCudaErrors(cuModuleUnload(hModule));
hModule = 0;
}
if (hContext) {
checkCudaErrors(cuCtxDestroy(hContext));
hContext = 0;
}
return 0;
}