尝试运行内核代码时,OpenCL(意外)冻结

时间:2013-01-04 06:09:31

标签: c++ macos opencl

好吧,我试过在Apple开发者论坛上询问,但没有人回应。我认为stackoverflow会更合适。这是......

我有一些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, tagged=@0x7fff5fbfb960, w=761, h=711) at clhandler.cpp:343
#14 0x000000010002f8c1 in CustomBladesGLWidget::render (this=0x1072b09e0, indexMode=true, offset=135288, numPnts=4416, blobID=25, bladeIdsIntersected=@0x7fff5fbfb960) at customBladesGLWidget.cpp:943

在附件中,第343行(上面的粗体)对应于此调用(在函数CLHandler :: update中):

//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。

由于

2 个答案:

答案 0 :(得分:1)

在使用GL对象的第一个OpenCL API调用之前应该调用glFinish,在最后一个之后调用clFinish。较弱的选项(即调用Flush而不是Finish)可能适用于特定平台。

参见OpenCL 1.2 extension specification,第9.7.6.1节。

更新。特别是在Apple平台上,最快的选择是在第一次OpenCL调用之前调用glFlushRenderApple,在最后一次调用之后调用clFinish

答案 1 :(得分:0)

如果您声明阻塞写入(第3个参数为true),为什么要将事件传递给 clEnqueueWriteBuffer / clEnqueueReadBuffer ?出于这个原因,您也不需要对 clWaitForEvents(1,& event)进行任何调用。

相反,我会将事件添加到 clEnqueueNDRangeKernel 。并在 clFlush()之后等待它。 因为 clFlush 仅触发执行,但不保证在调用之后所有先前排队的命令都将完成(与 clFinish 不同)。然后才调用 clEnqueueReleaseGLObjects 。但是,只要您的队列未使用 CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE 标志创建,您的情况也应该没问题。

您还可以指定哪些确切的行被注释/取消注释?