Проблема наложения памяти на вычисления в cuda

0

У меня есть ядро CUDA, обрабатывающее много данных. Поскольку я не могу сразу передать все данные, я должен разбить их на куски и обработать их патронами и обновить выходные данные на графическом процессоре. Я разбираю входные данные из файла. Я думал, могу ли я перекрывать передачи памяти кусков, имея два буфера как на хосте, так и на графическом процессоре. При обработке одного патрона я мог читать другой, передавать его на GPU и запускать ядро в тот же поток. Моя проблема в том, что время выполнения ядра медленнее, чем синтаксический анализ данных и перенос их на GPU. Как я могу гарантировать, что memcpys не будет записывать данные, которые использует ядро, учитывая тот факт, что memcpys не блокируют?

//e.g. Pseudocode
//for every chunk
   //parse data
   //cudaMemcpyAsync ( dev, host, size, H2D )
   //launch kernel
   //switch_buffer
//copy result from device to host

Заранее спасибо.

  • 1
    Если это вариант для вас, чтобы не использовать повторно одну и ту же память каждый раз и переключать буферы, вы можете взглянуть на этот вебинар . Возможность состоит в том, чтобы использовать разные потоки для каждой пары соответствующих memcpy и запуска ядра. Также вы должны убедиться, что вы используете закрепленную память! В вашем псевдокоде используемый поток cuda также отсутствует в cudaMemcpyAsync .
Теги:
asynchronous
parallel-processing
cuda
overlap

1 ответ

0
Лучший ответ

Просто вставьте явную точку синхронизации с cudaDeviceSynchronize() после запуска ядра.

Таким образом, вы, по сути, начинаете передачу памяти и запускаете ядро одновременно. Передача переместилась бы в один буфер, и ядро работало бы с другим. CudaDeviceSynchronize() будет ждать, пока оба будут выполнены, и в это время вы поменяете буфер и повторите.

Конечно, вам также нужно скопировать результаты с устройства на хост в цикле и добавить логику для обработки первой итерации, когда нет данных для ядра для обработки еще и последней итерации, когда нет больше данных для копия, но еще один буфер для обработки. Это можно сделать с помощью логики в цикле или путем частичного разворачивания цикла, чтобы конкретно кодировать первую и последнюю итерации.

Редактировать:

Перемещая точку синхронизации непосредственно перед cudaMemcpyAsync() и после чтения и анализа файла вы позволяете ядру также перекрывать эту часть обработки (если ядро работает достаточно долго).

  • 0
    Я реализовал это с помощью cudaDeviceSynchronize, но я хотел избежать этого, так как это требует времени. Тем не менее, я не вижу другого способа обеспечить то, что я хочу. Спасибо.
  • 0
    @ user2117698, если вы удвоите буфер, как описывает Роджер, это не будет стоить много дополнительного времени. Ваше потенциальное ускорение ограничено тем, насколько равномерно распределена ваша рабочая нагрузка между переносом и вычислением. Если два буфера достаточно велики, тогда издержки запуска ядра и мемппы будут скрыты, а производительность будет снижаться с естественной степенью ограниченности передачи / обработки.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню