tile_static динамически индексируемые массивы; я должен даже беспокоиться?

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

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

В идеальном мире я бы просто сделал это и профилировал, но это оказалось важной операцией, и я хотел бы получить представление о том, трачу ли я свое время здесь или нет:

tile_static int staticArray[128];
int resultFast = staticArray[0]; // this is super fast

// but what about this:   
i = // dynamically derived value!
int resultNotSoFast = staticArray[i]; // is this faster than getting it from global memory?

Как я могу узнать, поддерживает ли мой GPU/ драйвер динамическое индексирование статических массивов?

1 ответ

Решение

Динамическая индексация локальной памяти

Поэтому я немного покопался в этом, потому что тоже хотел это понять. Если вы имеете в виду динамическое индексирование локальной памяти, а не tile_static (или на языке CUDA "общая память"). В вашем примере выше staticArray должен быть объявлен как:

int staticArray[128]; // not tile_static

Это не может быть динамически проиндексировано, потому что массив int staticArray[128] фактически хранится как 128 регистров, и к ним нельзя получить динамический доступ. Выделение таких больших массивов в любом случае проблематично, так как использует большое количество регистров, которые являются ограниченным ресурсом на GPU. Используйте слишком много регистров для каждого потока, и ваше приложение не сможет использовать весь доступный параллелизм, потому что некоторые доступные потоки будут остановлены, ожидая появления регистров.

В случае с C++ AMP я даже не уверен, что уровень абстракции, предоставляемый DX11, может сделать это несколько нерелевантным. Мне не хватает эксперта по DX11, чтобы знать.

Здесь есть отличное объяснение: в ядре CUDA как сохранить массив в "локальной памяти потоков"?

Банковские конфликты

Плитка статической памяти делится на несколько модулей, называемых банками. Статическая память листов обычно состоит из 16, 32 или 64 банков, каждый из которых имеет ширину 32 бита. Это зависит от конкретного оборудования графического процессора и может измениться в будущем. Плитка статической памяти чередуется между этими банками. Это означает, что для графического процессора со статической памятью листов, реализованной с 32 банками, если arr является массивом , то arr[ 1] и arr[ 33] находятся в одном банке, потому что каждый float занимает один 32-битный банк место нахождения. Это ключевой момент, который нужно понимать, когда дело доходит до урегулирования банковских конфликтов.

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

Я думаю, что ключевым моментом путаницы может быть (на основе некоторых других ваших вопросов) то, что банк памяти имеет ширину 32 бита, но отвечает за доступ ко всей памяти в банке, которая будет 1/16, 1/32 или 1/64 от общей статической памяти тайлов.

Вы можете прочитать больше о банковских конфликтах здесь. Что такое банковский конфликт? (Занимаюсь программированием на Cuda/OpenCL)

Другие вопросы по тегам