OpenCL / GL Interop在nvidia / win上运行缓慢但在linux上运行速度很快?

时间:2013-08-28 15:40:33

标签: performance opengl opencl nvidia

以下问题已在nvidia的新驱动程序版本331.xx中修复,目前可用作测试版驱动程序。

感谢您的所有评论!

我有一个多平台应用程序,可以在OpenGL纹理上执行许多片段操作和gpgpu。该应用程序大量使用GL / CL互操作,每个纹理可以绑定到OpenCL映像并使用CL内核进行操作。

问题是,应用程序在Linux和Windows的AMD卡上运行得很快。在NVIDIA显卡上,它在Linux上运行速度很快,但在Windows 7上运行得非常慢。问题似乎是enqueueAcquireGLObjects和enqueueReleaseGLObjects。我创建了一个最小的样本,简单地演示了糟糕的性能:

  1. 创建2个OpenGL纹理(1600x1200像素,RGBA浮点数)
  2. 创建2个OpenCL图像,共享2个纹理
  3. 反复(50次)获得,释放,完成
  4. 结果(执行获取,释放,完成的平均时间)

    • AMD HD 6980,Linux:< 0.1 ms
    • AMD HD 6980,Win7:<0.1 ms
    • NVIDIA GTX590,Linux:&lt; 0.1 ms
    • NVIDIA GTX590,Win7: 16.0 ms

    我尝试了几种不同的驱动程序,从nvidia,从较旧的295.73到当前的beta驱动程序326.80,都表现出相同的行为。

    我现在的问题是,nvidia驱动程序是否严重损坏,或者我在这里做错了什么?代码在linux上运行得很快,所以它不能成为nvidia支持OpenCL的一般问题。代码在AMD + Win上运行得很快,所以我的代码没有针对Windows进行优化也不会有问题。例如,通过将cl图像更改为只读/写入来优化代码是没有意义的,因为性能命中几乎是30倍!

    下面你可以找到我的测试用例的相关代码,我也可以提供完整的源代码。

    上下文创建的相关代码

    { // initialize GLEW
      glewInit();
    }
    
    { // initialize CL Context, sharing GL Contet
      std::vector<cl::Platform> platforms;
      cl::Platform::get(&platforms);
      cl_context_properties cps[] = {
                 CL_GL_CONTEXT_KHR,(cl_context_properties)wglGetCurrentContext(),
                 CL_WGL_HDC_KHR,(cl_context_properties)wglGetCurrentDC(),
                 CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[0]()),
                 0};
      std::vector<cl::Device> devices;
      platforms[0].getDevices((cl_device_type)CL_DEVICE_TYPE_GPU, &devices);
      context_ = new cl::Context(devices, cps, NULL, this);
      queue_ = new cl::CommandQueue(*context_, devices[0]);
    }
    

    用于创建纹理和共享CL图像的相关代码

    width_ = 1600;
    height_ = 1200;
    
    float *data = new float[ 1600*1200*4 ];
    
    textures_.resize(2);
    glGenTextures(2, textures_.data());
    
    for (int i=0;i<2;i++) {
      glBindTexture(GL_TEXTURE_2D, textures_[i]);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
      // "data" pointer holds random/uninitialized data, do not care in this example
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, width_,height_, 0, GL_RGBA, GL_FLOAT, data);
    }
    
    delete data;
    { // create shared CL Images
    #ifdef CL_VERSION_1_2
      clImages_.push_back(cl::ImageGL(*context_, CL_MEM_READ_WRITE, GL_TEXTURE_2D, 0, textures_[0]));
      clImages_.push_back(cl::ImageGL(*context_, CL_MEM_READ_WRITE, GL_TEXTURE_2D, 0, textures_[1]));
    #else
      clImages_.push_back(cl::Image2DGL(*context_, CL_MEM_READ_WRITE, GL_TEXTURE_2D, 0, textures_[0]));
      clImages_.push_back(cl::Image2DGL(*context_, CL_MEM_READ_WRITE, GL_TEXTURE_2D, 0, textures_[1]));
    #endif
    }
    

    一个获取,发布,完成周期的相关代码

    try {
      queue_->enqueueAcquireGLObjects( &clImages_ );
      queue_->enqueueReleaseGLObjects( &clImages_ );
      queue_->finish();
    } catch (cl::Error &e) {
      std::cout << e.what() << std::endl;
    }
    

1 个答案:

答案 0 :(得分:1)

我要假设自从你使用OpenGL后,你会在OCL计算后在屏幕上显示一些东西。

基于这个假设,我首先考虑的是检查NVIDIA控制面板是否启用了VSync,如果是,则禁用它并重新测试。

据我记忆,关于vsync的默认选项对于AMD和NVIDIA是不同的;这可以解释两个GPU之间的区别。

以防万一,这里有一个post解释了vsync如何减慢渲染速度。