2012-06-11 14 views
54

Geçtiğimiz günlerde, volumeraycaster'ı OpenGL'den OpenCL'ye taşıdım. Bu, raycaster'ın performansını yaklaşık yüzde 90 oranında düşürdü. Performans düşüşünü, OpenCL'nin görüntü örnekleme işlevlerine, ilgili OpenGL doku örnekleme işlevlerinden çok daha yavaş izledim. Görüntü örnekleme işlevlerini ve doku örnekleme işlevlerini kaldırarak, her iki raycaster uygulaması da aynı hıza sahipti. Farklı donanımlardaki işlevleri kolayca eşleştirmek ve RT'ler kodunun geri kalanında bazı aptalca hataları hariç tutabilmek için OpenCL örnekleme hızını OpenGL örnekleme hızıyla karşılaştıran ve farklı makinelerde test eden küçük bir kıyaslama yazdım. ancak OpenCL hala OpenGL'in performansının yaklaşık% 10'unu aldı.Abysmal OpenCL ImageSampling performansı - OpenGL TextureSampling

Benchmark'ın OpenCL HostCode (bunun en azından en önemli parçası):

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 Çekirdek: tam ekran dört için

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 parçalarının aynı miktarda yer alır OpenCL çekirdeğinin çalışma öğeleri vardır:

#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); 
} 
} 

-changing çalışma grubu boyutu: E performansını artırmak için aşağıdaki herhangi bir performans artışı

-Farklı Donanım: 280 GTX 580 GTX bazı Fermi Tessla kart, hepsi OpenGL vs OpenCL'de aynı dipsiz bir performans vardı

-Farklı doku formatları (yerine yüzen bayt), farklı erişim desen ve farklı doku boyutları: örnekleme için veriler için bir görüntünün yerine tampon -Kullanım bir artış

ve kendini yazılı üç çizgili enterpolasyon fonksiyonu CL Çekirdeğinde: OpenCL performansını artırdı yaklaşık% 100

3D görüntü/doku yerine 2D görüntü/doku kullanılması: OpenGL performansı hiç değişmediği halde bu% 100 oranında OpenCL performansını artırdı.

"en yakın" yerine "doğrusal" interpolasyon -Kullanım: Bu merak beni bıraktı

yok performans değişimi: Ben OpenCL performansı azalır çok aptalca bir hata yaptı mı? OpenCL örnekleme performansı neden bu kadar düşük olsa da, OpenGL ile aynı doku donanımını kullanmalıdır? Karmaşık trilinear enterpolasyon işlevim neden donanım uygulamasından daha hızlı çalışıyor? OpenCL'deki örnekleme performansını nasıl artırabilirim, böylece OpenGL ile aynı hıza sahip olabilirim?

+0

En son sürücüleriniz var mı? OpenGL bitlerinin son zamanlarda değişmediğinden eminim, ama OpenCL'nin sahip olması gerekenler! – Ani

+0

Evet, 301.32 sürümleri; Nvidia'nın şu anda indirme sayfasında sunduğu aynı. – user1449137

+2

CL/GL interop kullanmayı denediniz mi? (Http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateFromGLTexture3D.html) Bunu geçmişte kullandım çünkü OpenCL kullanarak hesaplamalar yaparak OpenGL kullanarak biraz işlem yaptım. Bu muhtemelen sizin nihai çözümünüz değil - ama asıl sorun üzerinde ışık tutabilir. – Ani

cevap

2

Bazı video kartlarında en son NVidia sürücülerinde OpenCL ile ilgili bir sorun olduğundan şüpheleniyorum. Here ve here bunlarla ilgili bazı raporlardır. Başka bir aileden GPU üzerinde test yapmayı deneyin.