DXGI_ERROR_DEVICE_HUNG由C ++ AMP上的concurrency :: copy产生

时间:2015-04-25 00:29:55

标签: gpgpu direct3d11 c++-amp

我创建了一些C ++ AMP代码,用于在天文图像上执行背景渐变去除。它们以RGB的16位无符号整数形式出现。我的所有应用程序的处理和输出都是以单精度浮点运行的,所以我转换输入数据,运行C ++ AMP代码,然后将结果复制回CPU(实际上,图像将通过许多这些C ++ AMP过滤器在被复制之前在GPU上,但对于这个测试代码,我已将它隔离到一个这样的过滤器。

一切顺利,直到我启动concurrency :: copy操作将数据从GPU阵列复制回CPU。该操作会抛出异常,指示由于DXGI_ERROR_DEVICE_HUNG已触发TDR。完整的错误是:

  

D3D11错误:ID3D11Device :: RemoveDevice:由于以下原因触发了设备删除(DXGI_ERROR_DEVICE_HUNG:设备执行其命令花费了不合理的时间,或硬件崩溃/挂起。因此,TDR(已经触发了超时检测和恢复机制。当挂起发生时,当前的设备上下文正在执行命令。应用程序可能希望重新生成并回退到不太积极地使用显示硬件)。 [执行错误#378:DEVICE_REMOVAL_PROCESS_AT_FAULT]

以下是相关代码。我省略了过滤器的代码,因为它使所有过滤器都很好(我在调试器中逐步完成)并且只在它复制回CPU时抛出异常。以下代码中的问题行为concurrency::copy(frame, begin(cpu_frame));

array<float_3, 2> convert_input(std::vector<float_3> &output, unsigned short *input, int n, int m) {
    int o = 0;

    for (int i = 0; i < n * m * 3; i += 3) {
        output[o] = float_3((float)input[i] / (float)MAXUINT16, (float)input[i + 1] / (float)MAXUINT16, (float)input[i + 2] / (float)MAXUINT16);
        o++;
    }

    return array<float_3, 2>(n, m, begin(output));
}

void _stdcall remove_gradient(unsigned short *input, float *output, int n, int m)
{
    std::vector<float_3> cpu_frame(n * m);

    array<float_3, 2> frame = convert_input(cpu_frame, input, n, m);

    GradientRemovalFilter *filter = new GradientRemovalFilter();

    try {
        filter->FilterFrame(frame);

        concurrency::copy(frame, begin(cpu_frame));
    }
    catch (accelerator_view_removed &ex) {
        std::cout << ex.what() << std::endl;
        std::cout << ex.get_view_removed_reason() << std::endl;
    }

    for (int i = 0; i < n * m; i ++) {
        output[(i * 3)] = cpu_frame[i].r;
        output[(i * 3) + 1] = cpu_frame[i].g;
        output[(i * 3) + 2] = cpu_frame[i].b;
    }
}

知道出了什么问题以及如何预防?我的测试图像大约是10,000个像素,所以非常小,比实际使用的小得多,所以我不明白为什么复制回来需要足够长的时间来导致TDR启动,特别是当复杂的处理和复制到GPU正在完成。

1 个答案:

答案 0 :(得分:1)

上面的错误输出告诉你发生了什么:你的着色器花了这么长时间,驱动程序认为GPU挂了。

这里的recommendations是:

  • 将处理分解为更小的块或简化计算操作
  • D3D11_CREATE_DEVICE_DISABLE_GPU_TIMEOUT与DirectX 11.1+一起使用(请参阅this post
  • edit the registry延长超时时间,这对开发非常有用。

编辑:问题最有可能发生在filter->FilterFrame,这是C ++ AMP代码,它会成为可能导致TDR的DirectCompute着色器。由于CPU / GPU同步/时序差异,错误稍后返回的事实并不令人惊讶。