我一直在尝试使用PyOpenCL在GPU上对我的FFT程序进行基准测试。在使用OpenCL的"profiling"和python的"time"模块时,我看到了完全不同的结果。为了使用分析,我做了这样的事情,
queue = cl.CommandQueue(ctx,properties=cl.command_queue_properties.PROFILING_ENABLE)
<other codes>
for i in range(N):
events.append(prg3.butterfly(queue,(len(twid),),None,twid_dev,<buffers>))
events[i].wait()
for i in range(N):
elapsed = elapsed + 1e-9*(event[i].profile.end - event[i].profile.start)
print elapsed
虽然时间模块可以这样使用,
k=time.time()
for i in range(N):
event = prg3.butterfly(queue,(len(twid),),None,twid_dev,<buffers>)
print time.time()-k
由于这两种方法在N=20的情况下给出了完全不同的结果(而答案仍然相同且正确!),我有以下问题。
- 事件分析究竟做了什么?它是否添加了在event.wait()中花费的时间
- 既然在情况2中没有event.wait()的情况下答案是一样的,那么仅仅执行内核所花费的时间是否合适
请告诉我在python中测试OpenCL程序的正确方法。
您的第二种情况只是捕获将内核入队所需的时间,而不是实际运行它。一旦内核调用被放入队列中,这些入队内核调用就会返回-内核将与主机代码异步运行。为了给内核执行计时,只需添加一个等待所有排队命令完成的调用:
k=time.time()
for i in range(N):
event = prg3.butterfly(queue,(len(twid),),None,twid_dev,<buffers>)
queue.finish()
print time.time()-k
第一种情况是正确地计时内核内部执行所花费的时间,但在每次内核调用之间不必要地阻塞主机。一旦所有命令都已入队,您就可以再次使用queue.finish()
:
for i in range(N):
events.append(prg3.butterfly(queue,(len(twid),),None,twid_dev,<buffers>))
queue.finish()
for i in range(N):
elapsed = elapsed + 1e-9*(event[i].profile.end - event[i].profile.start)
print elapsed
这两种方法返回的时间应该几乎相同。