【发布时间】: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