C++ OpenCL(意外地)在尝试运行内核代码时冻结
嗯,我试着在苹果开发者论坛上提问,但没有人回应。我认为stackoverflow更合适。这是 我有一些OpenCL内核,它运行于存储在帧缓冲区对象中的像素,并计算非黑色和非白色像素。它过去在我的机器上运行得很好,但我相信对MacOSX和/或devtools的更新可能导致了一个问题,导致它暂停 与内核代码关联的内核对象附加到QT窗口,当窗口需要渲染更新时,内核代码运行n次。此窗口在最初创建后会更新两次,这意味着openCL代码序列最初不会导致问题。当我将窗口置于前台时,它需要另一次更新,并尝试再次运行内核代码n次。但在这些时期的中间,它停滞了。i、 e.如果需要运行51次,则在迭代26处暂停。似乎调用clEnqueueReadBuffer会导致暂停 我将省略关于为什么使用openCL代码的细节,除非这是绝对必要的,因为这可能会让人困惑。我认为专注于OpenCL代码本身会很好。以下为参考: 以下是gdb回溯:C++ OpenCL(意外地)在尝试运行内核代码时冻结,c++,macos,opencl,C++,Macos,Opencl,嗯,我试着在苹果开发者论坛上提问,但没有人回应。我认为stackoverflow更合适。这是 我有一些OpenCL内核,它运行于存储在帧缓冲区对象中的像素,并计算非黑色和非白色像素。它过去在我的机器上运行得很好,但我相信对MacOSX和/或devtools的更新可能导致了一个问题,导致它暂停 与内核代码关联的内核对象附加到QT窗口,当窗口需要渲染更新时,内核代码运行n次。此窗口在最初创建后会更新两次,这意味着openCL代码序列最初不会导致问题。当我将窗口置于前台时,它需要另一次更新,并尝试再次
#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中):
现在,如果我在对clEnqueueWriteBuffer的初始调用下面注释所有内容,它将在该函数调用处暂停。我不知道为什么会这样。我并不是在尝试使用互斥或其他什么。非常感谢您的帮助
系统规格:MacbookPro 8,2,Core i7 2.2 GHz,AMD Radeon HD 6750M,OS X 10.8.2
谢谢如果您声明事件正在阻止写入(第三个参数为true),为什么要将事件传递给clEnqueueWriteBuffer/clEnqueueReadBuffer?因此,您也不需要调用clWaitForEvents(1,&event) 相反,我会将事件添加到clEnqueueNDRangeKernel。然后在clFlush()之后等待它。 因为clFlush只触发执行,但不保证调用后所有先前排队的命令都将完成(与clFinish不同)。然后才调用ClenqueureReleaseGlobalObjects。但您的情况也应该是正常的,只要您的队列不是使用CL\u queue\u OUT\u OF\u ORDER\u EXEC\u MODE\u ENABLE标志创建的
还可以指定哪些行被注释/未注释?如果您声明它正在阻止写入(第三个参数为true),为什么要将事件传递给clEnqueueWriteBuffer/clEnqueueReadBuffer?因此,您也不需要调用clWaitForEvents(1,&event) 相反,我会将事件添加到clEnqueueNDRangeKernel。然后在clFlush()之后等待它。 因为clFlush只触发执行,但不保证调用后所有先前排队的命令都将完成(与clFinish不同)。然后才调用ClenqueureReleaseGlobalObjects。但您的情况也应该是正常的,只要您的队列不是使用CL\u queue\u OUT\u OF\u ORDER\u EXEC\u MODE\u ENABLE标志创建的
还可以指定哪些行被注释/未注释?在使用GL对象的第一次OpenCL API调用之前,应该调用
glFinish
,在最后一次调用之后,应该调用clFinish
。较弱的选项(即调用Flush而不是Finish)可能适用于特定平台
见第9.7.6.1节
更新。特别是在Apple平台上,最快的选择是在第一次OpenCL调用之前调用
glFlushRenderApple
,在最后一次调用之后调用clFinish
。在使用GL对象的第一次OpenCL API调用之前,应该调用glFinish
,最后一个之后是clFinish
。较弱的选项(即调用Flush而不是Finish)可能适用于特定平台
见第9.7.6.1节
更新。特别是在苹果平台上,最快的选择是在第一次调用OpenCL之前调用
glFlushRenderApple
,在最后一次调用之后调用clFinish
。谢谢。我已经在链接的cpp文件中标记了注释内容的位置(请参阅update(*)函数)。我会给你一些与活动相关的建议。我使用它进行clEnqueueWrite/Read调用,因为我是OpenCL的新手……是的,clWaitForEvents是不需要的,因为它已经被阻塞了。所以你想让我在NDRangeKernel之后等待事件,然后调用release?虽然waitforevents调用可以在clenqueuendrangekernel之后进行,并且不会导致锁定,但它应该在调用释放对象之后,根据@Eric链接的规范。无论如何,根据这个链接,确保挂起的OpenGL和/或OpenCL操作不会相互干扰是一个很好的实践。这很重要,因为我的代码确实使用OpenGL对象。我在forumsquestion.cpp文件中添加了更新函数的“好版本”,就在“坏版本”之后。谢谢。我已经在链接的cpp文件中标记了注释内容的位置(请参阅update(*)函数)。我会给你一些与活动相关的建议。我使用它进行clEnqueueWrite/Read调用,因为我是OpenCL的新手……是的,clWaitForEvents是不需要的,因为它已经被阻塞了。所以你想让我在NDRangeKernel之后等待事件,然后调用release?虽然waitforevents调用可以在clenqueuendrangekernel之后进行,并且不会导致锁定,但它应该在调用释放对象之后,根据@Eric链接的规范。无论如何,根据这个链接,这是一个很好的公关
//read data from buffer
status = clEnqueueReadBuffer(cqueue,hitbuffer,CL_TRUE,0,mNumBladeCells * sizeof(float),mBladesHit,0, NULL,&event);
handleError("clEnqueueReadBuffer","",status);