java - OpenCL:区分计算失败与 TDR 中断

标签 java windows opencl

当使用同时运行主显示器的 GPU 在 Windows 上运行长时间的 OpenCL 计算时,操作系统可能会用 Timeout Detection and Recovery 中断计算。 .

根据我的经验(Java,通过 NativeLibs4Java 使用 JavaCL,使用 NVidia GPU)这在调用 clEnqueueReadBuffer 时表现为“资源不足”(cl_out_of_resources)错误。

问题是当 OpenCL 程序出于其他原因(例如,由于访问无效内存)时,我得到了完全相同的消息。

是否有一种(半)可靠的方法来区分由 TDR 引起的“资源不足”和由其他问题引起的“资源不足”?

或者,我能否至少可靠地(在 Java 中/通过 OpenCL API)确定用于计算的 GPU 也在运行显示?

我知道 this question然而,答案与 clFinish 不返回的情况有关,这对我来说不是问题(到目前为止,我的代码从未在 OpenCL API 中保持卡住状态)。

最佳答案

Is there a (semi) reliable way to distinguish between an "Out of Resources" caused by TDR and an "Out of Resources" caused by other problems?

1)

如果可以访问

KeyPath   :
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\GraphicsDrivers
KeyValue  : TdrDelay ValueType : REG_DWORD ValueData : Number of
seconds to delay. 2 seconds is the default value.

从 WMI 乘以

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 秒。访问无效的内存段应该会更快退出。也许您可以将这些来自 WMI 的 TDR 时间限制增加到几分钟,这样它就可以让程序计算而不会因为抢占饥饿而崩溃。但是更改注册表可能很危险,例如,您将 TDR 时间限制设置为 1 秒或其中的一部分,然后 Windows 可能永远不会在没有持续的 TDR 崩溃的情况下启动,因此只读取这些变量必须更安全。

2)

您将全部工作分成更小的部分。如果数据不可分离,则复制一次,然后开始将长时间运行的内核作为非常短范围的内核排队 n 次,并在任意两次之间进行一些等待。

然后,您必须确保 TDR 已被消除。如果这个版本跑了,而long-running-kernel不跑,就是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

Alternately, can I at least reliably (in Java / through OpenCL API) determine that the GPU used for computation is also running the display?

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 静态对象绘图代码以保持其中一个 GPU 忙碌。然后使用另一个线程同时测试所有 gpus 以获取一些微不足道的 opencl 内核代码。测试:

  • opengl 开始绘制具有高三角形数 @60 fps 的东西。
  • 启动用于 opencl 计算的设备,获取每秒平均内核执行数
  • 设备 1:30 keps
  • 设备 2:40 keps
  • 片刻之后,停止 opengl 并关闭其窗口(如果尚未关闭)
  • 设备 1:75 keps -----> 百分比增加最高!-->显示!!!
  • 设备 2:41 keps ----> 没有那么高,但可以

执行此操作时不应在设备之间复制任何数据,这样 CPU/RAM 就不会成为瓶颈。

3)

如果数据是可分离的,那么你可以使用分而治之的算法让任何 gpu 只在它可用时得到它自己的工作并让显示部分更灵活(因为这是性能感知解决方案并且可以类似短期运行的版本,但调度是在多个 gpus 上完成的)

4)

我没有检查因为我卖掉了我的第二个 gpu 但是,你应该试试

CL_DEVICE_TYPE_DEFAULT

在您的多 GPU 系统中测试它是否获得显示 GPU。关闭电脑,将显示器电缆插入其他卡,然后重试。关机,换牌位,再试。关机,取出其中一张卡,只剩下 1 个 gpu 和 1 个 cpu,再试一次。如果所有这些只提供显示 gpu,那么它应该将显示 gpu 标记为默认值。

关于java - OpenCL:区分计算失败与 TDR 中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40503644/

相关文章:

python - Winreg Python、QueryInfoKey 给出的上次更改的日期/时间不正确?

C++通过Windows搜索路径查找可执行文件

c++ - IO 完成端口和套接字 send()

c++ - OpenCL C++ 上下文属性语法

java - Jboss - 部署 - 由 HDScanner 在爆炸的耳朵中引起的取消部署循环

java - 接口(interface)层次结构中的循环

opencl - 在 OpenCL 中使用 128 位或 256 位无符号整数?

opencv - 在Linux上将OpenCL与Intel UHD图形一起使用

java - 创建 Esper 的 epl 实例

java - 谷歌日历