Причина относительно низкой производительности общей памяти CUDA при использовании больших массивов может быть связана с тем фактом, что каждый многопроцессорный процессор имеет ограниченный объем доступной общей памяти.
Каждый мультипроцессор содержит несколько процессоров; для современных устройств, как правило, 32, количество потоков в основе. Это означает, что при отсутствии расхождений или остановок памяти средняя скорость обработки составляет 32 инструкции за цикл (задержка высока из-за конвейерной обработки).
CUDA планирует несколько блоков для многопроцессорных. Каждый блок состоит из нескольких основ. Когда деформация останавливается при глобальном доступе к памяти (даже объединенные доступы имеют большую задержку), другие деформации обрабатываются. Это эффективно скрывает задержку, поэтому глобальная память с высокой задержкой приемлема в графических процессорах. Чтобы эффективно скрыть задержку, вам нужно выполнить достаточное количество дополнительных деформаций до тех пор, пока не прекратится остановка. Если при доступе к памяти все деформации останавливаются, вы больше не можете скрывать задержку.
Общая память выделяется блокам в CUDA и сохраняется на однопроцессорном устройстве на устройстве с графическим процессором. Каждый мультипроцессор имеет относительно небольшой фиксированный объем общей памяти. CUDA не может запланировать больше блоков для многопроцессорных систем, чем мультипроцессоры могут поддерживать с точки зрения общей памяти и использования регистров. Другими словами, если объем разделяемой памяти на многопроцессорном устройстве равен X, а для каждого блока требуется Y совместно используемой памяти, CUDA будет планировать не более нижних (X / Y) блоков одновременно для каждого мультипроцессора (это может быть меньше, поскольку другие ограничения, такие как использование регистра).
Следовательно, увеличивая использование совместно используемой памяти блока, вы можете уменьшить количество активных деформаций - занятость - вашего ядра, тем самым снижая производительность. Вы должны заглянуть в код своего ядра, скомпилировав с флагом -Xptxas = "- v"; это должно дать вам регистрацию и использование общей и постоянной памяти для каждого ядра. Используйте эти данные и параметры запуска вашего ядра, а также другую необходимую информацию в самой последней версии CUDA Occupancy Calculator, чтобы определить, может ли на вас повлиять занятость.
EDIT:
Чтобы ответить на другую часть вашего вопроса, не допуская конфликтов банков совместно используемой памяти и безупречного объединения глобальных обращений к памяти ... у этого ответа есть два измерения: задержка и пропускная способность. Задержка разделяемой памяти будет ниже, чем задержка глобальной памяти, поскольку разделяемая память находится на кристалле. Пропускная способность будет примерно такой же. Следовательно, если вы можете скрыть глобальную задержку доступа к памяти посредством объединения, штрафов не будет (примечание: здесь важен шаблон доступа, поскольку общая память допускает потенциально более разнообразные шаблоны доступа практически без потери производительности, поэтому иметь преимущества в использовании разделяемой памяти, даже если вы можете скрыть все глобальные задержки памяти).