如何准确测量和比较OpenCL速度以实现简单的循环功能?

时间:2017-03-09 04:28:25

标签: c++ opencl

我最近使用Struct实现(测试)OpenCL来使用写入内核的简单函数来携带和更新C ++类对象,并且发现令我沮丧的是,使用简单的for循环在没有内核的情况下处理相同的函数是事实上更快。

这是内核函数:

 __kernel void function_x_y_(__global myclass_* input,long n)
{

int gid = get_global_id(0);
if(gid<n)
input[gid].valuez = input[gid].valuey * input[gid].valuex * 8736;

}

这是for循环:

for(int i=0;i<100;i++){
thisclass[i].function_x_y();
}

和类函数:

void function_x_y(){

valuez = valuex * valuey;

}

我在这两个过程都运行了一个时钟:

cout<<"Run function in serial\n";
startTime = clock();
for(int i=0;i<100;i++){
thisclass[i].function_x_y();
}
endTime = clock();
cout << "It took (serial) " << (endTime -startTime) / (CLOCKS_PER_SEC / 1000000) << " ms. " << endl;


cout<<"Run function in parallel using struct to write to object\n";
init_ocl();
startTime = clock();
load_kernel_from_struct("function_x_y_",p_struct,100);      //Loads function and variables into opencl

endTime = clock();
cout << "It took (parallel) " << (endTime -startTime) / (CLOCKS_PER_SEC / 1000000 ) << " ms. " << endl;

输出:

Run function in serial
It took (serial) 5 ms. 
Run function in parallel using struct to write to object
It took (parallel) 159010 ms. 

我正在使用Andreas Kloecker的cl-helper.c

我不明白这应该更快。欢迎任何帮助或建议。

是否有更准确的速度测试?这可能是因为初始化分配内存并将数据传输到内核需要时间吗?

必须有一种方法可以确保在运行函数之前我必须转移并初始化所有内容才能更快地运行吗?

谢谢, Hbyte。

1 个答案:

答案 0 :(得分:1)

您的原始测试仅使用100个元素进行测试这一事实应该是一个非常重要的线索,关于发生了什么,尤其是因为当您将迭代次数增加到5时,时间变化了多少万美元。

  • C ++编译器非常擅长优化循环。特别是迭代次数很少的循环(大约10-10'000)。它可能会将您的一些逻辑折叠成更少的指令,从而极大地加快了速度。
  • 由OpenGL引起的OpenCL不可避免的开销
    • 内核的在线编译
    • 需要将数据传输到GPU可访问的内存,
    • 同步异步主机←→设备架构
    • 的成本
  • 由于计算设备通过利用计算设备中的数百个,有时甚至数千个核心来表现,仅仅100个元素的循环将完全饱和(一个核心)典型的CPU,但通常只会饱和一小部分GPU的核心。

顺便提一下,我建议通过仅测量向GPU提交和检索工作数据来执行测试,而不是编译内核所花费的时间,因为这将更准确地模拟主机代码(显然已预先编译)和设备代码。

当然,如果您计划充分利用GPGPU设备,您需要确保工作负载实际上足够大,以便从并行性中受益,即使设置开销很大。