Измерение и минимизация накладных расходов OpenCL

У меня есть программа pyopencl, которая делает долгий расчет (~ 3-5 часов за прогон). У меня несколько ядер запускались одно за другим в цикле. Итак, у меня есть что-то вроде этого:

prepare_kernels_and_data()

for i in range(big_number): # in my case big_number is 400000
  load_data_to_device(i)    # ~0.0002s
  run_kernel1(i)            # ~0.0086s
  run_kernel2(i)            # ~0.00028s
  store_data_from_device(i) # ~0.0002s

Я измерил время и получил следующее:

  1. Системное время составляет 4:30 часа (измерено командой linux time)
  2. Чистое время, основанное на событиях opencl, составляет 3:30 часа (загрузка + расчет + сохранение).

Я хотел бы знать:

  1. Насколько велики минимальные накладные расходы для программы OpenCL? В моем случае это 35%
  2. Должен ли я доверять времени на основе событий?
  3. Увеличивает ли включение профилирования время выполнения всей программы?

Я знаю, что накладные расходы зависят от программы, и я знаю, что python не так быстр, как чистый C или CPP. Но я считаю, что когда я переведу все свои тяжелые вычисления на ядра OpenCL, я могу потерять не более 5-7%. Пожалуйста, поправьте меня, если я ошибаюсь.

P.S. AMD OpenCL, графический процессор AMD


person petRUShka    schedule 01.07.2013    source источник


Ответы (1)


Как вы измеряете время OCL? Используя только что-то вроде:

my_event.profile.end - my_event.profile.start

Если это так, вы также можете взять другую метрику, подобную этой:

my_event.profile.start - my_event.profile.queued

Эта метрика измеряет время, проведенное в пользовательском приложении, а также во время выполнения перед выполнением, следовательно, накладные расходы. Этот показатель предлагается в руководстве по программированию AMD в разделе 4.4.1.
Они также дать предупреждение о профилировании, объясняя, что команды могут быть отправлены пакетно и, следовательно,

Команды, отправленные в виде пакета, сообщают одинаковое время начала и время окончания.

Насколько я помню, NVIDIA выполняет потоковую передачу команд. Но в любом случае вы можете использовать это, чтобы уменьшить накладные расходы. Например, вместо того, чтобы иметь:

Cl_prog.kernel1(…).wait()
Cl_prog.kernel2(…).wait()

Вы можете сделать что-то вроде:

Event1 =   Cl_prog.kernel1(…)
Event2 = Cl_prog.kernel2(…)
Event1.wait()
Event2.wait()

И так далее.
Но я отвлекся; теперь, чтобы ответить конкретно на ваши вопросы, вот некоторые данные, взятые из того же раздела, о котором я упоминал выше (это от AMD, но я думаю, что это должно быть примерно то же самое для NVIDIA):

  1. «Для процессорных устройств время запуска ядра небольшое (десятки мкс), но для дискретных устройств с графическим процессором оно может составлять несколько сотен мкс»

  2. См. цитату выше

  3. «Включение профилирования в очереди команд добавляет примерно от 10 мкс до 40 мкс накладных расходов на все вызовы clEnqueue».
person CaptainObvious    schedule 02.07.2013