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,68 @@
# Copyright (c) 1993-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)
add_executable(simple simple.c)
add_test(NAME simple COMMAND simple WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
target_link_libraries(simple ${NVVM_LIB} ${CUDA_LIB})
if (WIN32)
set_target_properties(simple PROPERTIES COMPILE_FLAGS "/wd4996")
else (WIN32)
set_target_properties(simple 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 simple DESTINATION ${CUDA_SAMPLES_INSTALL_DIR})
install(FILES simple-gpu64.ll DESTINATION ${CUDA_SAMPLES_INSTALL_DIR})
else()
install(TARGETS simple DESTINATION bin)
install(FILES simple-gpu64.ll DESTINATION bin)
endif()
# 'simple' will load simple-gpu64.ll from the current working directory. That
# .ll file should be present where tests are executed (the build directory).
add_custom_command(
TARGET simple
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/simple-gpu64.ll" "$<TARGET_FILE_DIR:simple>"
)
if (WIN32)
add_custom_command(
TARGET simple
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_BINARY_DIR}/nvvm64_40_0.dll" "$<TARGET_FILE_DIR:simple>"
)
endif ()

View File

@@ -0,0 +1,6 @@
Introduction
============
simple is a C program that illustrates the use of libNVVM.
simple converts the simple-gpu64.ll NVVM-IR file into PTX via the libNVVM API
and forwards that PTX to the CUDA driver for GPU execution.

View File

@@ -0,0 +1,61 @@
; Copyright (c) 1993-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.
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"
define i32 @ave(i32 %a, i32 %b) {
entry:
%add = add nsw i32 %a, %b
%div = sdiv i32 %add, 2
ret i32 %div
}
define void @simple(i32* %data) {
entry:
%0 = call i32 @llvm.nvvm.read.ptx.sreg.ctaid.x()
%1 = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
%mul = mul i32 %0, %1
%2 = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
%add = add i32 %mul, %2
%call = call i32 @ave(i32 %add, i32 %add)
%idxprom = sext i32 %add to i64
%arrayidx = getelementptr inbounds i32, i32* %data, i64 %idxprom
store i32 %call, i32* %arrayidx, align 4
ret void
}
declare i32 @llvm.nvvm.read.ptx.sreg.ctaid.x() nounwind readnone
declare i32 @llvm.nvvm.read.ptx.sreg.ntid.x() nounwind readnone
declare i32 @llvm.nvvm.read.ptx.sreg.tid.x() nounwind readnone
!nvvm.annotations = !{!1}
!1 = !{void (i32*)* @simple, !"kernel", i32 1}
!nvvmir.version = !{!2}
!2 = !{i32 2, i32 0, i32 3, i32 1}

View File

@@ -0,0 +1,251 @@
// Copyright (c) 1993-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 <sys/stat.h>
// 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);
}
}
// Return a CUDA capable device or exit if one cannot be found.
static CUdevice cudaDeviceInit(int *devMajor, int *devMinor)
{
assert(devMajor && devMinor);
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);
}
// Locate a CUDA supporting device and its name.
CUdevice cuDevice = 0;
checkCudaErrors(cuDeviceGet(&cuDevice, 0));
char name[128];
cuDeviceGetName(name, sizeof(name), cuDevice);
printf("Using CUDA Device [0]: %s\n", name);
// Obtain the device's compute capability.
checkCudaErrors(cuDeviceGetAttribute(devMajor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, cuDevice));
checkCudaErrors(cuDeviceGetAttribute(devMinor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, cuDevice));
if (*devMajor < 7 && *devMinor < 5) {
fprintf(stderr, "Device 0 is not sm_75 or later\n");
exit(EXIT_FAILURE);
}
return cuDevice;
}
static CUresult
initCUDA(CUcontext *phContext, CUdevice *phDevice, CUmodule *phModule, CUfunction *phKernel, const char *ptx)
{
assert(phContext && phDevice && phModule && phKernel && ptx);
// Create a CUDA context on the device.
checkCudaErrors(cuCtxCreate(phContext, NULL, 0, *phDevice));
// Load the PTX.
checkCudaErrors(cuModuleLoadDataEx(phModule, ptx, 0, 0, 0));
// Locate the kernel entry point.
checkCudaErrors(cuModuleGetFunction(phKernel, *phModule, "simple"));
return CUDA_SUCCESS;
}
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 = malloc(statbuf.st_size + 1);
assert(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;
}
static char *generatePTX(const char *ir, size_t size, const char *filename, int devMajor, int devMinor)
{
assert(ir && filename);
// Create a program instance for use with libNVVM.
nvvmProgram program;
nvvmResult result = nvvmCreateProgram(&program);
if (result != NVVM_SUCCESS) {
fprintf(stderr, "nvvmCreateProgram: Failed\n");
exit(EXIT_FAILURE);
}
// Add the NVVM IR to the program instance.
result = nvvmAddModuleToProgram(program, ir, 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) {
fprintf(stderr, "nvvmCompileProgram: Failed\n");
size_t logSize;
nvvmGetProgramLogSize(program, &logSize);
char *msg = malloc(logSize);
assert(msg);
nvvmGetProgramLog(program, msg);
fprintf(stderr, "%s\n", msg);
free(msg);
exit(EXIT_FAILURE);
}
// Obrain the resulting PTX.
size_t ptxSize;
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);
}
// Cleanup the libNVVM program instance.
result = nvvmDestroyProgram(&program);
if (result != NVVM_SUCCESS) {
fprintf(stderr, "nvvmDestroyProgram: Failed\n");
free(ptx);
exit(EXIT_FAILURE);
}
return ptx;
}
int main(int argc, char **argv)
{
const unsigned int nThreads = 32;
const unsigned int nBlocks = 1;
const size_t memSize = nThreads * nBlocks * sizeof(int);
const char *filename = "simple-gpu64.ll";
// Retrieve the NVVM IR from filename and create the kernel parameters.
size_t size = 0;
char *ir = loadProgramSource(filename, &size);
fprintf(stdout, "NVVM IR (.ll) file loaded\n");
// Initialize the device and obtain the compute capability.
int devMajor = 0, devMinor = 0;
CUdevice hDevice = cudaDeviceInit(&devMajor, &devMinor);
// Use libNVVM to generate PTX from the NVVM IR.
char *ptx = generatePTX(ir, size, filename, devMajor, devMinor);
fprintf(stdout, "PTX generated:\n");
fprintf(stdout, "%s\n", ptx);
// Initialize the device and get a handle to the kernel.
CUcontext hContext = 0;
CUmodule hModule = 0;
CUfunction hKernel = 0;
checkCudaErrors(initCUDA(&hContext, &hDevice, &hModule, &hKernel, ptx));
// Allocate memory on the host and device.
int *hData = malloc(memSize);
if (!hData) {
fprintf(stderr, "Could not allocate host memory\n");
exit(EXIT_FAILURE);
}
CUdeviceptr dData = 0;
checkCudaErrors(cuMemAlloc(&dData, memSize));
// Launch the kernel.
void *params[] = {&dData};
checkCudaErrors(cuLaunchKernel(hKernel, nBlocks, 1, 1, nThreads, 1, 1, 0, NULL, params, NULL));
fprintf(stdout, "CUDA kernel launched\n");
// Copy the result back to the host.
checkCudaErrors(cuMemcpyDtoH(hData, dData, memSize));
// Print the result.
for (unsigned i = 0; i < nBlocks * nThreads; i++)
fprintf(stdout, "%d ", hData[i]);
fprintf(stdout, "\n");
// Cleanup.
if (dData)
checkCudaErrors(cuMemFree(dData));
if (hModule)
checkCudaErrors(cuModuleUnload(hModule));
if (hContext)
checkCudaErrors(cuCtxDestroy(hContext));
free(hData);
free(ir);
free(ptx);
return 0;
}