2013-01-04 57 views
1

嗯,我試過在Apple開發人員論壇上詢問,但沒有人回覆。我認爲stackoverflow會更合適。這裏是...嘗試運行內核代碼時OpenCL(意外地)凍結

我有一些OpenCL內核運行通過存儲在幀緩衝區對象中的像素,並計數非黑色和非白色像素。它曾經在我的機器上運行良好,但我相信Mac OS X和/或devtools的更新可能會導致問題導致它停滯。

與內核代碼關聯的內核對象附加到QT窗口,並且當窗口需要渲染更新時,內核代碼將運行n次。該窗口在初始創建後會更新兩次,這意味着openCL代碼的序列最初不會導致問題。當我將窗口置於前臺時,它需要另一次更新,並嘗試再次運行內核代碼n次。但是在這些n次中間,它停滯不前。即如果它需要運行51次,則它在第26次迭代時停頓。看起來對clEnqueueReadBuffer的調用導致失速。

我打算略去有關爲什麼我使用openCL代碼的詳細信息,除非它是絕對必要的,因爲這可能會讓人們感到困惑。我認爲將重點放在OpenCL代碼本身上會很好。在這裏它是供參考:http://dl.dropbox.com/u/10838242/forumsquestion.cpp

這裏的gdb的回溯:

#0 0x00007fff8e3a6122 in __psynch_mutexwait() 
#1 0x00007fff8955ad9d in pthread_mutex_lock() 
#2 0x000000010dd3acbd in gldFlushQueue() 
#3 0x000000010bbc193f in IOAccelContextFinishResourceSysMem()  
#4 0x000000010bbcd5b0 in gpumAcquireFenceOnQueue() 
#5 0x000000010dd43fcd in gldCopyBufferDataWithQueue() 
#6 0x00007fff8ffa7e2e in GCC_except_table49() 
#7 0x00007fff8ffc5f11 in clFinish() 
#8 0x00007fff936800b6 in _dispatch_client_callout() 
#9 0x00007fff93681723 in _dispatch_barrier_sync_f_invoke() 
#10 0x00007fff8ffc5ddb in clFinish() 
#11 0x00007fff8ffc25c2 in clSetEventCallback() 
#12 0x00007fff8ffb86e6 in clEnqueueReadBuffer() 
#13 0x0000000100020a31 in CLHandler::update (this=0x107683e20, [email protected], w=761, h=711) at clhandler.cpp:343 
#14 0x000000010002f8c1 in CustomBladesGLWidget::render (this=0x1072b09e0, indexMode=true, offset=135288, numPnts=4416, blobID=25, [email protected]) at customBladesGLWidget.cpp:943 

在附加的文件,線343(以上粗體)對應於該呼叫(在功能CLHandler ::更新):

//read data from buffer 
status = clEnqueueReadBuffer(cqueue,hitbuffer,CL_TRUE,0,mNumBladeCells * sizeof(float),mBladesHit,0, NULL,&event); 
handleError("clEnqueueReadBuffer","",status); 

現在,如果我要評論clEnqueueWriteBuffer的最初調用中的所有內容,它將在該函數調用中停止。我不知道爲什麼會發生這種情況。這不像我想要使用互斥或​​任何東西。任何幫助是極大的讚賞。系統規格:MacbookPro 8,2,Core i7 2.2 GHz,AMD Radeon HD 6750M,OS X 10.8.2。

感謝

回答

1

應該在第一次使用GL對象的OpenCL API調用之前調用glFinish,最後一次應該調用clFinish。較弱的選項(即調用Flush而不是Finish)可能在特定平臺上工作。

查看OpenCL 1.2 extension specification,第9.7.6.1節。

更新。特別是在Apple平臺上,最快的選項是在第一次OpenCL調用之前調用glFlushRenderApple,最後一次調用後調用clFinish

+0

這對我有意義 - 存在某種同步問題。兩種可能的解決方案適用於我,包括在clEnqueueReleaseGLObjects調用後執行glFinish/clFinish或執行waitForevents調用。這兩份文件均在該文件中提及。一般來說,最好是調用glFinish和clFinish(即使我調用了waitforevents),以確保沒有什麼不好的事情發生。謝謝。 – luxchar

+0

我剛剛看到您的最新評論關於蘋果平臺。我想我並不需要速度,但我會牢記這一點。 – luxchar

0

你爲什麼要通過事件來clEnqueueWriteBuffer/clEnqueueReadBuffer如果你指出,這是阻塞寫入(第三個參數爲true)?您也不需要撥打clWaitForEvents(1,&事件)出於這個原因。

相反,我會添加事件到clEnqueueNDRangeKernel。並在clFlush()後等待。 因爲CLFLUSH只觸發執行,但不保證其呼叫畢竟先前排隊的命令將完成(不像clFinish)。並且只能撥打clEnqueueReleaseGLObjects。但你的情況也應該沒問題,只要你的隊列沒有用CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE標誌創建。

你還可以指定哪些確切的行被評論/取消註釋?

+0

謝謝。我已經標記鏈接的cpp文件關於什麼東西得到評論(見更新(*)函數)。我會給你的事件相關的建議一個鏡頭。我使用它來進行clEnqueueWrite/Read調用,因爲我是OpenCL的新手......而且不需要clWaitForEvents,因爲它已經被阻塞了。所以你希望我在NDRangeKernel之後等待事件,然後調用release? – luxchar

+0

儘管waitforevents調用可以在clEnqeueueNDRangeKernel之後,並且不會導致鎖定,但應該在根據由@Eric鏈接的規範釋放對象之後進行調用。無論如何,根據該鏈接,確保未決的OpenGL和/或OpenCL操作不會相互干擾是一種很好的做法。這很重要,因爲我的代碼確實使用OpenGL對象。我在「不好」的後面添加了更新函數的「良好版本」給forumsquestion.cpp文件。 – luxchar