3D свертка, как операции с большим размером маски в CUDA, недостаточно общей памяти - PullRequest
0 голосов
/ 04 ноября 2019

В настоящее время я выполняю некоторые похожие на свертку операции, используя CUDA. Объектом являются три объемных изображения, каждое из которых имеет размер 512x512x512 , отфильтрованных большой маской фильтра 19x19x19 . Для каждого вокселя в каждом томе мне нужно выполнить некоторые операции с окружающими его вокселями, используя маску фильтра.

Схема реализации ядра CUDA на моей голове заключалась в том, что я запускаю блоки потоков размером BLOCK_SIZE, одинаковые для каждого измерения. Я заставляю TILE_SIZE соответствовать размеру вывода. Таким образом, все потоки в каждом блоке будут скользить, чтобы загрузить данные TILE_SIZE из глобальной памяти в общую память. Вот некоторые вычисления для использования памяти:

  • Общая постоянная память для маски фильтра: 19 * 19 * 19 * sizeof (float) / 1024 = 26,8 КиБ.
  • Общий размер разделяемой памяти = 3 * sizeof (float) * (BLOCK_SIZE + 2 * (19 - 1) / 2) ^ 3/1024 КиБ.

Постоянная память равнав пределах устройства 64 КБ, но использование общей памяти никогда не выходит за пределы того, что я использую BLOCK_SIZE. Например, для BLOCK_SIZE, равного 4, использование общей памяти составляет 166,38 КиБ.

Мой вопрос:

  • Поскольку общая память никогда не опускается ниже ограничения устройства 48 КБ, означает ли это, что сокращение доступа к глобальной памяти с использованием общей памяти невозможно?
  • Может кто-нибудь дать мне несколько идей по сокращению глобального доступа к памяти?

РЕДАКТИРОВАТЬ: @RobertCrovella, @tera, спасибо за ваш ответ! Извините, что не упомянул детали в оригинальном сообщении. Я пытался подумать о методе множественных проходов, но на самом деле вся операция слишком сложна для выполнения. Первым шагом является свертка одного из этих трех томов, скажем, V0. Затем мне нужно выполнить наименьших квадратов по отношению к окружающим вокселям с размером маски фильтра, каждого отдельного вокселя в каждом из этих трех томов:

min (|| a * V1_filterMask +b * V0_filterMask + c - V2_filterMask ||).

Так что на этапе подгонки ls я не могу сделать его отделимым для нескольких проходов. Я попытался, для 2D-изображения, с размером маски фильтра 19x19x19, загрузив окружающие пиксели в общую память для выполнения свертки, а затем подгонки по методу наименьших квадратов. Это фантастическая производительность, но теперь я обнаружил, что это вряд ли возможно из-за ограниченной sharedMem. не могли бы вы дать какие-либо предложения, пожалуйста?

...