Подтвердить что ты не робот

В CUDA, что такое объединение памяти и как оно достигается?

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

4b9b3361

Ответ 1

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

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


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

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

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

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. Последовательный! Слившихся! Ура!

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

Ответ 2

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

enter image description here

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

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

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

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

В линейном хранилище данных на фиг. (a) компонент я (0 ≤ я < m) векторного indx (0 ≤ indx < n) адресуется на m × indx +i; тот же компонент в объединенном (b) рассматривается как

(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

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


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

Ответ 3

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

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

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

Ответ 4

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

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

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