2012-06-11 19 views
54

Gần đây tôi đã chuyển volumeraycaster của tôi từ OpenGL sang OpenCL, làm giảm hiệu suất của raycaster khoảng 90 phần trăm. Tôi đã theo dõi hiệu suất giảm xuống các chức năng lấy mẫu hình ảnh của OpenCL, chậm hơn nhiều so với các chức năng texturesampling OpenGL tương ứng. Bằng cách loại bỏ các chức năng lấy mẫu hình ảnh và chức năng lấy mẫu kết cấu, cả hai triển khai raycaster đều có cùng tốc độ. Để dễ dàng thực hiện các chức năng trên phần cứng khác nhau, và để loại trừ một số lỗi ngớ ngẩn trong phần còn lại của mã RTs, tôi đã viết một chuẩn nhỏ so sánh tốc độ lấy mẫu OpenCL với tốc độ lấy mẫu OpenGL và thử nghiệm trên các máy khác nhau nhưng OpenCL vẫn chỉ có khoảng 10% hiệu suất của OpenGL.Hiệu suất lấy mẫu OpenCL không hoạt động với OpenGL TextureSampling

của chuẩn OpenCL HostCode (ít nhất là phần quan trọng nhất của nó):

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 cho một quad độ toàn màn hình trong đó có cùng một lượng mảnh vỡ như hạt nhân OpenCL có các mục công việc:

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

Hơn nữa tôi đã thử e sau để tăng hiệu suất:

-changing kích thước workgroup: không tăng hiệu suất

-Different Phần cứng: 280 GTX, 580 GTX, một số thẻ Fermi Tessla, tất cả trong số họ đã thực hiện rất hạn chế tương tự trong OpenCL vs OpenGL

định dạng kết cấu -Different (byte thay vì phao), mô hình truy cập khác nhau và kích thước kết cấu khác nhau: không tăng

-Sử dụng một bộ đệm thay vì một hình ảnh cho các dữ liệu và tự viết chức năng Trilinear suy cho việc lấy mẫu trong hạt nhân CL: Tăng hiệu suất OpenCL bằng khoảng 100%

-Sử dụng kết cấu // hình ảnh 2D thay vì kết cấu // hình ảnh 3D: Điều này làm tăng hiệu suất OpenCL lên 100% mặc dù hiệu suất OpenGL không hề thay đổi.

-Sử dụng "gần nhất" thay vì "tuyến tính" nội suy: Không thay đổi hiệu suất

này để lại cho tôi tự hỏi: Tôi đã làm một sai lầm rất ngớ ngẩn mà làm giảm hiệu suất OpenCL? Tại sao hiệu suất lấy mẫu OpenCL quá thấp, mặc dù nó nên sử dụng cùng phần cứng kết cấu như OpenGL? Tại sao chức năng nội suy trilinear phức tạp của tôi thực hiện nhanh hơn so với việc thực hiện phần cứng? Làm cách nào để tăng hiệu suất lấy mẫu trong OpenCL để tôi có thể có cùng tốc độ như trong OpenGL?

+0

Bạn có trình điều khiển mới nhất không? Tôi chắc chắn rằng các bit OpenGL đã không thay đổi gần đây, nhưng các công cụ OpenCL nên có! – Ani

+0

Có, chúng là phiên bản 301.32; giống như Nvidia hiện đang cung cấp tại trang tải xuống của nó. – user1449137

+2

Bạn đã thử sử dụng CL/GL interop chưa? (http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateFromGLTexture3D.html) Tôi đã sử dụng điều này trong quá khứ bởi vì tôi đã làm một chút công bằng của rendering bằng cách sử dụng OpenGL cùng với các tính toán bằng cách sử dụng OpenCL. Đây có lẽ không phải là giải pháp cuối cùng của bạn - nhưng nó có thể giúp làm sáng tỏ vấn đề thực tế. – Ani

Trả lời

2

Tôi nghi ngờ có một số vấn đề với OpenCL trong các trình điều khiển NVidia mới nhất trên một số thẻ video. Herehere là một số báo cáo về những điều đó. Thử lặp lại kiểm tra trên GPU từ một gia đình khác.