Сколько памяти я могу объявить как tile_static?
В настоящее время я нахожусь в процессе написания моего кода C++ AMP. Для каждой плитки у меня есть 4096 байтов данных, которые часто читаются, поэтому я хотел бы объявить это как tile_static. Делить это на несколько плиток нецелесообразно, поскольку каждому потоку необходим доступ ко всем данным. Мои тайлы состоят из 128 потоков, поэтому они должны занимать 2-4 деформации на графических процессорах Nvidia/AMD.
Я только что прочитал следующую статью, в которой, похоже, я могу использовать только 1024 бита в tile_static для основы: http://blogs.msdn.com/b/nativeconcurrency/archive/2012/08/14/avoid-bank-conflicts-on-tile-static-memory-with-c-amp.aspx
В некоторых современных графических процессорах память tile_static состоит из "n" банков памяти одинакового размера, к которым можно получить доступ одновременно, и последовательные "m" -битные слова отображаются в последовательные банки памяти. Точная организация памяти tile_static (т.е. n и m) зависит от аппаратного обеспечения. Например, на карте Nvidia GTX 580 или карте ATI HD 5870 память tile_static имеет 32 банка (n = 32), которые организованы так, что последовательные 32-разрядные слова (m = 32) отображаются в последовательные банки памяти. Обратите внимание, что n может отличаться от аппаратного обеспечения к аппаратному обеспечению, m обычно составляет 32. В оставшейся части поста я предполагаю, что m равно 32.
Означает ли это, что я могу объявить до 1024 бит на деформацию или на поток? Все переменные tile_static совместно используются деформациями, или каждая деформация имеет свою собственную копию?
Насколько эти вопросы зависят от аппаратного обеспечения, и если да, то как я могу узнать ограничения во время выполнения?
Я прочитал обложку книги C++ AMP, и хотя я благодарен авторам за то, что они познакомили меня с этой темой, похоже, что этот вопрос не решался (или, если это так, я не понял).
В Интернете много информации об использовании памяти tile_static (это хорошее начало: http://www.danielmoth.com/Blog/tilestatic-Tilebarrier-And-Tiled-Matrix-Multiplication-With-C-AMP.aspx) но никто, кажется, не говорит о том, сколько мы можем объявить, что делает невозможным фактически реализовать что-либо из этого! Эта последняя ссылка дает следующий пример:
01: void MatrixMultiplyTiled(vector<float>& vC,
const vector<float>& vA,
const vector<float>& vB, int M, int N, int W)
02: {
03: static const int TS = 16;
04: array_view<const float,2> a(M, W, vA);
05: array_view<const float,2> b(W, N, vB);
06: array_view<float,2> c(M,N,vC); c.discard_data();
07: parallel_for_each(c.extent.tile< TS, TS >(),
08: [=] (tiled_index< TS, TS> t_idx) restrict(amp)
09: {
10: int row = t_idx.local[0]; int col = t_idx.local[1];
11: float sum = 0.0f;
12: for (int i = 0; i < W; i += TS) {
13: tile_static float locA[TS][TS], locB[TS][TS];
14: locA[row][col] = a(t_idx.global[0], col + i);
15: locB[row][col] = b(row + i, t_idx.global[1]);
16: t_idx.barrier.wait();
17: for (int k = 0; k < TS; k++)
18: sum += locA[row][k] * locB[k][col];
19: t_idx.barrier.wait();
20: }
21: c[t_idx.global] = sum;
22: });
23: }
Обратите внимание, что строка 13 объявляет 2x 1024 бита, что позволяет мне надеяться, что мои 4096 бит не слишком большие, чтобы просить.... Если кто-то, имеющий некоторый опыт в программировании на C++ amp или GPU в целом, может помочь мне, это было бы здорово - Я полагаю, что эти вопросы больше зависят от аппаратного обеспечения / реализации, чем от самого расширения языка AMP...
2 ответа
Во-первых, я думаю, что вы имеете в виду 2 x 1024 байта, а не биты. Статическая память плитки объявляется для каждой плитки, а не для потока или деформации. Деформация - это на самом деле просто структура планирования для организации групп потоков, которые выполняются вместе, как правило, группами по 32 или 64 в зависимости от архитектуры. Чтобы облегчить жизнь планировщику, вы должны использовать плитки, которые содержат количество потоков, которое является точным кратным размеру основы.
Прежде чем обсуждать это подробно, полезно еще раз рассмотреть, как графические процессоры выполняют потоки, составляющие ваше ядро. Графические процессоры состоят из нескольких процессоров. AMD называет их вычислительными блоками, а NVIDIA называет их потоковыми мультипроцессорами. Каждый график CU работает в виде кусков или пучков потоков, называемых перекосами. Когда деформация блокируется, планировщик CU может скрывать задержки, переключаясь на другую деформацию, а не ожидая текущей деформации. CU могут использовать этот подход, чтобы скрыть задержки, связанные с обращениями к памяти, при условии, что доступны достаточные перекосы.
Одна из причин, по которой это не очень подробно освещено в книге, заключается в том, что C++ AMP разработан с учетом аппаратной независимости и работает поверх DirectX. Поэтому, если вы разрабатываете свое приложение с учетом конкретных деталей графического процессора, оно может стать менее переносимым. Кроме того, поскольку C++ AMP реализован поверх DX11, в некоторых случаях просто невозможно получить информацию об аппаратном обеспечении. Размер основы, tile_static
Размер памяти и размер кэша - все это примеры. Как и в случае с любой книгой, у нас также были ограничения по объему и срокам публикации.
Однако вы можете сделать разумные предположения о размере основы и памяти тайлов. На современном графическом процессоре предполагается, что размер деформации составляет 32 или 64, а статическая память тайлов порядка 10 с. Если вы действительно хотите настроить свой код для конкретного процессора, то вы можете использовать спецификации производителя и / или инструмент, который отображает соответствующую информацию.
На Tesla общая память составляет 16 КБ. В Fermi общая память на самом деле составляет 64 КБ, и ее можно настроить как программный кэш данных размером 48 КБ с аппаратным кешем данных 16 КБ или наоборот (SW 16 КБ, 48 КБ HW кэш).
10 с КБ могут показаться не слишком много памяти для tile_static
массив, но в действительности есть другие давления, которые также будут определять размер плитки; давление реестра для одного. Вы также должны помнить, что несколько очень больших плиток обычно приводят к низкой загруженности и, следовательно, к неэффективному коду.
Я согласен, что вся терминология банка памяти сбивает с толку. 32 бита относится к размеру банка памяти, а не к размеру общей памяти. Вы можете рассматривать банк как механизм доступа, а не как общее хранилище. Как указано в приведенной выше ссылке, каждый 32-битный банк сопоставляется с последовательными 32-битными адресами памяти. Поскольку вы получаете один доступ к банку за цикл, самый эффективный способ получить доступ к памяти - это прочитать по одному элементу из каждого банка. Или, чтобы все темы читали один и тот же элемент (трансляцию). Книга содержит некоторое обсуждение этого в главе "Производительность / оптимизация".
Это около 32 КБ. Если вы достигнете предела, вы получите ошибку при попытке компиляции.
Если вы не получили ошибку, все в порядке. Вы должны быть в состоянии проверить это самостоятельно, объявив массивный tile_static
массив, и вы должны получить гневное сообщение о том, что tile_static
предел