Apply consistent code formatting across the repo. Add clang-format and pre-commit hooks.

This commit is contained in:
Rob Armstrong
2025-03-27 10:30:07 -07:00
parent 2cd58fbc9a
commit ceab6e8bcc
782 changed files with 107230 additions and 106548 deletions

View File

@@ -16,7 +16,7 @@ section from CUDA C Programming Guide
Kernel Launch APIs
------------------
Device-side kernel launches can be implemented using the following two 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
@@ -34,8 +34,8 @@ form shown below before it is used.
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
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.
@@ -60,21 +60,21 @@ given below:
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,
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.
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,
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
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

@@ -37,221 +37,224 @@
// 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;
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 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;
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;
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);
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);
}
// 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);
}
// 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);
// 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);
}
// 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);
}
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);
}
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);
}
result = nvvmDestroyProgram(&program);
if (result != NVVM_SUCCESS) {
fprintf(stderr, "nvvmDestroyProgram: Failed\n");
free(ptx);
exit(EXIT_FAILURE);
}
return ptx;
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);
}
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 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 < 5) {
fprintf(stderr, "Device 0 is not sm_50 or later\n");
exit(EXIT_FAILURE);
}
return cuDevice;
// 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 < 5) {
fprintf(stderr, "Device 0 is not sm_50 or later\n");
exit(EXIT_FAILURE);
}
return cuDevice;
}
static CUresult buildKernel(CUcontext *phContext, CUdevice *phDevice,
CUmodule *phModule, CUfunction *phKernel) {
assert(phContext && phDevice && phModule && phKernel);
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, 0, *phDevice));
// Initialize CUDA and obtain the device's compute capability.
int major = 0, minor = 0;
*phDevice = cudaDeviceInit(&major, &minor);
checkCudaErrors(cuCtxCreate(phContext, 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");
// 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);
// 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));
// 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));
// Load the linked binary.
checkCudaErrors(cuModuleLoadData(phModule, cubin));
// Locate the kernel entry point.
checkCudaErrors(cuModuleGetFunction(phKernel, *phModule, "kernel"));
// Locate the kernel entry point.
checkCudaErrors(cuModuleGetFunction(phKernel, *phModule, "kernel"));
checkCudaErrors(cuLinkDestroy(linkState));
free(ll);
free(ptx);
return CUDA_SUCCESS;
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;
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));
// 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));
// 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;
}
if (hModule) {
checkCudaErrors(cuModuleUnload(hModule));
hModule = 0;
}
if (hContext) {
checkCudaErrors(cuCtxDestroy(hContext));
hContext = 0;
}
return 0;
return 0;
}