mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2026-10-13 00:08:26 +08:00
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:
69
cpp/7_libNVVM/device-side-launch/CMakeLists.txt
Normal file
69
cpp/7_libNVVM/device-side-launch/CMakeLists.txt
Normal 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 ()
|
||||
80
cpp/7_libNVVM/device-side-launch/README.md
Normal file
80
cpp/7_libNVVM/device-side-launch/README.md
Normal 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.
|
||||
103
cpp/7_libNVVM/device-side-launch/dsl-gpu64.ll
Normal file
103
cpp/7_libNVVM/device-side-launch/dsl-gpu64.ll
Normal 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}
|
||||
260
cpp/7_libNVVM/device-side-launch/dsl.c
Normal file
260
cpp/7_libNVVM/device-side-launch/dsl.c
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user