如何将 cuda 驱动程序 api 与 cuda 运行时 api 混合使用?
Posted
技术标签:
【中文标题】如何将 cuda 驱动程序 api 与 cuda 运行时 api 混合使用?【英文标题】:how can I mix cuda driver api with cuda runtime api? 【发布时间】:2020-05-24 17:03:00 【问题描述】:来自cuda document 声明:
-
如果通过驱动程序 API 创建上下文并使其成为当前上下文,则后续运行时调用将获取此上下文,而不是创建新上下文。
如果运行时已初始化(在 CUDA 运行时中隐含提及),可使用 cuCtxGetCurrent() 检索初始化期间创建的上下文。后续驱动程序 API 调用可以使用此上下文。
我可以使第一点起作用。我可以从 cuda 驱动程序创建上下文。然后我可以使用 cuda 运行时函数而不调用 cudaSetDevice()
,这会隐式创建一个新的主上下文。
但是,我想通过第二个选项工作。那就是先初始化运行时然后执行cuCtxGetCurrent()
并在 cuda 驱动程序 api 中使用它。这根本不起作用。我总是提出错误说上下文已被破坏或无效。我做错了什么?
这是我的示例代码:
#define CUDA_DRIVER_API
#include <cuda.h>
#include <cuda_runtime.h>
#include <helper_cuda.h>
#include <iostream>
CUcontext check_current_ctx()
CUcontext context0;
unsigned int api_ver;
checkCudaErrors(cuCtxGetCurrent(&context));
fprintf(stdout, "current context=%p\n", context);
checkCudaErrors( cuCtxGetApiVersion(context, &api_ver));
fprintf(stdout, "current context api version = %d\n", api_ver);
return context;
auto inital_runtime_context()
int current_device = 0;
int device_count = 0;
int devices_prohibited = 0;
CUcontext current_ctx0;
cudaDeviceProp deviceProp;
checkCudaErrors(cudaGetDeviceCount(&device_count));;
if (device_count == 0)
fprintf(stderr, "CUDA error: no devices supporting CUDA.\n");
exit(EXIT_FAILURE);
// Find the GPU which is selected by Vulkan
while (current_device < device_count)
cudaGetDeviceProperties(&deviceProp, current_device);
if ((deviceProp.computeMode != cudaComputeModeProhibited))
checkCudaErrors(cudaSetDevice(current_device));
checkCudaErrors(cudaGetDeviceProperties(&deviceProp, current_device));
printf("GPU Device %d: \"%s\" with compute capability %d.%d\n\n",
current_device, deviceProp.name, deviceProp.major,
deviceProp.minor);
CUcontext current_ctx;
cuCtxGetCurrent(¤t_ctx);
std::cout << "current_ctx=" << current_ctx << "\n";
return current_device;
else
devices_prohibited++;
current_device++;
if (devices_prohibited == device_count)
fprintf(stderr,
"CUDA error:"
" No Vulkan-CUDA Interop capable GPU found.\n");
exit(EXIT_FAILURE);
return -1;
void test_runtime_driver_op()
inital_runtime_context();
check_current_ctx();
它报告:
GPU Device 0: "GeForce RTX ..." with compute capability 7.5
current_ctx=0x6eb220
current context=0x6eb220
CUDA error at ... code=201(CUDA_ERROR_INVALID_CONTEXT) "cuCtxGetApiVersion(context, &api_ver)"
【问题讨论】:
您可能需要实际包含一个 API 调用,如cudafree(0)
以使运行时 API 创建一个上下文。您现有的代码可能不会强制创建惰性上下文
@talonmies 非常感谢!这真的有效。但是那文件有错吗?由于从文档中, cudaSetDevice() 应该已经创建了 cuda 上下文。你能把这个总结为答案吗?那我就接受了。
我不认为文档是错误的,但是在运行时 API 中创建上下文的确切时间和方式一直有点模棱两可
为您提供进一步的“轻读”:How do the CUDA Runtime's current device and the driver context stack interact?
【参考方案1】:
您收到错误的原因是,至少在这种情况下,当您尝试使用驱动程序 API 绑定到上下文时,没有发生延迟运行时 API 上下文创建。确保您获得使用运行时创建的上下文的规范方法一直是
cudaSetDevice(current_device);
cudaFree(0);
文档在这一点上一直模棱两可,语义似乎随着时间的推移发生了微妙的变化,但这种调用一直对我有用。
【讨论】:
【参考方案2】:@talonmies 的答案是正确的,从某种意义上说它会起作用,但是 - 如果你想从 driver 方面纠正问题,你可以尝试类似:
// ...
CUcontext check_current_ctx()
CUcontext context0;
checkCudaErrors( cuCtxGetCurrent(&context) );
CUdevice device;
checkCudaErrors( cuCtxGetDevice(&device) );
CUcontext primary_context;
checkCudaErrors( cuDevicePrimaryCtxRetain(&primary_context, device) );
unsigned int flags;
int active;
CUresult primary_state_check_result =
cuDevicePrimaryCtxGetState(device, unsigned &flags, &active);
// etc. etc.
现在您可以检查了:
-
当前设备的当前上下文是否是主要的(= 运行时 API 的上下文)。
主上下文是否已初始化(通过比较
primary_state_check_result
与 CUDA_ERROR_DEINITIALIZED
和 CUDA_ERROR_NOT_INITIALIZED
)。
然后尝试获取 API 版本。
我还应该提到,我编写了一个 C++ 包装层,它涵盖了两个驱动程序和运行时 API,并允许无缝使用这两者;请参阅 cuda-api-wrappers 库的 this branch。它们尚未发布(截至撰写本文时),但非常欢迎您试一试。
【讨论】:
以上是关于如何将 cuda 驱动程序 api 与 cuda 运行时 api 混合使用?的主要内容,如果未能解决你的问题,请参考以下文章
我应该如何以及何时将倾斜指针与 cuda API 一起使用?
将 cv::cuda::GpuMat 与推力和测试推力 API 一起使用时出现问题