用于在英特尔高清显卡和C主机代码上获得OpenCL代码加速的时间测量

时间:2014-11-11 12:39:35

标签: c performance optimization profiling opencl


我是openCL的新手,愿意比较C代码和openCL内核之间的性能提升。 在将性能与C参考代码进行比较时,有人可以详细说明这两种方法中哪种方法对于分析openCL代码更好/更正:

  1. 使用QueryPerformanceCounter()/ __ rdtsc()循环(在getTime函数内部调用)

    ret |= clFinish(command_queue); //Empty the queue
    getTime(&begin);
    ret |= clEnqueueNDRangeKernel(command_queue, kernel, 2, NULL, global_ws, NULL, 0, NULL, NULL);  //Profiling Disabled.
    ret |= clFinish(command_queue);
    getTime(&end);
    g_NDRangePureExecTimeSec = elapsed_time(&begin, &end);      //Performs: (end-begin)/(CLOCK_PER_CYCLE*CLOCK_PER_CYCLE*CLOCK_PER_CYCLE)
    
  2. 使用事件分析:

    ret = clEnqueueMarker(command_queue, &evt1);
    //Empty the Queue
    ret |= clEnqueueNDRangeKernel(command_queue, kernel, 2, NULL, global_ws, NULL, 0, NULL, &evt1);
    ret |= clWaitForEvents(1, &evt1);
    ret |= clGetEventProfilingInfo(evt1, CL_PROFILING_COMMAND_START, sizeof(cl_long), &begin, NULL);
    ret |= clGetEventProfilingInfo(evt1, CL_PROFILING_COMMAND_END, sizeof(cl_long), &end, NULL);
    g_NDRangePureExecTimeSec = (cl_double)(end - begin)/(CLOCK_PER_CYCLE*CLOCK_PER_CYCLE*CLOCK_PER_CYCLE);  //nSec to Sec
    ret |= clReleaseEvent(evt1);
    
  3. 此外,我没有使用专用显卡,并使用英特尔HD 4600集成显卡进行以下openCL代码:

        __kernel void filter_rows(__global float *ip_img,\
                                  __global float *op_img, \
                                  int width, int height, \
                                  int pitch,int N, \
                                  __constant float *W)
        {
            __private int i=get_global_id(0); 
            __private int j=get_global_id(1); 
            __private int k;
            __private float a;
            __private int image_offset = N*pitch +N;
            __private int curr_pix = j*pitch + i +image_offset;
    
            // apply filter
            a  = ip_img[curr_pix-8] * W[0 ];    
            a += ip_img[curr_pix-7] * W[1 ];    
            a += ip_img[curr_pix-6] * W[2 ];    
            a += ip_img[curr_pix-5] * W[3 ];    
            a += ip_img[curr_pix-4] * W[4 ];    
            a += ip_img[curr_pix-3] * W[5 ];    
            a += ip_img[curr_pix-2] * W[6 ];    
            a += ip_img[curr_pix-1] * W[7 ];    
            a += ip_img[curr_pix-0] * W[8 ];    
            a += ip_img[curr_pix+1] * W[9 ];    
            a += ip_img[curr_pix+2] * W[10];    
            a += ip_img[curr_pix+3] * W[11];    
            a += ip_img[curr_pix+4] * W[12];    
            a += ip_img[curr_pix+5] * W[13];    
            a += ip_img[curr_pix+6] * W[14];    
            a += ip_img[curr_pix+7] * W[15];    
            a += ip_img[curr_pix+8] * W[16];
            // write output
            op_img[curr_pix] = (float)a;
        }
    

    列式处理的类似代码。我使用方法1观察增益(openCL Vs优化矢量化C-Ref)大约11倍,使用方法2大约16倍。 但是我注意到,当使用专用显卡时,人们声称增益大约为200-300倍。

    所以我的问题是:

    1. 如果我在专用显卡中运行相同的代码,我可以获得多大的增益。它是类似的订单还是显卡将胜过英特尔高清显卡?
    2. 我可以将WARP和线程概念从CUDA映射到Intel HD图形(即并行执行的线程数)吗?

2 个答案:

答案 0 :(得分:3)

  

我使用方法1观察增益约为11倍,使用方法2观察增益约为16倍。

这看起来很可疑。在这两种情况下,您都使用高分辨率计数器。我认为您的输入大小太小,会产生高运行差异。基于事件的测量稍微准确一些,因为测量中不包括某些OS +应用程序开销。然而,差异非常小。但是在内核持续时间非常小的情况下,测量方法之间的差异......计算。

  

如果我在专用显卡中运行相同的代码,我可以获得多大的增益。是类似的订单还是显卡   将超越英特尔高清显卡?

非常依赖卡的功能。虽然英特尔高清显卡是办公室,电影和一些游戏的好卡,但它无法与高端专用显卡相提并论。考虑到该卡具有非常高的功率包络,更大的芯片面积和更多的计算资源。预计专用卡将显示更高的加速。 您的卡的峰值性能约为600 GFLOPS,而分立卡的峰值性能可达到3000 GFLOPS。因此您可以大致预期您的卡将比分立卡快5倍。 但是,在说300X加速时要注意人们的比较。如果他们与旧一代CPU相比。他们可能是对的。但新一代i7 CPU可以真正缩小差距。

  

我可以将WARP和线程概念从CUDA映射到Intel HD图形(即并行执行的线程数)吗?

英特尔高清显卡没有扭曲。扭曲与CUDA硬件密切相关。基本上,warp是相同的指令,由在32个CUDA核上执行的warp调度程序调度。但是,OpenCL与CUDA非常相似,因此您可以启动大量线程,这些线程将在您的图形卡计算单元上并行执行。 但是当您在集成卡上进行编程时,最好是忘记warp并知道您的卡有多少计算单元。您的代码将在您的计算单元上并行运行多个线程。 换句话说,您的代码看起来与CUDA代码非常相似,但它将根据集成卡中的可用计算单元进行并行化。然后,每个计算单元可以以SIMD方式并行执行,例如。但是CUDA的优化技术与编程Intel HD图形的优化技术不同。

答案 1 :(得分:1)

从不同的供应商中,您可以比较性能,基本比较和期望可以使用没有并行线程运行乘以其频率来完成。

你有一台采用Intel HD 4600显卡的处理器:它应该有20个执行单元(EU),每个EU运行7个硬件线程,每个线程能够执行SIMD8,SIMD16或SIMD32指令,每个SIMD通道对应一个工作OpenCL中的item(WI)说话。

SIMD16是典型的简单内核,就像你想要优化的内核一样,所以我们讨论的是并行执行的20 * 7 * 16 = 2240个工作项。请记住,每个工作项都能够处理矢量数据类型,例如float4,所以你一定要尝试重写你的内核以利用它们。我希望这也可以帮助您与NVidia的产品进行比较。