2012-06-11 3 views
54

Недавно я портировал мой volumeraycaster с OpenGL на OpenCL, что снизило производительность raycaster примерно на 90 процентов. Я отслеживал снижение производительности в функции обработки изображений OpenCL, которые намного медленнее, чем соответствующие функции текстурирования OpenGL. Удалив функции репликации изображений и функции выборки текстуры, обе версии raycaster имели примерно такую ​​же скорость. Чтобы легко сканировать функции на разных аппаратных средствах и исключать некоторые глупые ошибки в остальной части моего кода RT, я написал небольшой тест, который сравнивает скорость выборки OpenCL с частотой выборки OpenGL и проверял ее на разных машинах но у OpenCL все еще было около 10% производительности OpenGL.Abysmal OpenCL ImageСэмплирование по сравнению с OpenGL TextureSampling

эталоном в OpenCL HostCode (по крайней мере, наиболее важная часть):

void OGLWidget::OCLImageSampleTest() 
{ 
    try 
    { 
    int size=8; 
    float Values[4*size*size*size]; 
    cl::Kernel kernel=cl::Kernel(program,"ImageSampleTest",NULL); 
    cl::ImageFormat FormatA(CL_RGBA,CL_FLOAT); 
    cl::Image3D CLImage(CLcontext, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR ,FormatA,size,size,size,0,0,Values,NULL); 


    cl::ImageFormat FormatB(CL_RGBA,CL_UNSIGNED_INT8); 
    cl::Image2D TempImage(CLcontext, CL_MEM_WRITE_ONLY,FormatB,1024,1024,0,NULL,NULL); 


    kernel.setArg(0, CLImage); 
    kernel.setArg(1, TempImage); 



    cl::Sampler Samp; 
    Samp() = clCreateSampler(CLcontext(), CL_TRUE, CL_ADDRESS_REPEAT, CL_FILTER_LINEAR, NULL); 
    kernel.setArg(2, Samp); 

    QTime BenchmarkTimer=QTime(); 
    BenchmarkTimer.start(); 

    cl::KernelFunctor func = kernel.bind(queue, cl::NDRange(1024,1024), cl::NDRange(32,32)); 
    func().wait(); 

    int Duration = BenchmarkTimer.elapsed(); 
    printf("OCLImageSampleTest: %d ms \n", Duration); 
    } 
    catch (cl::Error& err) 
     { 
     std::cerr << "An OpenCL error occured, " << err.what() 
        << "\nError num of " << err.err() << "\n"; 
     return; 
     } 

} 

OpenCL Ядро:

void kernel ImageSampleTest(read_only image3d_t CoordTexture, write_only image2d_t FrameBuffer, sampler_t smp) 
{ 
int Screenx = get_global_id(0); 
int Screeny = get_global_id(1); 

int2 PositionOnScreen=(int2)(Screenx,Screeny) ; 

float4 Testvec=(float4)(1,1,1,1); 
for(int i=0; i< 2000; i++) 
{ 
Testvec+= read_imagef(CoordTexture,smp, (float4)(0+0.00000001*i,0,0,0)); // i makes sure that the compiler doesn't unroll the loop 
} 

uint4 ToInt=(uint4)((uint) (Testvec.x), (uint) (Testvec.y) ,(uint)(Testvec.z),1); 
write_imageui ( FrameBuffer, PositionOnScreen, ToInt); 

} 

OpenGL FragmentShader для полноэкранного четырехугольника, который имеет такое же количество фрагментов, как Ядро OpenCL имеет рабочие элементы:

#version 150 
uniform sampler3D Tex; 
out vec4 FragColor; 

void main() 
{ 
FragColor=vec4(0,0,0,0); 
for(int i=0; i<2000; i++) 
{ 
FragColor+= texture(Tex,vec3(0+0.00000001*i,0,0),0); 
} 
} 

Кроме того, я уже пробовал е следующее для повышения производительности:

-Изменение размера рабочих групп: отсутствие увеличения производительности

-Различные Оборудование: 280 GTX, 580 GTX, некоторые Ферми Tessla карты, все они имели один и тот же плачевной производительности в OpenCL против OpenGL

-Разные форматы текстуры (байты вместо поплавков), различные шаблоны доступа и различных размеры текстуры: нет увеличения

-Использования буфера вместо того, чтобы изображения для данных и сама написано функцией трилинейной интерполяции для отбора проб в ядре CL: увеличение производительности OpenCL на около 100%

-Использование 2D-изображения // текстура вместо 3D-изображения // текстура: это увеличило производительность OpenCL на 100%, хотя производительность OpenGL вообще не изменилась.

-Использование «ближайший» вместо «линейного» интерполяции: Нет изменений производительности

Это оставило мне интересно: ли я очень глупая ошибка, которая уменьшает производительность OpenCL? Почему производительность выборки OpenCL настолько низкая, хотя она должна использовать те же аппаратные средства, что и OpenGL? Почему моя сложная трилинейная функция интерполяции быстрее, чем ее аппаратная реализация? Как увеличить производительность выборки в OpenCL, чтобы я мог иметь такую ​​же скорость, как и в OpenGL?

+0

У вас есть последние версии драйверов? Я уверен, что бит OpenGL не изменился в последнее время, но у OpenCL-файлов должно быть! – Ani

+0

Да, это версия 301.32; то же самое, что Nvidia предлагает на странице загрузки. – user1449137

+2

Вы пробовали использовать CL/GL interop? (Http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateFromGLTexture3D.html) Я использовал это в прошлом, потому что я делал справедливую часть рендеринга с использованием OpenGL вместе с вычислениями с использованием OpenCL. Это, вероятно, не ваше окончательное решение, но это может помочь пролить свет на настоящую проблему. – Ani

ответ

2

Я подозреваю, что есть некоторые проблемы с OpenCL в последних драйверах NVidia на некоторых видеокартах. Here и here - некоторые сообщения о них. Попробуйте повторить тест на GPU из другой семьи.

Смежные вопросы