【问题标题】:CUDA Runtime API error 30: Repeated kernel callsCUDA 运行时 API 错误 30:重复内核调用
【发布时间】:2012-08-30 16:01:39
【问题描述】:

我最近开始学习 CUDA,我偶然发现了一个我无法理解的非常奇怪的行为。

我的代码本质上是计算一个简单 atomicAdd 内核的平均执行时间。为此,我在循环中调用内核以获得更好的平均值。我将设备内存分配和副本包含在循环中,因为我想将其包含在我的执行时间估计中。问题是,如果循环的运行次数过多,程序通常会失败并出现 Runtime API 错误 30。

我怀疑我的内存访问可能有问题,所以我在程序上运行 memcheck 无济于事。显然没有内存错误。此外,如果只运行内核几次,就没有问题,这似乎也表明内核并不是问题所在。只有连续调用太频繁才会有问题。

我的代码框架如下:

for(int i = 0; i < runs; i++)
{


    //////////////////////////////////
    // Copy memory from Host to Device
    //////////////////////////////////

    cutilSafeCallNoSync( cudaMemcpy(dev_waveforms, waveforms, num_wf * wf_length *  sizeof(float), 
                        cudaMemcpyHostToDevice) );
    cutilSafeCallNoSync( cudaMemcpy(dev_delays, delays, num_wf * sizeof(int), 
                        cudaMemcpyHostToDevice) );




    ////////////////////////
    // Kernel Call
    ////////////////////////

    kernel_wrapper<float>(dev_waveforms, dev_focused, dev_delays, 
                    wf_length, num_wf, threads, blocks, kernel); 

    //copy back to host memory.
    cutilSafeCallNoSync( cudaMemcpy(focused, dev_focused, J * wf_length * sizeof(float), 
        cudaMemcpyDeviceToHost) );

}

同样,只有在运行足够大时才会失败。还有其他一些奇怪的事情发生了,但我暂时不谈了。

哦,我正在使用 Visual Studio 2010 在 Windows 7 上进行开发。我的 GPU 还充当我的视频卡,我担心这可能会产生奇怪的效果。

提前致谢!

【问题讨论】:

  • 在 Windows 下有一个看门狗定时器,它可以在长内核上跳闸。多个没有同步的内核可能会导致相同的问题。查看它是否与时间阈值(例如 30 秒)有关。
  • 根据@PaulR 所说,尝试在循环中添加cudaDeviceSynchronize();
  • 快速更新:我已将看门狗计时器的阈值从默认的 2 设置为 8 秒。我最初认为这有帮助,因为我成功了 8/10 次。但是,我刚刚又试了一次,成功率为0%。不一致使得调试变得困难。尽管如此,这并不能解释更改数组大小如何影响问题。此外,数组的内容似乎也有影响。

标签: cuda


【解决方案1】:

Windows 7 驱动程序可以将多个命令批处理到单个提交中,以规避 WDDM 增加的驱动程序开销(与 WDDM 之前的驱动程序相比,例如 Win XP)。出于这个原因,即使单个内核没有超过看门狗,在这样的循环中运行也可能。你可以打电话给cudaDeviceSynchronize() @RogerDahl 建议尝试解决它(可能只有每 N 次迭代)。

或者在 Linux 上运行。

编辑: 运行时错误 30 是未知错误。如果这是看门狗定时器超时,我会期待 cudaErrorLaunchTimeout(错误 6)。由于您没有提供完整的代码,因此很难说是什么导致了错误。我怀疑您的内核代码中存在错误。

【讨论】:

  • 感谢大家的建议。我在循环中添加了“cudaDeviceSynchronize()”,但问题仍然存在。我正在研究更改与看门狗计时器关联的注册表项,我将对此进行测试,但我怀疑这不是问题。我发现,如果通过在代码中设置 J=2 将输出数组的大小加倍,则可以消除该问题。例如,如果我的运行次数 = 1000,则程序在 J = 1 时只会成功 2/10 次。在 J = 2 时,成功率为 10/10。所以这是一个解决方案,但我没有解释。
【解决方案2】:

我遇到了同样的错误,发现我的内核实际上超出了我分配的内存。由于您将缓冲区加倍并看到问题消失,因此我预计您可能会遇到同样的问题。

我的问题是我在确定要启动多少线程和块的数学中存在错误。我发射的区块数量是我预期的八倍。在我的内核中,确定给定线程应该处理哪个元素的数学运算导致访问我的数组之外的方式。

确保检查每个线程正在处理数组的哪些元素,以防止执行将访问/修改数组外内存的线程。

【讨论】:

    【解决方案3】:

    对于其他来此帖子寻找答案的人为什么会收到错误 30 消息:

    如果您不小心将 CPU 变量作为 GPU device 函数的参数之一,也会出现此错误。这对我来说是这个问题的最常见原因。您会认为在多次意外地将变量的 cpu 副本作为参数放置之后,您会学到,但是 ...

    确保您的设备功能的所有参数: myDeviceFunciont>>(argument1,argument2,argument3)

    是 GPU 变量(即:您在 cudaMalloc 和 cudaMemcpy 中用于在 GPU 上分配内存的变量)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-06
      • 1970-01-01
      • 1970-01-01
      • 2012-06-15
      • 2013-07-03
      • 2019-02-24
      • 2021-05-31
      • 1970-01-01
      相关资源
      最近更新 更多