我遇到了一些OpenCL代碼中的一個奇怪問題,我正在處理每個藍色月亮的地方,Windows TDR將啓動並重置GPU。有問題的內核只運行150ms,在TDR關閉之前會運行數千次(在幾個小時內),所以我確信內核本身不是責任。檢測並從Windows TDR恢復?
我擔心的是,一旦TDR開始運行,內核就會死亡,程序會陷入永恆的狀態。從我能告訴電話clFinish
永遠不會返回。
有沒有辦法檢測內核是否已經死亡,以便它能夠被正常處理?
我遇到了一些OpenCL代碼中的一個奇怪問題,我正在處理每個藍色月亮的地方,Windows TDR將啓動並重置GPU。有問題的內核只運行150ms,在TDR關閉之前會運行數千次(在幾個小時內),所以我確信內核本身不是責任。檢測並從Windows TDR恢復?
我擔心的是,一旦TDR開始運行,內核就會死亡,程序會陷入永恆的狀態。從我能告訴電話clFinish
永遠不會返回。
有沒有辦法檢測內核是否已經死亡,以便它能夠被正常處理?
我設法想出了一個解決方案,儘管它遠非最佳。
我修改了程序,以便OpenCL處理在單獨的線程中完成。我在父進程和子進程之間創建了一個全局共享的看門狗變量。當父親將處理函數作爲線程產生時,它將該變量設置爲當前時間(以毫秒爲單位)。當處理線程結束時,它將看門狗變量重置爲零。
當父線程等待處理線程完成時,它會關注看門狗定時器。如果計時器超過某個閾值,程序將強制終止而不等待子進程返回。
此解決方案可以使用或不使用Windows TDR集。如果設置了TDR並且驅動程序復位,則對clFinish()的調用將永遠不會返回,並且一旦看門狗定時器跳閘,父節點將終止。如果TDR未設置,失控進程將凍結顯示,但一旦看門狗定時器跳閘,父進程將終止處理,結束凍結。
現在我有一個看門狗設置,我簡單地將我的程序包裝在一個腳本中:如果它以錯誤(正面返回碼)終止,那麼程序將重新運行。
理想情況下,您應該從排隊內核時生成的OpenCL事件對象中獲取clFinish或clWaitForEvents的錯誤代碼。由於TDR重置圖形驅動程序,我認爲任何OpenCL實現都不會可靠工作,這意味着沒有恢復路徑。
完全禁用TDR。只有當您調試代碼時,它纔會被永久保持GPU忙碌的無限循環中。
如果您想保留TDR但可以更改代碼,那麼使用某種線程休眠功能將代碼延遲幾毫秒也可以減輕此問題,但會犧牲處理速度。這使顯卡有機會響應顯示渲染命令,以便TDR不被觸發。