Mar*_*rák 6 java windows opencl
当使用也运行主显示器的GPU在Windows上运行长OpenCL计算时,操作系统可能会使用超时检测和恢复中断计算.
根据我的经验(Java,使用NativeLibs4Java的JavaCL,使用NVidia GPU),这在ivoking clEnqueueReadBuffer时表现为"Out Of Resources"(cl_out_of_resources)错误.
问题是,由于其他原因(例如,由于访问无效内存),我在OpenCL程序时得到完全相同的消息.
是否存在(半)可靠的方法来区分由TDR引起的"资源外"和由其他问题引起的"资源外"?
或者,我至少可以(在Java /通过OpenCL API中)确定用于计算的GPU是否也在运行显示器?
但是我知道这个问题,那里的答案是关于clFinish没有返回的情况,这对我来说不是问题(我的代码到目前为止从未在OpenCL API中保持冻结).
是否有一种(半)可靠的方法来区分由 TDR 引起的“资源不足”和由其他问题引起的“资源不足”?
1)
如果您可以访问
Run Code Online (Sandbox Code Playgroud)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 将其乘以
Run Code Online (Sandbox Code Playgroud)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 秒的时间。而且,你应该得到
Run Code Online (Sandbox Code Playgroud)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。除此之外,还有线程从驱动程序退出的时间限制,
Run Code Online (Sandbox Code Playgroud)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。如果这个版本运行但长时间运行的内核不运行,则为TDR故障。如果相反,则为内存崩溃。看起来像这样:
short running x 1024 times
long running
long running <---- fail? TDR! because memory would crash short ver. too!
long running
Run Code Online (Sandbox Code Playgroud)
另一种尝试:
short running x 1024 times <---- fail? memory! because only 1ms per kernel
long running
long running
long running
Run Code Online (Sandbox Code Playgroud)
或者,我至少可以可靠地(在 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))
Run Code Online (Sandbox Code Playgroud)
这给出了可互操作的设备列表。如果你不想使用它,你应该获取它的 id 以将其排除。
2)
让另一个线程运行一些 opengl 或 directx 静态对象绘制代码以使其中一个 GPU 保持忙碌。然后使用另一个线程同时测试所有 GPU 的一些简单的 opencl 内核代码。测试:
执行此操作时,不应在设备之间复制任何数据,这样 CPU/RAM 就不会成为瓶颈。
3)
如果数据是可分离的,那么您可以使用分治算法让任何 GPU 仅在可用时才获得自己的工作,并让显示部分更加灵活(因为这是性能感知的解决方案,可能类似于短路)正在运行的版本,但调度是在多个 GPU 上完成的)
4)
我没有检查,因为我卖掉了我的第二个 GPU,但是,你应该尝试一下
CL_DEVICE_TYPE_DEFAULT
Run Code Online (Sandbox Code Playgroud)
在您的多 GPU 系统中测试它是否获得显示 GPU。关闭电脑,将显示器电缆插入其他卡,然后重试。关机,换卡座,再试一次。关闭,移除其中一张卡,只剩下 1 个 gpu 和 1 个 cpu,然后重试。如果所有这些仅提供显示 GPU,那么它应该将显示 GPU 标记为默认值。