2014-10-28 2 views
1

Я пытался сравнить мою программу FFT на графическом процессоре с использованием PyOpenCL. Я вижу совершенно разные результаты, используя «профилирование» модуля OpenCL и «time» python. Для того, чтобы использовать профилирование, я что-то вроде этого,Настольная маркировка программ PyOpenCL

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, (в то время как ответ остается то же и правильно!), у меня есть следующие вопросы.

  1. Что именно делает профилирование событий и добавляет ли время, проведенное в event.wait()?
  2. Так как ответ такой же без события.wait() в случае 2, это правильное количество времени, затраченное на простое выполнение ядра?

Просьба рассказать мне о правильном способе тестирования программ OpenCL в python.

ответ

3

Ваш второй случай - это только захват времени, затрачиваемого на размещение ядра, а не его запуск. Эти вызовы ядра enqueue возвращаются, как только вызов ядра помещается в очередь - ядро ​​будет выполняться асинхронно с вашим хост-кодом. Для того, чтобы время выполнения ядра, а также, просто добавьте вызов подождать, пока все помещенные в очереди команды не закончили:

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 

Оба эти подхода должен возвращать почти идентичные времена.

+1

спасибо, это имеет смысл. Но без event.wait() или queue.finish(), им удается получить правильные ответы. Итак, ядра должны были быть выполнены в это время, и вывод готов к копированию на хост. Любые комментарии? –

+2

@KarthikHegde Да - когда вы копируете данные обратно на хост (например, с помощью операции чтения с блокировкой), что заставит все ранее отправленные команды завершить работу. – jprice

Смежные вопросы