Proteus
Programmable JIT compilation and optimization for C/C++ using LLVM
Loading...
Searching...
No Matches
CoreDeviceCUDA.h
Go to the documentation of this file.
1#ifndef PROTEUS_CORE_CUDA_H
2#define PROTEUS_CORE_CUDA_H
3
4#include "proteus/Error.h"
7
8#include <llvm/ADT/StringRef.h>
9#include <llvm/ADT/Twine.h>
10
11#include <cstdint>
12#include <string>
13#include <unordered_map>
14
15namespace proteus {
16
17extern "C" {
18// Definitions for function pointers to CUDA APIs that we will resolve at
19// runtime using builtins.
20// NOLINTBEGIN(readability-identifier-naming)
22 void **, const void *) = nullptr;
23inline cudaError_t (*__proteus_cudaLaunchKernel_ptr)(const void *, dim3, dim3,
24 void **, size_t,
25 cudaStream_t) = nullptr;
26}
27// NOLINTEND(readability-identifier-naming)
28
29inline void *resolveDeviceGlobalAddr(const void *Addr) {
30 void *DevPtr = nullptr;
33 assert(DevPtr && "Expected non-null device pointer for global");
34 return DevPtr;
35 }
36
37 reportFatalError("__proteus_cudaGetSymbolAddress_ptr is not initialized. "
38 "Ensure the CUDA runtime is properly linked.");
39}
40
41inline cudaError_t launchKernelDirect(void *KernelFunc, dim3 GridDim,
42 dim3 BlockDim, void **KernelArgs,
43 uint64_t ShmemSize, CUstream Stream) {
45 return __proteus_cudaLaunchKernel_ptr(KernelFunc, GridDim, BlockDim,
46 KernelArgs, ShmemSize, Stream);
47 }
48
49 reportFatalError("__proteus_cudaLaunchKernel_ptr is not initialized. Ensure "
50 "the CUDA runtime is properly linked.");
51}
52
54 StringRef KernelName, const void *Image, bool RelinkGlobalsByCopy,
55 const std::unordered_map<std::string, GlobalVarInfo> &VarNameToGlobalInfo) {
56 CUfunction KernelFunc;
57 CUmodule Mod;
58
60 if (RelinkGlobalsByCopy) {
61 for (auto &[GlobalName, GVI] : VarNameToGlobalInfo) {
62 if (!GVI.DevAddr)
63 reportFatalError("Cannot copy to Global Var " + GlobalName +
64 " without a concrete device address");
65
66 CUdeviceptr Dptr;
67 size_t Bytes;
69 cuModuleGetGlobal(&Dptr, &Bytes, Mod, (GlobalName + "$ptr").c_str()));
70
71 uint64_t PtrVal = (uint64_t)GVI.DevAddr;
72 proteusCuErrCheck(cuMemcpyHtoD(Dptr, &PtrVal, Bytes));
73 }
74 }
76 cuModuleGetFunction(&KernelFunc, Mod, KernelName.str().c_str()));
77
78 return KernelFunc;
79}
80
81inline cudaError_t launchKernelFunction(CUfunction KernelFunc, dim3 GridDim,
82 dim3 BlockDim, void **KernelArgs,
83 uint64_t ShmemSize, CUstream Stream) {
84 // Convert CUresult to cudaError_t for the caller, where we replace a
85 // cudaLaunchKernel call with cuLaunchKernel for the JIT module.
86 auto CUresultToCudaError = [](CUresult Res) -> cudaError_t {
87 switch (Res) {
88 case CUDA_SUCCESS:
89 return cudaSuccess;
90 case CUDA_ERROR_INVALID_VALUE:
91 return cudaErrorInvalidValue;
92 case CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES:
93 return cudaErrorLaunchOutOfResources;
94 case CUDA_ERROR_LAUNCH_TIMEOUT:
95 return cudaErrorLaunchTimeout;
96 case CUDA_ERROR_LAUNCH_FAILED:
97 return cudaErrorLaunchFailure;
98 case CUDA_ERROR_SHARED_OBJECT_INIT_FAILED:
99 return cudaErrorSharedObjectInitFailed;
100 case CUDA_ERROR_INVALID_HANDLE:
101 return cudaErrorInvalidResourceHandle;
102 case CUDA_ERROR_NOT_READY:
103 return cudaErrorNotReady;
104 case CUDA_ERROR_ILLEGAL_ADDRESS:
105 return cudaErrorIllegalAddress;
106 default:
107 return cudaErrorUnknown;
108 }
109 };
110 // Opt in to more dynamic shared memory only when the request exceeds the
111 // function's current limit.
112 int MaxDynamicShmem = 0;
114 &MaxDynamicShmem, CU_FUNC_ATTRIBUTE_MAX_DYNAMIC_SHARED_SIZE_BYTES,
115 KernelFunc));
116
117 if (ShmemSize > static_cast<uint64_t>(MaxDynamicShmem)) {
118 // The device opt-in limit covers static plus dynamic shared memory.
119 int StaticShmem = 0;
121 &StaticShmem, CU_FUNC_ATTRIBUTE_SHARED_SIZE_BYTES, KernelFunc));
122
123 CUdevice Device;
125
126 int OptinMaxShmem = 0;
128 &OptinMaxShmem, CU_DEVICE_ATTRIBUTE_MAX_SHARED_MEMORY_PER_BLOCK_OPTIN,
129 Device));
130
131 if (ShmemSize + static_cast<uint64_t>(StaticShmem) >
132 static_cast<uint64_t>(OptinMaxShmem))
133 reportFatalError("Shared memory request exceeds device limit: dynamic " +
134 Twine(ShmemSize) + " + static " + Twine(StaticShmem) +
135 " > " + Twine(OptinMaxShmem) + " bytes");
136
138 KernelFunc, CU_FUNC_ATTRIBUTE_MAX_DYNAMIC_SHARED_SIZE_BYTES,
139 static_cast<int>(ShmemSize)));
140 }
141
142 CUresult Res = cuLaunchKernel(KernelFunc, GridDim.x, GridDim.y, GridDim.z,
143 BlockDim.x, BlockDim.y, BlockDim.z, ShmemSize,
144 Stream, KernelArgs, nullptr);
145 return static_cast<cudaError_t>(CUresultToCudaError(Res));
146}
147
148} // namespace proteus
149
150#endif
CUresult CUDAAPI cuModuleGetFunction(CUfunction *Hfunc, CUmodule Hmod, const char *Name)
Definition CUDADriverAPI.cpp:120
CUresult CUDAAPI cuModuleLoadData(CUmodule *Module, const void *Image)
Definition CUDADriverAPI.cpp:106
CUresult CUDAAPI cuMemcpyHtoD(CUdeviceptr DstDevice, const void *SrcHost, size_t ByteCount)
Definition CUDADriverAPI.cpp:136
CUresult CUDAAPI cuModuleGetGlobal(CUdeviceptr *Dptr, size_t *Bytes, CUmodule Hmod, const char *Name)
Definition CUDADriverAPI.cpp:128
CUresult CUDAAPI cuDeviceGetAttribute(int *Pi, CUdevice_attribute Attrib, CUdevice Dev)
Definition CUDADriverAPI.cpp:98
CUresult CUDAAPI cuCtxGetDevice(CUdevice *Device)
Definition CUDADriverAPI.cpp:77
CUresult CUDAAPI cuFuncSetAttribute(CUfunction Hfunc, CUfunction_attribute Attrib, int Value)
Definition CUDADriverAPI.cpp:160
CUresult CUDAAPI cuFuncGetAttribute(int *Pi, CUfunction_attribute Attrib, CUfunction Hfunc)
Definition CUDADriverAPI.cpp:152
CUresult CUDAAPI cuLaunchKernel(CUfunction F, unsigned int GridDimX, unsigned int GridDimY, unsigned int GridDimZ, unsigned int BlockDimX, unsigned int BlockDimY, unsigned int BlockDimZ, unsigned int SharedMemBytes, CUstream HStream, void **KernelParams, void **Extra)
Definition CUDADriverAPI.cpp:168
#define proteusCuErrCheck(CALL)
Definition UtilsCUDA.h:28
Definition KernelName.h:18
Definition MemoryCache.h:27
cudaError_t(* __proteus_cudaGetSymbolAddress_ptr)(void **, const void *)
Definition CoreDeviceCUDA.h:21
void reportFatalError(const llvm::Twine &Reason, const char *FILE, unsigned Line)
Definition Error.cpp:14
cudaError_t launchKernelDirect(void *KernelFunc, dim3 GridDim, dim3 BlockDim, void **KernelArgs, uint64_t ShmemSize, CUstream Stream)
Definition CoreDeviceCUDA.h:41
cudaError_t launchKernelFunction(CUfunction KernelFunc, dim3 GridDim, dim3 BlockDim, void **KernelArgs, uint64_t ShmemSize, CUstream Stream)
Definition CoreDeviceCUDA.h:81
void * resolveDeviceGlobalAddr(const void *Addr)
Definition CoreDeviceCUDA.h:29
cudaError_t(* __proteus_cudaLaunchKernel_ptr)(const void *, dim3, dim3, void **, size_t, cudaStream_t)
Definition CoreDeviceCUDA.h:23
CUfunction getKernelFunctionFromImage(StringRef KernelName, const void *Image, bool RelinkGlobalsByCopy, const std::unordered_map< std::string, GlobalVarInfo > &VarNameToGlobalInfo)
Definition CoreDeviceCUDA.h:53