我已经创建了一些C++ AMP代码,以执行背景梯度去除天文图像。它们作为RGB的16位无符号整数出现。我的应用程序的所有处理和输出都是以单精度浮点进行的,因此我转换输入数据,运行C++ AMP代码,然后将结果复制回CPU (实际上,在复制回GPU之前,图像将经过GPU上的许多C++ AMP过滤器,但是对于这个测试代码,我已经将其隔离到一个这样的过滤器中。
一切都进行得很顺利,直到我启动并发性::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的工作完成得很好时。
发布于 2015-04-25 05:07:40
上面的错误输出告诉了您发生了什么:您的着色器花了很长时间,驱动程序计算出GPU挂起。
这里的建议是:
D3D11_CREATE_DEVICE_DISABLE_GPU_TIMEOUT与DirectX 11.1+一起使用(参见这个职位)编辑:问题最可能出现在filter->FilterFrame中,这是C++ AMP代码,它成为可能导致TDR的DirectCompute着色器。由于CPU/GPU同步/定时的差异,错误稍后返回的事实并不令人惊讶。
https://stackoverflow.com/questions/29859631
复制相似问题