使用非默认GPU时从cudaLaunchKernel返回的资源句柄无效

时间:2019-05-14 19:41:30

标签: cuda

我有一个CUDA程序,当在默认GPU上运行时,该程序运行无错误。当我在main()函数的第一行将设备设置为GPU#1时,不会立即出现错误(这并不奇怪,因为nvidia-smi确认我的计算机中有8个GPU )。以后,当程序尝试启动内核时,遇到invalid resouce handle(400)错误。

我试图提出一个最小的可行示例,但是下面的代码当然运行良好。尽管如此,它仍然说明了这个概念,因此我将其包括在内。 我的真实代码使用多个CPU线程,每个线程都启动自己的内核。

#include <iostream>
#include <stdio.h>
#include <cuda_runtime_api.h>
#include <cuda.h>


static void CheckCudaErrorAux (const char *, unsigned, const char *, cudaError_t);
#define CUDA_CHECK_RETURN(value) CheckCudaErrorAux(__FILE__,__LINE__, #value, value)

void CheckCudaErrorAux (const char *file, unsigned line, const char *statement, cudaError_t err) {
    if (err == cudaSuccess)
        return;
    std::cerr << statement<<" returned " << cudaGetErrorString(err) << "("<<err<< ") at "<<file<<":"<<line << std::endl;
    exit (1);
}


__global__ void foo() {
    printf("I'm a foo\n");
}

int main() {

    CUDA_CHECK_RETURN(cudaSetDevice(1));
    cudaStream_t stream;
    CUDA_CHECK_RETURN(cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking));

    void *kernelArgs[] = {
    };

    CUDA_CHECK_RETURN(cudaLaunchKernel((void*) &foo, 80, 4, kernelArgs, 0, stream)); // THIS RETURNS THE INVALID RESOURCE HANDLE
    CUDA_CHECK_RETURN(cudaStreamSynchronize(stream));

    printf("Finished kernel; exiting gracefully.\n");
    return 0;
}

我的印象是,这很可能是流问题。但是,由于实际程序在默认GPU下可以正常运行,而无需对流进行任何更改,因此我倾向于排除这种情况。

我对多GPU编程非常陌生,因此我正在寻找有关其他可能导致此问题的建议。谢谢!

更新

更改内核调用以使用默认流而不是指定流不会产生任何错误。但是,当我尝试在默认流上进行同步时,我遇到了其他问题(可能可以解决,但后来我们找到了解决方案,于是我停在了那里)。

1 个答案:

答案 0 :(得分:2)

每个CPU线程可以与另一个GPU设备关联。

这样,一旦我修改了线程的执行,以便它们在生成之后分别调用cudaSetDevice(1),问题就消失了。

最初出现此问题是因为流是为第一个GPU设备创建的,但是产生的cpu线程正试图在默认gpu(即设备0)上启动内核。

这在https://devblogs.nvidia.com/cuda-pro-tip-always-set-current-device-avoid-multithreading-bugs/

中进行了粗略讨论