Что такое объединение памяти в CUDA и как оно достигается? - PullRequest
65 голосов
/ 18 февраля 2011

Что такое «объединение» в глобальной транзакции памяти CUDA?Я не мог понять даже после прохождения моего руководства CUDA.Как это сделать?В примере матрицы руководства по программированию CUDA, доступ к матрице строка за строкой называется "объединенным", или col .. по столбцу ... называется объединенным?Что правильно и почему?

Ответы [ 4 ]

135 голосов
/ 18 февраля 2011

Вполне вероятно, что эта информация применима только для вычисления возможностей 1.x или cuda 2.0. Более поздние архитектуры и cuda 3.0 имеют более сложный доступ к глобальной памяти, и фактически «объединенные глобальные нагрузки» даже не профилируются для этих чипов.

Кроме того, эта логика может быть применена к общей памяти, чтобы избежать конфликтов банков.


Транзакция объединенной памяти - это транзакция, в которой все потоки в полусфере одновременно обращаются к глобальной памяти. Это слишком просто, но правильный способ сделать это - просто иметь последовательные потоки, обращающиеся к последовательным адресам памяти.

Таким образом, если потоки 0, 1, 2 и 3 читают глобальную память 0x0, 0x4, 0x8 и 0xc, это должно быть объединенное чтение.

В примере с матрицей имейте в виду, что вы хотите, чтобы ваша матрица линейно находилась в памяти. Вы можете делать это как хотите, и ваш доступ к памяти должен отражать, как устроена ваша матрица. Итак, матрица 3х4 ниже

0 1 2 3
4 5 6 7
8 9 a b

может быть сделано строка за строкой, например, так что (r, c) отображается в память (r * 4 + c)

0 1 2 3 4 5 6 7 8 9 a b

Предположим, вам нужно получить доступ к элементу один раз и сказать, что у вас есть четыре потока. Какие темы будут использоваться для какого элемента? Возможно либо

thread 0:  0, 1, 2
thread 1:  3, 4, 5
thread 2:  6, 7, 8
thread 3:  9, a, b

или

thread 0:  0, 4, 8
thread 1:  1, 5, 9
thread 2:  2, 6, a
thread 3:  3, 7, b

Что лучше? Что приведет к слиянию операций чтения, а что нет?

В любом случае каждый поток имеет три доступа. Давайте посмотрим на первый доступ и посмотрим, будут ли потоки обращаться к памяти последовательно. В первом варианте первый доступ - 0, 3, 6, 9. Не последовательно, не объединено. Второй вариант, это 0, 1, 2, 3. Последовательный! Слившихся! Ура!

Лучший способ, вероятно, написать свое ядро ​​и затем профилировать его, чтобы увидеть, есть ли у вас не слитые глобальные загрузки и хранилища.

10 голосов
/ 15 февраля 2014

Объединение памяти - это метод, который позволяет оптимально использовать пропускную способность глобальной памяти.То есть, когда параллельные потоки, выполняющие одну и ту же инструкцию, обращаются к последовательным расположениям в глобальной памяти, достигается наиболее благоприятный шаблон доступа.

enter image description here

Пример на рисунке выше помогает объяснитьобъединенное расположение:

На рис. (а) n векторы длины m хранятся линейным образом.Элемент i вектора j обозначается v j i .Каждому потоку в ядре графического процессора присваивается один вектор m .Потоки в CUDA сгруппированы в массив блоков, и каждый поток в GPU имеет уникальный идентификатор, который может быть определен как indx=bd*bx+tx, где bd представляет размер блока, bx обозначает индекс блока, а tx - потокИндекс в каждом блоке.

Вертикальные стрелки показывают случай, когда параллельные потоки обращаются к первым компонентам каждого вектора, то есть к адресам 0, m , 2m ... памяти.Как показано на рис. (А), в этом случае доступ к памяти не является последовательным.Обнуляя разрыв между этими адресами (красные стрелки показаны на рисунке выше), доступ к памяти становится объединенным.

Однако, здесь проблема немного усложняется, поскольку допустимый размер резидентных потоков на блок GPU ограничен bd.Поэтому объединение данных может быть выполнено путем сохранения первых элементов первых bd векторов в последовательном порядке, за которыми следуют первые элементы вторых bd векторов и так далее.Остальные элементы векторов сохраняются аналогичным образом, как показано на рис. (Б).Если n (число векторов) не является коэффициентом bd, необходимо дополнить оставшиеся данные в последнем блоке некоторым тривиальным значением, например, 0.

Влинейное хранение данных на рис. (а), компонент i (0 ≤ i <<em> m ) вектора indx (0 ≤ indx <<em> n ) адресуется m × indx +i;тот же компонент в объединенной схеме хранения на рис. (б) обозначен как

(m × bd) ixC + bd × ixB + ixA,

, где ixC = floor[(m.indx + j )/(m.bd)]= bx, ixB = j и ixA = mod(indx,bd) = tx.

В итоге, в примере сохранения количества векторов размером m линейное индексирование отображается на объединенное индексирование в соответствии с:

m.indx +i −→ m.bd.bx +i .bd +tx

Эта перегруппировка данных может привести к значительному увеличению пропускной способности памяти глобальной памяти графического процессора.


источник: «Ускорение вычислений на основе графического процессора в нелинейном анализе деформаций конечных элементов».Международный журнал по численным методам в биомедицинской инженерии (2013).

7 голосов
/ 18 февраля 2011

Если потоки в блоке обращаются к последовательным ячейкам глобальной памяти, то все обращения объединяются аппаратным обеспечением в один запрос (или объединяются). В примере матрицы элементы матрицы в строке расположены линейно, за ними следует следующая строка и так далее. Например, для матрицы 2x2 и 2 потоков в блоке ячейки памяти расположены следующим образом:

(0,0) (0,1) (1,0) (1,1)

При доступе к строке, thread1 обращается к (0,0) и (1,0), которые не могут быть объединены. При доступе к столбцу поток1 обращается к (0,0) и (0,1), которые могут быть объединены, потому что они смежные.

2 голосов
/ 23 апреля 2011

Критерии объединения хорошо документированы в Руководстве по программированию CUDA 3.2 , Раздел G.3.2.Краткая версия выглядит следующим образом: потоки в деформации должны последовательно обращаться к памяти, а слова, к которым осуществляется доступ, должны> = 32 бита.Кроме того, базовый адрес, к которому обращается деформация, должен быть выровнен на 64, 128 или 256 байт для 32-, 64- и 128-битного доступа соответственно.

Оборудование Tesla2 и Fermi работает нормальноработа по объединению 8- и 16-битных обращений, но их лучше избегать, если вы хотите пиковой пропускной способности.

Обратите внимание, что, несмотря на улучшения в аппаратном обеспечении Tesla2 и Fermi, объединение BY NO MEANS устарело.Даже на оборудовании класса Tesla2 или Fermi, неспособность объединить глобальные транзакции памяти может привести к удвоению производительности.(На оборудовании класса Fermi это, кажется, верно только при включенном ECC. Непрерывные транзакции с памятью занимают около 20% для Fermi.)

...