【问题标题】:how can I mix cuda driver api with cuda runtime api?如何将 cuda 驱动程序 api 与 cuda 运行时 api 混合使用?
【发布时间】:2020-05-24 17:03:00
【问题描述】:

来自cuda document 声明:

  1. 如果通过驱动程序 API 创建上下文并使其成为当前上下文,则后续运行时调用将获取此上下文,而不是创建新上下文。
  2. 如果运行时已初始化(在 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 context{0};
    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_ctx{0};

    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(&current_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 中创建上下文的确切时间和方式一直有点模棱两可

标签: c++ cuda


【解决方案1】:

您收到错误的原因是,至少在这种情况下,当您尝试使用驱动程序 API 绑定到上下文时,没有发生延迟运行时 API 上下文创建。确保您获得使用运行时创建的上下文的规范方法一直是

cudaSetDevice(current_device);
cudaFree(0);

文档在这一点上一直模棱两可,语义似乎随着时间的推移发生了微妙的变化,但这种调用一直对我有用。

【讨论】:

    【解决方案2】:

    @talonmies 的答案是正确的,从某种意义上说它会起作用,但是 - 如果你想从 driver 方面纠正问题,你可以尝试类似:

    // ...
    CUcontext check_current_ctx()
    {
        CUcontext context{0};
        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.
    }
    

    现在您可以检查了:

    1. 当前设备的当前上下文是否是主要的(= 运行时 API 的上下文)。
    2. 主上下文是否已初始化(通过比较 primary_state_check_resultCUDA_ERROR_DEINITIALIZEDCUDA_ERROR_NOT_INITIALIZED)。

    然后尝试获取 API 版本。


    我还应该提到,我编写了一个 C++ 包装层,它涵盖了两个驱动程序和运行时 API,并允许无缝使用这两者;请参阅 cuda-api-wrappers 库的 this branch。它们尚未发布(截至撰写本文时),但非常欢迎您试一试。

    【讨论】:

      猜你喜欢
      • 2010-09-19
      • 2020-09-22
      • 2015-03-05
      • 2021-10-31
      • 2012-06-15
      • 2014-01-08
      • 1970-01-01
      • 2016-03-09
      • 2011-10-29
      相关资源
      最近更新 更多