【问题标题】:DXGI_ERROR_DEVICE_HUNG resulting from concurrency::copy on C++ AMPDXGI_ERROR_DEVICE_HUNG 由 C++ AMP 上的 concurrency::copy 产生
【发布时间】:2015-04-25 00:29:55
【问题描述】:

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

在我启动 concurrency::copy 操作以将数据从 GPU 阵列复制回 CPU 之前,一切都很顺利。该操作会引发一个异常,表明 TDR 已因DXGI_ERROR_DEVICE_HUNG 而被触发。完整的错误是:

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 的复制都完成得很好。

【问题讨论】:

    标签: gpgpu direct3d11 c++-amp


    【解决方案1】:

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

    recommendations 是:

    • 将处理分成更小的块或简化计算操作
    • 在 DirectX 11.1+ 中使用D3D11_CREATE_DEVICE_DISABLE_GPU_TIMEOUT(请参阅this post
    • edit the registry延长超时时间,这真的只对开发有用。

    编辑:问题最有可能出现在filter-&gt;FilterFrame,它是成为可能导致 TDR 的 DirectCompute 着色器的 C++ AMP 代码。由于 CPU/GPU 同步/时序差异,稍后返回错误这一事实不足为奇。

    【讨论】:

    • 我不相信你真的读过这个问题。错误发生在对 concurrency::copy 的调用上,而不是在我的着色器上。你是在建议我把副本分成更小的块吗? 10,000 个元素是否需要这样做?当然,它可以在不到 2 秒的时间内将 10,000 个浮点数从 gpu 复制到 cpu。
    • AMP 将您的 C++ 转换为 DIrectCompute 着色器,因此我将“着色器”与“代码”互换使用。我很抱歉造成混乱。我预计问题可能发生在filter-&gt;FilterFrame,因为当您尝试执行复制并超过 TDR 超时时它仍在运行。尝试我链接的补救措施,看看是否可以解决它们,或者尝试一个简单的GradientRemovalFilter 版本。请记住,GPU 和 CPU 没有同步,许多 Direct3D 操作会排队并分批发生。
    • 谢谢,这个澄清对于问题的根源非常有见地。我认为,如果您可以编辑您的答案以专注于强制同步的副本的洞察力以及将其作为“原因”作为红鲱鱼的“原因”而进行的调试,那将是一件好事。对于将来遇到这个明显问题的其他人来说,这可能是最有用的信息,我会接受答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    • 1970-01-01
    • 2016-01-28
    • 2013-01-08
    相关资源
    最近更新 更多