путаница в оптимизации общей памяти

#cuda #memory-optimization

#cuda #gpu-shared-memory #оптимизация памяти

Вопрос:

Я написал приложение на CUDA, которое использует 1 КБ общей памяти в каждом блоке.
Поскольку в каждом SM имеется только 16 КБ общей памяти, в целом можно разместить только 16 блоков, верно? Хотя одновременно можно запланировать только 8, но теперь, если какой-то блок занят выполнением операций с памятью, на графическом процессоре будет запланирован другой блок, но вся общая память используется другими 16 блоками, которые уже были запланированы там.

Так не будет ли CUDA планировать больше блоков на том же SM, если предыдущие выделенные блоки не будут полностью завершены?

Или это переместит общую память какого-либо блока в глобальную память и выделит там другой блок? В этом случае нам следует беспокоиться о глобальной задержке доступа к памяти?

Ответ №1:

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

  1. 8 блоков
  2. Количество блоков, сумма статической и динамически выделяемой общей памяти которых составляет менее 16 КБ или 48 КБ, в зависимости от архитектуры и настроек GPU. Также существуют ограничения на размер страницы в общей памяти, которые означают, что распределение на блок округляется до следующего по величине кратного размера страницы
  3. Количество блоков, сумма использования регистра каждого блока которых меньше 8192/16384/32678, в зависимости от архитектуры. Существуют также размеры страниц файла реестра, которые означают, что распределение на блок округляется до следующего по величине кратного размера страницы.

Это все, что нужно сделать. Нет «подкачки» общей памяти для размещения большего количества блоков. NVIDIA создала электронную таблицу для вычисления занятости, которая поставляется вместе с инструментарием и доступна для отдельной загрузки. Вы можете увидеть точные правила в формулах, которые он содержит. Они также обсуждаются в разделе 4.2 руководства по программированию на CUDA.

Комментарии:

1. значит ли это, что иногда лучше не использовать общую память? поскольку параллельно будет выполняться больше блоков?

2. Это действительно зависит. Общая память намного медленнее, чем register, а у register нет конфликтов банков, поэтому всегда лучше использовать register поверх общей памяти, если это возможно. Традиционное использование общей памяти заключалось в том, чтобы разрешить повторное использование данных между потоками внутри блока, и во времена до ферми это было очень эффективно для этого. В Fermi аргументы в пользу разделяемой памяти могут быть немного менее убедительными. Кэши L1 и L2 означают, что вы часто можете получить значительную часть того, что дает mint с общей памятью, ничего не делая, и не возникает конфликтов банков или эффектов сериализации, о которых стоит беспокоиться.

3. Итак, это похоже на то, что если некоторые блоки будут запланированы на одном SM в одно мгновение, и теперь все деформации ожидают завершения операции с памятью, поэтому cuda запланирует другой блок на том же SM (что произойдет с данными общей памяти уже выделенных блоков?), или он будет ждать, пока выделенные блоки завершат свои операции?

4. Аппаратное обеспечение всегда будет планировать столько блоков, сколько сможет выполнить, а затем не больше, пока не будут доступны ресурсы, чтобы можно было запланировать больше. Если бы каждая активная деформация в SM ожидала транзакций с памятью или находилась на барьере синхронизации, SM был бы остановлен. То, как именно работает эвристика планирования, официально не задокументировано, но общее мнение, похоже, таково, что в картах до fermi новые блоки не будут планироваться, пока каждый блок не будет завершен на SM, но в fermi это более гибко, чем это.