我有一个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编程非常陌生,因此我正在寻找有关其他可能导致此问题的建议。谢谢!
更新
更改内核调用以使用默认流而不是指定流不会产生任何错误。但是,当我尝试在默认流上进行同步时,我遇到了其他问题(可能可以解决,但后来我们找到了解决方案,于是我停在了那里)。
答案 0 :(得分:2)
每个CPU线程可以与另一个GPU设备关联。
这样,一旦我修改了线程的执行,以便它们在生成之后分别调用cudaSetDevice(1),问题就消失了。
最初出现此问题是因为流是为第一个GPU设备创建的,但是产生的cpu线程正试图在默认gpu(即设备0)上启动内核。
这在https://devblogs.nvidia.com/cuda-pro-tip-always-set-current-device-avoid-multithreading-bugs/
中进行了粗略讨论