CUDA内核随机失败,但仅当我使用某些超越函数时

njo*_*188 5 cuda

我一直在研究CUDA程序,该程序随机地因崩溃而unspecified launch failure相当频繁。通过仔细的调试,我确定了哪个内核发生了故障,此外,只有从CUDA内核中调用了某些先验功能(例如sinf()atanhf()),该故障才会发生。

这使我编写了一个简单得多的程序(请参见下文),以确认这些先验功能确实引起了问题,看起来确实如此。当我编译并运行下面的代码(反复重复调用使用tanh和atanh的内核)时,有时该程序可以运行,有时它Error with Kernel与驱动程序的消息一起输出,并显示:

NVRM:XiD(0000:01:00):13,0002 000000 000050c0 00000368 00000000 0000080

关于频率,它可能崩溃了我运行可执行文件的时间的50%。

从我在网上阅读的内容来看,这听起来像是XiD 13基于主机的段错误。但是,给定数组索引后,我看不到实际情况如何。此外,如果我将内核中的先验功能替换为其他功能(例如,重复的浮点减法和加法),则程序不会崩溃。也就是说,我没有收到XiD错误消息,程序最终返回了正确的atanh(0.7)值。

我在Ubuntu 11.10 x64 Desktop上运行cuda-5.0。驱动程序版本为304.54,我使用的是GeForce 9800 GTX。

我倾向于说这是硬件问题或驱动程序错误。奇怪的是,nvidia的示例应用程序运行良好,可能是因为它们未使用受影响的先验功能。

潜在的重要信息的最后一点是,如果我运行我的主项目,或者在cuda-memcheck下运行此测试程序,则它不会报告任何错误,并且永远不会崩溃。老实说,我只是在cuda-memcheck下运行我的项目,但是性能下降使它变得不切实际。

在此先感谢您的帮助/咨询。如果有人拥有9800 GTX并愿意运行此代码以查看其是否有效,将不胜感激。

#include <iostream>
#include <stdlib.h>

using namespace std;

__global__ void test_trans (float *a, int length) {
  if ((threadIdx.x + blockDim.x*blockIdx.x) < length) {
    float temp=0.7;
    for (int i=0;i<100;i++) {
      temp=atanh(temp);
      temp=tanh(temp);
    }
    a[threadIdx.x+ blockDim.x*blockIdx.x] = atanh(temp);
  }
}

int main () {
  float *array_dev;
  float *array_host;
  unsigned int size=10000000;
  if (cudaSuccess != cudaMalloc ((void**)&array_dev, size*sizeof(float)) ) {
    cerr << "Error with memory Allocation\n"; exit (-1);}
  array_host = new float [size];

  for (int i=0;i<10;i++) {
    test_trans <<< size/512+1, 512 >>> (array_dev, size);
    if (cudaSuccess != cudaDeviceSynchronize()) {
       cerr << "Error with kernel\n"; exit (-1);}
  }
  cudaMemcpy (array_host, array_dev, sizeof(float)*size, cudaMemcpyDeviceToHost);

  cout << array_host[size-1] << "\n";  
}
Run Code Online (Sandbox Code Playgroud)

编辑:我将该项目删除了几个月,但是昨天在更新为驱动程序版本319.23时,我不再遇到此问题。我认为我描述的问题一定是已修复的错误。希望这可以帮助。

har*_*ism 1

提问者确定这是一个临时问题,已由较新的 CUDA 版本修复。请参阅对原始问题的编辑。