2012-01-13 32 views
3

我知道在CUDA中有函數clock(),你可以放入內核代碼並查詢GPU的時間。但是我想知道OpenCL中是否存在這樣的事情?有什麼方法可以在OpenCL中查詢GPU時間嗎? (我正在使用NVIDIA的工具包)。opencl的clock()

回答

2

NVIDIA OpenCL SDK有一個示例Using Inline PTX with OpenCL。時鐘寄存器可通過內聯PTX作爲特殊寄存器%時鐘訪問。 %時鐘在PTX: Parallel Thread Execution ISA手冊中描述。您應該可以用%%時鐘替換%% laneid。

我從來沒有用OpenCL測試過,但在CUDA中使用它。

請注意,編譯器可能會重新排序或刪除寄存器讀取。

+0

是的,這是迄今爲止我想說的最可能的解決方案。謝謝! – Zk1001 2012-10-18 06:15:30

5

沒有OpenCL方式直接查詢時鐘週期。但是,OpenCL確實有一個分析機制,可以顯示計算設備上的增量計數器。通過比較有序事件之間的差異,可以測量經過的時間。請參閱clGetEventProfilingInfo。

+0

我認爲這會給整個內核的執行時間。但我想查詢特定數量的工作項目或工作組的時間。有沒有辦法做到這一點? – Zk1001 2012-01-14 05:37:07

+0

不是直接的,但是您可以使用特定數量的工作項目或工作組排隊內核並對其進行配置。 – vocaro 2012-01-18 03:50:15

+0

是的,我明白你的意思了。但事情有點複雜。工作項目的時間選擇取決於總共有多少工作項目。例如,如果存在資源爭用,那麼僅執行一個工作組將比將多個工作組放在一起更快。所以我猜想分析(計時)個別工作項目,甚至工作組尚未在OpenCL中實施。 – Zk1001 2012-01-20 05:32:13

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 

分析單個工作項/工作goups是不可能的呢。 您可以設置globalWorkSize = localWorkSize進行分析。那麼你只有一個工作組。

順便說一句:單個工作項目(一些工作項目)的分析不是很有幫助。只有一些工作項目,您將無法隱藏內存延遲和導致無意義測量的開銷。

+0

NVIDIA Nsight Visual Studio Edition執行上述對您的應用程序透明的任務,並在表格視圖和時間線上顯示信息。該工具在大多數OpenCL平臺上工作,因爲它在ICD層工作。 OpenCL不支持同步CPU和GPU定時器的機制,因此時間軸可能在非NVIDIA平臺上存在同步問題(偏差,漂移)。其他OpenCL供應商也有類似的工具。 – 2012-10-17 23:06:25

3

試試這個(僅限當然NVIDIA的OpenCL的工作):

uint clock_time() 
{ 
    uint clock_time; 
    asm("mov.u32 %0, %%clock;" : "=r"(clock_time)); 
    return clock_time; 
} 
+0

更新:自ptx 2.0版以來還有一個%clock64寄存器 – 2013-04-17 13:01:33

0

在NVIDIA您可以使用以下方法:

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; 
} 

volatile關鍵字告訴優化你真正的意思它並不希望它移動/優化。這是在PTX和例如在gcc

請注意,這將返回時鐘,而不是納秒。您需要查詢設備時鐘頻率(使用clGetDeviceInfo(device, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(freq), &freq, 0)))。另外請注意,在舊設備上有兩個頻率(如果您計算的存儲頻率在這種情況下無關),則有兩個頻率:設備時鐘和着色器時鐘。你想要的是着色器時鐘。

隨着64位版本的註冊,你不必擔心溢出,因爲它通常需要數百年。另一方面,32位版本可能會經常溢出(您仍然可以恢復結果 - 除非它溢出兩次)。