当使用也运行主显示器的GPU在Windows上运行长OpenCL计算时,操作系统可能会使用 Timeout Detection and Recovery中断计算。
根据我的经验(Java,使用NativeLibs4Java的JavaCL,使用NVidia GPU),这表现为" Out Of Resources" ivoking clEnqueueReadBuffer时出现(cl_out_of_resources)错误。
问题是,由于其他原因(例如,由于访问无效内存),我在OpenCL程序时收到完全相同的消息。
是否存在一种(半)可靠的方法来区分“资源外”和“#34;由TDR和" Out of Resources"其他问题引起的?
或者,我是否可以至少可靠地(在Java /通过OpenCL API中)确定用于计算的GPU也在运行显示器?
我知道this question但是,那里的答案是关于clFinish没有返回的情况,这对我来说不是问题(我的代码到目前为止从未在OpenCL API中保持冻结)。
答案 0 :(得分:2)
是否有(半)可靠的方法来区分“Out of “由TDR引起的资源和由其他人引起的”资源外“ 问题
<强> 1)强>
如果可以访问
从WMIKeyPath : HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\GraphicsDrivers KeyValue : TdrDelay ValueType : REG_DWORD ValueData : Number of seconds to delay. 2 seconds is the default value.
将其乘以
KeyPath : HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\GraphicsDrivers KeyValue : TdrLimitCount ValueType : REG_DWORD ValueData : Number of TDRs before crashing. The default value is 5.
再次使用WMI。当你乘以这些时,你得到10秒。而且,你应该得到
KeyPath : HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\GraphicsDrivers KeyValue : TdrLimitTime ValueType : REG_DWORD ValueData : Number of seconds before crashing. 60 seconds is the default value.
应该从WMI读取60秒。
对于此示例计算机,在最终崩溃限制60秒之前需要5 x 2秒+ 1个额外延迟。然后您可以从应用程序检查最后一个秒表计数器是否超过这些限制。如果是,可能是TDR。除此之外还有一个线程退出驱动程序时间限制
KeyPath : HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\GraphicsDrivers KeyValue : TdrDdiDelay ValueType : REG_DWORD ValueData : Number of seconds to leave the driver. 5 seconds is the default value.
默认为5秒。访问无效的内存段应该更快退出。也许你可以将这些TDR时间限制从WMI增加到几分钟,这样它就可以让程序计算而不会因为抢占饥饿而崩溃。但是更改注册表可能很危险,例如您将TDR时间限制设置为1秒或其中的一部分,然后Windows可能永远不会在没有持续TDR崩溃的情况下启动,因此只需读取这些变量就必须更安全。
2)
您将总工作分成更小的部分。如果数据不可分离,请复制一次,然后开始将长期运行的内核作为非常短程的内核排队n次,并在任意两次之间等待。
然后,您必须确保TDR被消除。如果这个版本运行但是长时间运行的内核没有运行,那就是TDR错误。如果相反,那就是内存崩溃。看起来像这样:
short running x 1024 times
long running
long running <---- fail? TDR! because memory would crash short ver. too!
long running
另一次尝试:
short running x 1024 times <---- fail? memory! because only 1ms per kernel
long running
long running
long running
或者,我可以至少可靠地(在Java /通过OpenCL API) 确定用于计算的GPU也在运行 显示?
1)
使用两种设备的互操作性属性:
// taken from Intel's site:
std::vector<cl_device_id> devs (devNum);
//reading the info
clGetGLContextInfoKHR(props, CL_DEVICES_FOR_GL_CONTEXT_KHR, bytes, devs, NULL))
这给出了可互操作的设备列表。如果你不想使用它,你应该得到它的id来排除它。
2)
让另一个线程运行一些opengl或directx静态对象绘图代码,以保持其中一个gpus忙。然后使用另一个线程同时测试所有gpus以获得一些简单的opencl内核代码。测试:
执行此操作时,不应在设备之间复制任何数据,因此CPU / RAM不会成为瓶颈。
3)
如果数据是可分的,那么你可以使用分而治之算法让任何gpu只有在可用时才能获得自己的工作,并让显示部分更具灵活性(因为这是性能感知的解决方案,可能是类似的短版本,但调度是在多个gpus上完成的)
4)
我没有检查,因为我卖掉了我的第二个gpu,但你应该试试
CL_DEVICE_TYPE_DEFAULT
在你的multi-gpu系统中测试它是否得到显示gpu。关闭电脑,将显示器电缆插入其他卡,再试一次。关闭,更换卡座,再试一次。关闭,删除其中一张卡,只留下1个gpu和1个cpu,再试一次。如果所有这些只给出显示gpu那么它应该标记显示gpu为默认值。