【发布时间】:2019-11-05 16:21:19
【问题描述】:
我每次使用一个 OpenCL 内核调用在 OpenCL 中生成帧 60 次,并将它们写入 OpenGL 纹理,以便我可以在屏幕上显示它们。没有性能问题,帧率符合预期,但问题是它非常浪费,它至少保持一个 CPU 核心完全忙碌,即使它几乎没有什么可做的,比如以非常低的分辨率绘制空白帧.为了进行比较,当我不使用 OpenGL 互操作而是从 CL 内核写入通用缓冲区,然后将该缓冲区复制回主机然后以另一种方式显示它时,帧速率会下降一点(由于后面和互操作不必要的第四个开销),但是当无事可做时,CPU使用率要低得多。
这意味着我执行互操作的方式有问题,我认为必须创建某种繁忙的等待。
这是相关代码,这是我使用互操作时的代码,而不是我不使用它时的代码。在我循环的一个地方,我清除了 GL 纹理并让 OpenCL 获取它:
uint32_t z = 0;
glClearTexImage(fb.gltex, 0, GL_RGBA, GL_UNSIGNED_BYTE, &z);
glFlush();
glFinish();
clEnqueueAcquireGLObjects(fb.clctx.command_queue, 1, &fb.cl_srgb, 0, 0, NULL);
然后我将我的 OpenCL 内核的执行排入队列,该内核将写入纹理作为 cl_mem 对象 fb.cl_srgb,然后我将控制权交还给 OpenGL,以便在显示器上显示纹理:
clEnqueueReleaseGLObjects(fb.clctx.command_queue, 1, &fb.cl_srgb, 0, 0, NULL);
clFinish(fb.clctx.command_queue); // this blocks until the kernel is done writing to the texture and releasing the texture
// setting GL texture coordinates, probably not relevant to this question
float hoff = 2. * (fb.h - fb.maxdim.y) / (double) fb.maxdim.y;
glLoadIdentity(); // Reset the projection matrix
glViewport(0, 0, fb.maxdim.x, fb.maxdim.y);
glBegin(GL_QUADS);
glTexCoord2f(0.f, 0.f); glVertex2f(-1., 1.+hoff);
glTexCoord2f(1.f, 0.f); glVertex2f(1., 1.+hoff);
glTexCoord2f(1.f, 1.f); glVertex2f(1., -1.+hoff);
glTexCoord2f(0.f, 1.f); glVertex2f(-1., -1.+hoff);
glEnd();
SDL_GL_SwapWindow(fb.window);
我很难说出是什么原因造成的,因为高 CPU 使用率是在另一个由 nvopencl64.dll 运行的线程中(当我在带有 nVidia GPU 的 Windows 10 机器上运行它时,但我遇到了类似的问题)配备 Intel iGPU 的笔记本电脑,同样在 Windows 10 上)。
分析告诉我,大部分 CPU 时间由从 nvopencl64.dll 调用的 WaitForSingleObjectEx(独占 CPU 时间的 42%)、从 nvoglv64.dll 的 DrvPresentBuffers 调用的 WaitForMultipleObjects(21%)和RtlUserThreadStart (16%) 来自上述WaitForMultipleObjects 呼叫的呼叫。这适用于我的 nVidia GPU 机器,但在只有 Intel HD 5000 iGPU 的机器上情况看起来非常相似。因此,显然有一些非常低效的事情正在发生,可能是因为太多线程启动得太频繁了。
【问题讨论】:
-
似乎 GPU 不希望你做你做的事。
clGetDeviceInfo(CL_DEVICE_PREFERRED_INTEROP_USER_SYNC)是否返回CL_FALSE? -
好的,所以您的 GPU 不需要手动同步。尝试删除
clEnqueueAcquireGLObjects和clEnqueueReleaseGLObjects看看会发生什么。顺便说一句,您是否使用clCreateFromGLTexture将 GL 纹理传递给 CL? -
现在这很好奇......明天的某个地方我会尝试在我的机器上执行你的代码,以亲自查看。
-
谢谢!你开始构建代码了吗?也许我写的说明不是很清楚。无论如何,我只是尝试使用单个
clEnqueueAcquireGLObjects()调用来跟踪clCreateFromGLTexture()调用,而没有进一步的互操作调用,这解决了问题,在仍然运行时只给了我大约 2% 的 CPU 使用率(而不是 1 或 2 个完整内核) 60 FPS,这似乎是最佳的。我想这就是CL_DEVICE_PREFERRED_INTEROP_USER_SYNC给我们 0 时必须做的事情。既然您暗示了该解决方案并且有赏金,您应该写下答案。感谢您的帮助! -
不幸的是我昨天无法编译它。但无论如何,你似乎已经自己解决了这个问题,所以赏金不应该是我的。请回答您自己的问题(这是允许和鼓励的),以帮助任何可能正在寻找这个问题的答案的人=)