主机上的代码是这样的:
#include<time.h>
clock_t start,finish;
start=clock();
ret = clEnqueueNDRangeKernel(.........);
finish=clock();
double time = (double)(finish-start)/(double)(CLOCK_PER_SEC);
为什么完成-开始总是0?是因为分辨率低,还是我的计时器代码有问题?
使内核入队非常便宜,因为函数调用可以在内核执行之前返回。
您可以将clEnqueueNDRangeKernel生成的事件用于clWaitForEvents,直到内核实际执行。
clEnqueueNDRangeKernel 仅将内核排队等待运行。与大多数人在调试时习惯使用的传统 C 代码不同,OpenCL 不是串行过程。要强制您的代码以串行方式运行,您可以使它们阻塞(如果可用,请参阅 clEnqueueWriteBuffer 和 clEnqueueReadBuffer)或在每个使用 cl_command_queue 的 OpenCL 命令之后抛出 clFinish()。clFinish() 强制 cl_command_queue 中的所有命令完成。
这使您可以轻松地使用主机计时器。
其他人提到了分析事件,这是分析 OpenCL 调用的预期方法。
正如其他人已经推断的那样,如果您使用的是解除阻塞的 clEnqueueNDRangeKernel (在您的代码中没有明确说明),则您不会测量内核执行时间,因为入队函数返回时没有任何保证内核已完成执行(甚至启动它) )。您可以将分析事件的引用传递给 enqueue 方法,然后查询它的开始和结束时间。使用 cpp 包装器:
cl::Event timingEvent;
queue_0.enqueueNDRangeKernel(mx_kernel,cl::NullRange,global,local,NULL,&timingEvent);
queue_0.finish();//wait for kernel to be executed
timingEvent.getProfilingInfo(CL_PROFILING_COMMAND_START,&start_time);
timingEvent.getProfilingInfo(CL_PROFILING_COMMAND_END,&end_time);
unsigned long elapsed = (unsigned long)(end_time - start_time);
为此,您必须在对象构造时在队列中启用分析:
cl::CommandQueue queue_0 = cl::CommandQueue(context, devices[0], CL_QUEUE_PROFILING_ENABLE);