我遇到了一些奇怪的问题,我正在研究一些OpenCL代码,每一次在蓝色的月亮中,Windows TDR都会启动并重置GPU。令人讨厌的内核只运行150ms,并且在TDR终止之前将运行数千次(在数小时内),所以我确信内核本身不应该受到责备。
我担心的是,一旦TDR启动,内核就会死掉,程序会陷入永恒的状态。据我所知,对clFinish
的调用永远不会回来。
有没有办法检测内核是否已经消失,以便可以优雅地处理它?
答案 0 :(得分:1)
我设法提出了一个解决方案,虽然它远非最优化。
我修改了程序,以便OpenCL处理在一个单独的线程中完成。我在父进程和子进程之间创建了一个全局共享监视器变量。当父进程将处理函数作为线程生成时,它将变量设置为当前时间(以毫秒为单位)。当处理线程完成时,它会将看门狗变量重置为零。
当父线程等待处理线程完成时,它会一直关注看门狗定时器。如果计时器超过某个阈值,则程序强制终止自身而不等待子进程返回。
此解决方案可以使用或不使用Windows TDR设置。如果设置了TDR并且驱动程序重置,则对clFinish()的调用将永远不会返回,并且一旦看门狗定时器跳闸,父节点将终止。如果未设置TDR,则失控进程将冻结显示,但一旦看门狗定时器跳闸,父进程将终止处理,结束冻结。
现在我有一个看门狗设置,我只是将我的程序包装在一个脚本中:如果它以错误终止(正回程代码),则程序重新运行。
答案 1 :(得分:0)
理想情况下,您应该从clFinish或clWaitForEvents获取一个错误代码,其中包含在将内核排入队列时生成的OpenCL事件对象。由于TDR重置了图形驱动程序,我认为任何OpenCL实现都不会可靠运行,这意味着没有恢复路径。
完全禁用TDR。只有当您调试陷入无限循环的代码时,才会永久保持GPU忙碌。
如果你想保留TDR但可以更改代码,那么使用某种线程休眠功能将代码延迟几毫秒也可以缓解这个问题,但代价是牺牲了处理速度。这使图形卡有机会响应显示渲染命令,从而不会触发TDR。