2013-01-04 31 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