【问题标题】:How can I accurately measure and compare OpenCL speed for simple for loop function?如何准确测量和比较 OpenCL 速度以实现简单的 for 循环功能?
【发布时间】:2025-12-02 09:50:01
【问题描述】:

我最近使用 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

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

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

必须有一种方法来确保它运行得更快,难道是我必须在运行该函数之前传输和初始化所有内容吗?

谢谢, 百字节。

【问题讨论】:

  • 这取决于 5000000 次迭代的迭代次数:它需要(串行)7133676 毫秒。使用 struct 并行运行函数以写入对象内核 Function:functions_.cl :function_x_y_ 它花了(并行)4753831 ms。我正在使用从linkhere 获取的函数。
  • İts 就像铲一粒盐并与镊子的性能进行比较。最佳小工作负载延迟是 cpu 的

标签: c++ opencl


【解决方案1】:

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

  • C++ 编译器非常擅长优化循环。尤其是迭代次数很少的循环(大约 10-10'000)。它可能会将您的一些逻辑折叠成更少的指令,从而大大加快处理速度。
  • OpenCL 中存在不可避免的开销,原因是
    • 内核在线编译
    • 需要将数据传入/传出 GPU 可访问内存,
    • 同步异步主机←→设备架构的成本
  • 由于计算设备通过利用相关计算设备中的数百个甚至数千个内核来运行,因此仅包含 100 个元素的循环将完全饱和(一个内核)典型 CPU,但通常只会饱和一小部分GPU 的内核。

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

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

【讨论】:

    最近更新 更多