cudaDeviceReset()的正确使用方法

5

我怀疑在某些较大的代码(可能还有其他情况)中,“黑盒子”(GPU)无法完全关闭,因此我建议在main()函数结束时添加cudaDeviceReset()。但是等等!这样会导致在main()中静态创建、并且析构函数中包含非平凡CUDA代码的所有类实例都会出现Segmentation fault,对吗?例如:

class A {
public:
  cudaEvent_t tt;
  cudaEvent_t uu;
  A() { 
    cudaEventCreate(&tt);
    cudaEventCreate(&uu);
  }
  ~A(){  
    cudaEventDestroy(tt);
    cudaEventDestroy(uu);
  }
};

静态实例化:

int main() {
  A t;
  cudaDeviceReset();
  return 0;
} 

退出时出现段错误。问题:是不是从main()退出时自动调用了cudaDeviceReset()

否则,main()的整个有用代码应该移到某个run()中,并且cudaDeviceReset()应该作为main()中的最后一条命令,对吗?


2
cudaDeviceReset会显式地销毁由调用它的进程或线程持有的活动设备上下文。但这就是它所做的全部。如果您的CUDA API调用需要一个上下文来在析构函数代码中工作,那么您不能在上下文已经被销毁后再调用它们(当进程终止时,运行时将自动销毁上下文)。 - talonmies
1个回答

3
根据Talonmies的说法,当主函数(main(..))结束时,会先调用cudaDeviceReset()函数,然后才会调用A类的析构函数。
我认为,你可以将cudaDeviceReset()函数放入到一个atexit(..)函数中。
void myexit() {
  cudaDeviceReset();
}

int main(...) {
  atexit(myexit); 
  A t;
  return 0;
}

1
因此,您可以尝试在另一个括号中声明“t”。然后在该括号结束后调用cudaDeviceReset。这样可能会在设备重置之前强制销毁“t”。 """ int main(..) { { A t; t.someoperation(); } cudaDeviceReset(); } """ - phoad
谢谢。我认为这是一个好观点。我会尽快检查并告诉你。 - Vitality
这个主题有一个由Talonmies在CUDA streams destruction and CudaDeviceReset上的有趣讨论。 - Vitality
是的,特别是涉及到CUDA的话题,Talonmies是王者。我真的很好奇他回答了哪些与CUDA相关的问题。让我们看看。感谢Talonmies。 - phoad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接