Image OpenCL图像采样性能差于OpenGL纹理采样

Image OpenCL图像采样性能差于OpenGL纹理采样,image,opengl,opencl,textures,sampling,Image,Opengl,Opencl,Textures,Sampling,我最近将volumeraycaster从OpenGL移植到OpenCL,这使raycaster的性能降低了约90%。我跟踪了OpenCL的imagesampling函数的性能下降,这些函数比相应的OpenGL texturesampling函数慢得多。通过删除imagesampling函数和纹理采样函数,两种raycaster实现的速度大致相同。 为了方便地在不同的硬件上测试函数,并排除我剩余RTs代码中的一些愚蠢错误,我编写了一个小型基准测试,将OpenCL采样速度与OpenGL采样速度进行比

我最近将volumeraycaster从OpenGL移植到OpenCL,这使raycaster的性能降低了约90%。我跟踪了OpenCL的imagesampling函数的性能下降,这些函数比相应的OpenGL texturesampling函数慢得多。通过删除imagesampling函数和纹理采样函数,两种raycaster实现的速度大致相同。 为了方便地在不同的硬件上测试函数,并排除我剩余RTs代码中的一些愚蠢错误,我编写了一个小型基准测试,将OpenCL采样速度与OpenGL采样速度进行比较,并在不同的机器上进行测试,但OpenCL的性能仍然只有OpenGL的10%左右

基准测试的OpenCL主机代码(至少是其中最重要的部分):

void OGLWidget::OCLImageSampleTest()
{
尝试
{
int size=8;
浮点值[4*大小*大小*大小];
cl::Kernel Kernel=cl::Kernel(程序,“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,size,0,0,value,NULL);
cl::ImageFormat FormatB(cl_RGBA,cl_UNSIGNED_INT8);
cl::Image2D TempImage(CLcontext,cl_MEM_WRITE_ONLY,FormatB,10241024,0,NULL,NULL);
setArg(0,CLImage);
setArg(1,TempImage);
cl::采样器Samp;
Samp()=clCreateSampler(CLcontext(),CL_TRUE,CL_ADDRESS_REPEAT,CL_FILTER_LINEAR,NULL);
setArg(2,Samp);
QTime BenchmarkTimer=QTime();
BenchmarkTimer.start();
cl::KernelFunctor func=kernel.bind(队列,cl::NDRange(10241024),cl::NDRange(32,32));
func().wait();
int Duration=BenchmarkTimer.appeased();
printf(“OCLImageSampleTest:%d ms\n”,持续时间);
}
捕获(cl::错误和错误)
{

我怀疑某些视频卡上最新的NVidia驱动程序中的OpenCL存在一些问题。
还有一些关于这些的报告。尝试在另一个系列的GPU上重复测试。

您尝试过使用CL/GL interop吗?()我在过去使用过它,因为我在使用OpenGL和使用OpenCL的计算机进行渲染时做了大量工作。这可能不是您的最终解决方案,但它可能有助于阐明实际问题。我感觉OpenCL没有在内存中随意滑动纹理:c.f.,这将导致非常糟糕的结果缓存访问性能,特别是3D纹理。我想在这里补充的另一点是,Nvidia正在积极尝试压缩OpenCL的使用,以促进CUDA(以及供应商锁定)。我不会依赖于他们的OpenCL实现优于运行在同一个平台上的同一程序(类似)英特尔或AMD GPU。你为什么禁止编译器展开你的循环?forloop会有很多次迭代,你的大部分时间会花在执行比较和跳转指令上。IIRC图形硬件没有分支预测,这会使它变慢?@user1449137这个问题最初发布已经2.5年了。我很高兴我很好奇:你或其他用户是否仍然认为OpenGL在更新硬件上的OpenCL和OpenGL的最新版本优于OpenCL(在本测试中)?
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;
      }

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

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