我是openCL的新手,愿意比较C代码和openCL内核之间的性能提升。
在将性能与C参考代码进行比较时,有人可以详细说明这两种方法中哪种方法对于分析openCL代码更好/更正:
使用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)
使用事件分析:
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);
此外,我没有使用专用显卡,并使用英特尔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倍。
所以我的问题是:
答案 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的产品进行比较。