2015-08-10 3 views
0

Я выполняю monte carlo sweeps на популяции реплик моей системы с использованием ядер OpenCL. После начальной фазы отладки я увеличил некоторые аргументы до более реалистичных значений и заметил, что программа внезапно сжигает большие объемы памяти хоста. Я выполняю 1000 разверток на около 4000 реплик, каждая развертка состоит из 2 ячеек. Это приводит к примерно 8 миллионам вызовов ядра.Ядро ядра OpenCL с большим количеством памяти хоста

Источником использования памяти было легко найти (см. Снимок экрана).

  • В то время как выполнение ядра выполняется в очереди, использование памяти увеличивается.
  • В то время как ядра используют использование памяти, он остается постоянным.
  • Как только ядра заканчиваются, использование переходит в исходное состояние.
  • Я не выделял никакой памяти, как можно видеть в моментальных снимках памяти.

enter image description here

Это означает, что драйвер OpenCL использует память. Я понимаю, что он должен хранить копию всех аргументов при вызове ядра, а также глобальный и локальный размер рабочей группы, но это не складывается.

Максимальное использование памяти пиковой памяти - 4,5 ГБ. Перед заражением использовались ядра размером около 250 МБ. Это означает, что OpenCL использовал около 4,25 ГБ для 8 миллионов вызовов, т. Е. Около полукилограмм на вызов.

Так что мои вопросы:

  • Это вид использования памяти нормально и следовало ожидать?
  • Есть ли хорошие/известные методы сокращения использования памяти?
  • Возможно, я не должен ставить в очередь столько ядер одновременно, но как бы это сделать, не вызывая синхронизации, например. с clFinish()?
+0

Попробуйте 'clFlush' каждые 100 или 1000 вызовов ядра или даже реже, если вы заметите, что это повредит производительности. Это неблокирующая команда, которая выведет все ранее запрошенные команды на устройство. – doqtor

+0

Спасибо за подсказку! Я добавил «clFlush» после каждых 1000 вызовов ядра и немного улучшил его. Использование пиковой памяти снизилось до 3,5 ГБ, а пик намного короче, т. Е. Нисходящий наклон начинается гораздо раньше, но не столь крут. Влияние на производительность либо мало, либо не существует, я не вижу ничего. – Gigo

+0

ОК, попробуйте 'clWaitForEvents'.Ячейки Enqueue 1000 добавят событие на последнем, затем вставьте еще 999 ядер и вызовите 'clWaitForEvents'. Это заставит его дождаться завершения 1000-го ядра, пока в очереди еще будут 999 ядер. Затем повторите все так же. – doqtor

ответ

1

Завершение большого количества вызовов ядра должно выполняться бит-контролем, чтобы командная очередь не потребляла слишком много памяти. Во-первых, clFlush может в какой-то мере помочь, тогда clWaitForEvents необходим, чтобы сделать точку синхронизации посередине такой, что, например, вызовы ядра ядра выставлены в очередь, а clWaitForEvents ждет 1000-го. Устройство не собирается останавливаться, потому что у нас уже есть еще 1000 запросов на работу. Тогда подобное нужно повторять снова и снова. Это можно проиллюстрировать следующим образом:

enqueue 999 kernel commands 
while(invocations < 8000000) 
{ 
    enqueue 1 kernel command with an event 
    enqueue 999 kernel commands 
    wait for the event 
} 

Оптимальное количество вызовов ядра, после чего мы должны ждать, могут отличаться от представленных здесь, так что должно быть разработаны для данного сценария.