Performances AbSmal OpenCL ImageSampling vs OpenGL TextureSampling

J’ai récemment porté mon volumeraycaster d’OpenGL à OpenCL, ce qui a réduit les performances du raycaster d’environ 90%. J’ai suivi la diminution des performances vers les fonctions d’échantillonnage d’images d’OpenCL, qui sont beaucoup plus lentes que les fonctions respectives d’échantillonnage de textures OpenGL. En supprimant les fonctions d’échantillonnage d’image et les fonctions d’échantillonnage de texture, les deux implémentations de Raycaster avaient à peu près la même vitesse. Afin de pouvoir facilement étalonner les fonctions sur différents matériels et d’exclure certaines erreurs idiotes dans le rest de mon code RT, j’ai écrit un petit benchmark qui compare la vitesse d’échantillonnage OpenCL à la vitesse d’échantillonnage OpenGL et l’a testé sur différentes machines. OpenCL n’avait toujours que 10% des performances d’OpenGL.

OpenCL HostCode du benchmark (au moins la partie la plus importante):

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 Kernel:

 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 pour un quad plein écran qui a la même quantité de fragments que le kernel OpenCL a des éléments de travail:

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

De plus, j’ai déjà essayé les choses suivantes pour augmenter les performances:

-changer la taille du groupe de travail: aucune augmentation de performance

-Différents matériels: 280 GTX, 580 GTX, des cartes Fermi Tessla, toutes ayant les mêmes performances désastreuses dans OpenCL vs OpenGL

Différents formats de texture (octets au lieu de flottants), différents modèles d’access et différentes tailles de texture: aucune augmentation

-Utilisation d’un tampon au lieu d’une image pour les données et d’une fonction d’interpolation sortinglinéaire auto-écrite pour l’échantillonnage dans le kernel CL: augmentation des performances d’OpenCL d’environ 100%

-Utilisation d’une image 2D // texture au lieu d’une image 3D // texture: ceci a augmenté les performances d’OpenCL de 100% bien que les performances d’OpenGL n’aient pas du tout changé.

-Utilisation d’interpolation “la plus proche” au lieu de “linéaire”: pas de changement de performance

Cela me laissait perplexe: Est-ce que j’ai fait une erreur très stupide qui diminue les performances d’OpenCL? Pourquoi la performance d’échantillonnage OpenCL est-elle si faible, bien qu’elle doive utiliser le même matériel de texture qu’OpenGL? Pourquoi mon implémentation d’interpolation sortinglinéaire complexe est-elle plus rapide que son implémentation matérielle? Comment puis-je augmenter les performances d’échantillonnage dans OpenCL afin d’avoir la même vitesse qu’avec OpenGL?

Je soupçonne qu’il existe un problème avec OpenCL dans les derniers pilotes NVidia sur certaines cartes vidéo. Ici et voici quelques rapports à leur sujet. Essayez de répéter le test sur un GPU d’une autre famille.