C++ 定时间隔的计算结果始终为零

C++ 定时间隔的计算结果始终为零,c++,c,timer,opencl,C++,C,Timer,Opencl,主机上的代码如下所示: #include<time.h> clock_t start,finish; start=clock(); ret = clEnqueueNDRangeKernel(.........); finish=clock(); double time = (double)(finish-start)/(double)(CLOCK_PER_SEC); #包括 时钟没有开始,结束; 开始=时钟(); ret=ClenqueEndRangeKernel(……); 完成=

主机上的代码如下所示:

#include<time.h>
clock_t start,finish;
start=clock();
ret = clEnqueueNDRangeKernel(.........);
finish=clock();
double time = (double)(finish-start)/(double)(CLOCK_PER_SEC);
#包括
时钟没有开始,结束;
开始=时钟();
ret=ClenqueEndRangeKernel(……);
完成=时钟();
双倍时间=(双倍)(完成-开始)/(双倍)(每秒时钟);

为什么完成-开始总是0?这是因为分辨率低,还是我的计时器代码有问题?

让内核排队非常便宜,因为函数调用可以在内核执行之前返回


在内核实际执行之前,您可以将clenqueueendrangekernel生成的事件用于clWaitForEvents

将内核排队是非常便宜的,因为函数调用可以在内核执行之前返回


在内核实际执行之前,您可以使用由clEnqueueNDRangeKernel生成的事件clWaitForEvents

正如其他人已经推断的那样,如果您使用的是解锁的clenqueendrangekernel(在代码中不明确),您不是在测量内核执行时间,因为排队函数返回时不保证内核已完成执行(甚至启动它)。 您可以将对分析事件的引用传递给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);

正如其他人已经推断的那样,如果您使用的是取消阻塞的ClenqueueEndRangeKernel(在代码中不显式),那么您就没有测量内核执行时间,因为排队函数返回时不保证内核已完成执行(甚至启动它)。 您可以将对分析事件的引用传递给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);

ClenqueueEndRangeKernel仅将内核排队运行。与大多数人在调试时习惯的传统C代码不同,OpenCL不是串行进程。要强制您的代码以串行方式运行,您可以使它们阻塞(如果可用,请参阅clEnqueueWriteBuffer和clEnqueueReadBuffer),或者在每个使用cl_命令队列的OpenCL命令之后抛出clFinish()。clFinish()强制完成cl_命令_队列中的所有命令

这使您可以轻松地使用主机计时器


其他人提到了评测事件,这是评测OpenCL调用的预期方法。

ClenqueueEndRangeKernel只将内核排队等待运行。与大多数人在调试时习惯的传统C代码不同,OpenCL不是串行进程。要强制您的代码以串行方式运行,您可以使它们阻塞(如果可用,请参阅clEnqueueWriteBuffer和clEnqueueReadBuffer),或者在每个使用cl_命令队列的OpenCL命令之后抛出clFinish()。clFinish()强制完成cl_命令_队列中的所有命令

这使您可以轻松地使用主机计时器


其他人提到了评测事件,这是评测OpenCL调用的预期方法。

您的问题应该是为什么
finish
=
start
?对内核进行更多的调用,比如100到10000次,如果是低分辨率的话,请重试。可能((double)(finish start))/(double)(CLOCK_PER_SEC))?是的,似乎开始=结束。EnqueuenRangeKernel()不花费时间吗?但这需要时间。“时钟里没有时间”和“根本没有时间”是不一样的。如果你的手表每分钟只滴答滴答地响一次,那么测量一场100米赛跑比赛就没有多大用处了,因为每个人都只有0分钟——但这并不意味着他们花了零时间到达那里<代码>时钟的滴答声频率通常为1ms或10ms,因此如果所需时间不足以“滴答”一声,则为零。你的问题应该是为什么
finish
=
start
?对内核进行更多调用,如100到10000,如果是低分辨率,请重试。可能((双精度)(finish start))/(双精度)(时钟每秒);?是的,似乎start==finish.EnqueueNDRangeKernel()不需要时间?但它应该需要时间。“时钟中没有时间”与“根本没有时间”不同.如果你的手表每分钟只滴答声一次,那么测量100米赛跑比赛就没有多大用处了,因为每个人都是0分钟——但这并不意味着他们花了零时间到达那里。
时钟的滴答声频率通常是1毫秒或10毫秒,所以如果所花的时间不足以“滴答”一声,那么你就得到零。