OpenCL / OpenGL互操作浪费CPU

时间:2019-06-23 18:30:40

标签: opengl opencl

我每次使用一个OpenCL内核调用以每秒60次的速度在OpenCL中生成帧,并将它们写入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);

我很难说出是什么原因造成的,因为nvopencl64.dll在另一个线程中运行了CPU占用率很高(当我在装有nVidia GPU的Windows 10机器上运行它时,但是我也遇到了类似的问题装有Intel iGPU的笔记本电脑(也适用于Windows 10)。

分析告诉我,大部分CPU时间由nvopencl64.dll调用的WaitForSingleObjectEx(占CPU时间的42%),nvoglv64.dll的WaitForMultipleObjects(占21%)占用的时间{1}}和发起上述DrvPresentBuffers调用的RtlUserThreadStart(16%)调用。那是给我的nVidia GPU机器使用的,但是在只有Intel HD 5000 iGPU的机器上情况看起来很相似。因此,显然发生了一些效率很低的事情,可能是因为太多的线程启动得太频繁了。

1 个答案:

答案 0 :(得分:2)

似乎CL_DEVICE_PREFERRED_INTEROP_USER_SYNC为false时,不需要进行与clEnqueueAcquireGLObjectsclEnqueueReleaseGLObjects的手动同步,除了在初始化OpenGL纹理后进行一次clEnqueueAcquireGLObjects调用之外。在那种情况下,glFinish似乎是唯一需要的同步形式。