主机上的代码如下:
#include<time.h>
clock_t start,finish;
start=clock();
ret = clEnqueueNDRangeKernel(.........);
finish=clock();
double time = (double)(finish-start)/(double)(CLOCK_PER_SEC);
为什么结束 - 始终为0?是因为分辨率低,还是我的定时器代码有问题?
答案 0 :(得分:3)
排队内核非常便宜,因为函数调用可以在内核执行之前返回。
您可以将 clEnqueueNDRangeKernel 生成的事件用于 clWaitForEvents ,直到实际执行内核为止。
答案 1 :(得分:2)
clEnqueueNDRangeKernel仅对内核进行排队以运行。与大多数人在调试时习惯使用的传统C代码不同,OpenCL不是一个串行进程。要强制您的代码以串行方式执行,您可以使它们阻塞(如果可用,请参阅clEnqueueWriteBuffer和clEnqueueReadBuffer),或者在使用cl_command_queue的每个OpenCL命令之后抛出clFinish()。 clFinish()强制cl_command_queue中的所有命令完成。
这使您可以轻松使用主机定时器。
其他人提到了分析事件,这是分析OpenCL调用的预期方法。
答案 2 :(得分:1)
正如其他人已经推断的那样,如果你正在使用一个解除阻塞的clEnqueueNDRangeKernel(你的代码中没有显式),你就不会测量内核执行时间,因为enqueueing函数返回时没有任何保证内核完成执行(或者甚至开始吧)。 您可以将对profiling事件的引用传递给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);