我知道CUDA中有函数clock(),您可以在其中放入内核代码并查询GPU时间。但我想知道OpenCL中是否存在这样的事情?有没有办法在OpenCL中查询GPU时间? (我正在使用NVIDIA的工具包)。
答案 0 :(得分:5)
没有OpenCL方法直接查询时钟周期。但是,OpenCL确实有一个分析机制,可以在计算设备上公开增量计数器。通过比较有序事件之间的差异,可以测量经过的时间。请参阅clGetEventProfilingInfo。
答案 1 :(得分:3)
仅为其他人寻求帮助:简要介绍使用OpenCL分析内核运行时
启用分析模式:
cmdQueue = clCreateCommandQueue(context, *devices, CL_QUEUE_PROFILING_ENABLE, &err);
分析内核:
cl_event prof_event;
clEnqueueNDRangeKernel(cmdQueue, kernel, 1 , 0, globalWorkSize, NULL, 0, NULL, &prof_event);
在以下位置读取分析数据:
cl_ulong ev_start_time=(cl_ulong)0;
cl_ulong ev_end_time=(cl_ulong)0;
clFinish(cmdQueue);
err = clWaitForEvents(1, &prof_event);
err |= clGetEventProfilingInfo(prof_event, CL_PROFILING_COMMAND_START, sizeof(cl_ulong), &ev_start_time, NULL);
err |= clGetEventProfilingInfo(prof_event, CL_PROFILING_COMMAND_END, sizeof(cl_ulong), &ev_end_time, NULL);
计算内核执行时间:
float run_time_gpu = (float)(ev_end_time - ev_start_time)/1000; // in usec
尚无法对个别工作项目/工作单进行概要分析。 您可以设置globalWorkSize = localWorkSize进行性能分析。那你就只有一个工作组。
顺便说一句:对单个工作项(某些工作项)进行概要分析并不是很有帮助。只使用一些工作项,您将无法隐藏内存延迟和开销导致无意义的测量。
答案 2 :(得分:3)
试试这个(当然只适用于NVidia OpenCL):
uint clock_time()
{
uint clock_time;
asm("mov.u32 %0, %%clock;" : "=r"(clock_time));
return clock_time;
}
答案 3 :(得分:2)
NVIDIA OpenCL SDK有一个示例Using Inline PTX with OpenCL。时钟寄存器可通过内联PTX作为特殊寄存器%时钟访问。 PTX: Parallel Thread Execution ISA手册中描述了%clock。您应该能够用%% clock替换%% laneid。
我从未使用OpenCL对此进行测试,但在CUDA中使用它。
请注意,编译器可能会重新排序或删除读取的寄存器。
答案 4 :(得分:1)
在NVIDIA上,您可以使用以下内容:
having
typedef unsigned long uint64_t; // if you haven't done so earlier
inline uint64_t n_nv_Clock()
{
uint64_t n_clock;
asm volatile("mov.u64 %0, %%clock64;" : "=l" (n_clock)); // make sure the compiler will not reorder this
return n_clock;
}
关键字告诉优化器您确实是指它并且不希望它被移动/优化掉。这是在PTX和{}}中执行此操作的标准方法。在gcc。
请注意,这会返回时钟,而不是纳秒。您需要查询设备时钟频率(使用volatile
)。另请注意,在较旧的设备上有两个频率(如果计算与此情况无关的内存频率,则为三个):设备时钟和着色器时钟。你想要的是着色器时钟。
使用64位版本的寄存器,您不必担心溢出,因为它通常需要数百年。另一方面,32位版本可能会经常溢出(您仍然可以恢复结果 - 除非它溢出两次)。