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?
En son sürücüleriniz var mı? OpenGL bitlerinin son zamanlarda değişmediğinden eminim, ama OpenCL'nin sahip olması gerekenler! – Ani
Evet, 301.32 sürümleri; Nvidia'nın şu anda indirme sayfasında sunduğu aynı. – user1449137
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