具有多个GPU的OpenCL / OpenGL Interop

时间:2013-07-30 20:33:20

标签: opengl interop opencl multi-gpu

我在使用OpenCL / OpenGL互操作的多个GPU时遇到了麻烦。我正在尝试编写一个呈现密集计算结果的应用程序。最后它会运行一个优化问题,然后根据结果向屏幕渲染一些东西。作为测试用例,我将从本课程的粒子模拟示例代码开始:http://web.engr.oregonstate.edu/~mjb/sig13/

示例代码创建和OpenGL上下文,然后使用cl_khr_gl_sharing扩展创建一个共享状态的OpenCL上下文。当我使用单个GPU时,一切正常。创建上下文如下所示:

3. create an opencl context based on the opengl context:
  cl_context_properties props[ ] =
  {
      CL_GL_CONTEXT_KHR, (cl_context_properties) glXGetCurrentContext( ),
      CL_GLX_DISPLAY_KHR, (cl_context_properties) glXGetCurrentDisplay( ),
      CL_CONTEXT_PLATFORM, (cl_context_properties) Platform,
      0
  };

  cl_context Context = clCreateContext( props, 1, Device, NULL, NULL, &status );
  if( status != CL_SUCCESS) 
  {
      PrintCLError( status, "clCreateContext: " );
      exit(1);
  }

稍后,该示例使用clCreateFromGLBuffer创建共享CL / GL缓冲区。

现在,我想从两个GPU设备创建一个上下文:

cl_context Context = clCreateContext( props, 2, Device, NULL, NULL, &status );

我已成功打开设备,并且可以查询它们是否都支持cl_khr_gl_sharing,并且两者都可以单独工作。但是,在尝试创建上述上下文时,我得到了

CL_INVALID_OPERATION 

这是cl_khr_gl_sharing扩展程序添加的错误代码。在扩展说明(上面链接)中,它说

  
      
  • 如果是上下文或共享组对象,则为CL_INVALID_OPERATION    为CGL,EGL,GLX或WGL之一和任何一个指定    以下条件成立:

         
        
    • OpenGL实现不支持窗口系统   上下文或共享组对象的绑定API   指定。
    •   
    • 多个属性CL_CGL_SHAREGROUP_KHR,   CL_EGL_DISPLAY_KHR,CL_GLX_DISPLAY_KHR和CL_WGL_HDC_KHR是   设置为非默认值。
    •   
    • 两个属性CL_CGL_SHAREGROUP_KHR和   CL_GL_CONTEXT_KHR设置为非默认值。
    •   
    • 参数中指定的任何设备都不能   支持共享OpenGL数据存储的OpenCL对象   对象,如第9.12节所述。“
    •   
  •   

这种描述似乎并不适合我的任何案例。是否不可能使用多个GPU进行OpenCL / OpenGL互操作?还是我有异构硬件?我从枚举设备中打印出一些参数。我刚拿了两个随机的GPU,我可以动手了。

PlatformID: 18483216
Num Devices: 2

-------- Device 00 ---------
CL_DEVICE_NAME: GeForce GTX 285
CL_DEVICE_VENDOR: NVIDIA Corporation
CL_DEVICE_VERSION: OpenCL 1.0 CUDA
CL_DRIVER_VERSION: 304.88
CL_DEVICE_MAX_COMPUTE_UNITS: 30
CL_DEVICE_MAX_CLOCK_FREQUENCY: 1476
CL_DEVICE_TYPE: CL_DEVICE_TYPE_GPU

-------- Device 01 ---------
CL_DEVICE_NAME: Quadro FX 580
CL_DEVICE_VENDOR: NVIDIA Corporation
CL_DEVICE_VERSION: OpenCL 1.0 CUDA
CL_DRIVER_VERSION: 304.88
CL_DEVICE_MAX_COMPUTE_UNITS: 4
CL_DEVICE_MAX_CLOCK_FREQUENCY: 1125
CL_DEVICE_TYPE: CL_DEVICE_TYPE_GPU

cl_khr_gl_sharing is supported on dev 0.
cl_khr_gl_sharing is supported on dev 1.

请注意,如果我创建没有interop部分的上下文(这样props数组如下所示)那么它就会成功创建上下文,但显然不能与应用程序的OpenGL端共享缓冲区。

cl_context_properties props[ ] =
{
   CL_CONTEXT_PLATFORM, (cl_context_properties) Platform,
   0
};

2 个答案:

答案 0 :(得分:2)

几个相关问题和示例


    bool stageProducer::preExecution() 
    {
        if(!glContext::getInstance().makeCurrent(_rc))
        {
            window::getInstance().messageBoxWithLastError("wglMakeCurrent");
            return false;
        }
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fboID);
        return true;
    }

特定于OpenCL,但与此问题相关

“如果您对queueA(deviceA)上的缓冲区进行排队,那么OpenCL将使用该设备进行写入。但是,如果您在同一上下文中使用queueB(deviceB)上的缓冲区,则OpenCL将识别出deviceA具有最新数据并在使用之前将其移至deviceB。简而言之,只要您使用事件确保没有两个设备同时尝试访问同一个内存对象,OpenCL将会确保每次使用内存对象都有最新数据,无论上次使用哪个设备。“

我假设你把OpenGL从gpus之间共享内存的方程式中按预期工作?

答案 1 :(得分:1)

当你打电话给这两行时:

CL_GL_CONTEXT_KHR, (cl_context_properties) glXGetCurrentContext( ), CL_GLX_DISPLAY_KHR, (cl_context_properties) glXGetCurrentDisplay( ),

调用需要来自具有新OpenGL上下文的新线程内部。通常,每个线程一次只能为一个设备关联一个OpenCL上下文和一个OpenGL上下文。