Как правильно объединить чтения из глобальной памяти в разделяемую память с элементами типа short или char (при условии, что по одному потоку на элемент)? - PullRequest
3 голосов
/ 21 января 2012

У меня есть вопросы по поводу объединенных глобальных загрузок памяти в CUDA.В настоящее время мне нужно иметь возможность выполнять на устройстве CUDA с возможностью вычислений CUDA 1.1 или 1.3.

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

Мой план состоит в том, чтобы каждый поток считывал один элемент в общую память, а затем __syncthreads () перед началом вычисления,В этом сценарии каждый поток загружает, вычисляет и сохраняет один элемент (хотя вычисления зависят от элементов, загруженных в общую память другими потоками).

В этом вопросе я хочу сосредоточиться на чтении из глобальной памяти вобщая память.

Предполагая, что в массиве есть N элементов, я настроил CUDA для выполнения в общей сложности N потоков.Для случая, когда sizeof (T) == 4, это должно хорошо слиться в соответствии с моим пониманием CUDA, так как поток K будет читать слово K (где K - индекс потока).

Однако в случаегде sizeof(T) < 4, например, если T = unsigned char или T = short, то я думаю, что это может быть проблемой.В этом случае мой (наивный) план таков:

  • Вычислить numElementsPerWord = 4 / sizeof (T)
  • если (K% numElementsPerWord == 0), то прочитать есть поток Kпрочитайте следующее полное 32-битное слово
  • сохраните 32-битное слово в разделяемой памяти
  • после заполнения разделяемой памяти (и вызовите __syncthreads ()), после чего каждый поток K сможет обработать работупри вычислении выходного элемента K

Меня беспокоит, что он не будет объединяться, потому что (например, в случае, когда T = short)

  • Поток 0 читает слово 0 изглобальная память
  • поток 1 не читает
  • поток 2 читает слово 1 из глобальной памяти
  • поток 3 не читает
  • и т. д ...

Другими словами, поток K читает слово (K / sizeof (T)).Казалось бы, это не слилось должным образом.

Альтернативный подход, который я рассмотрел, был:

  • Запуск с числом потоков = (N + 3) / 4, так что каждый поток будетотвечать за загрузку и обработку (4 / sizeof (T)) элементов (каждый поток обрабатывает одно 32-битное слово - возможно, 1, 2 или 4 элемента в зависимости от sizeof (T)).Однако я обеспокоен тем, что этот подход не будет настолько быстрым, насколько это возможно, поскольку каждый поток должен затем в два раза (если T = short) или даже в четыре раза (если T = unsigned char) количество обработки.

Может кто-нибудь сказать мне, если мои предположения о моем плане верны: то есть: он не будет объединяться должным образом?

Можете ли вы прокомментировать мой альтернативный подход?

Можете ли вы порекомендовать более оптимальныйподход, который правильно объединяется?

1 Ответ

3 голосов
/ 21 января 2012

Вы правы, вы должны выполнить загрузки размером не менее 32 бит, чтобы получить объединение, и схема, которую вы описываете (когда каждый другой поток выполняет загрузку) не будет объединяться.Просто сдвиньте смещение вправо на 2 бита, и каждый поток будет выполнять непрерывную 32-разрядную загрузку, и используйте условный код, чтобы запретить выполнение для потоков, которые будут работать с адресами вне диапазона.

Поскольку вы нацеливаетесьSM 1.x, обратите внимание также на то, что 1) для того, чтобы произошло объединение, нить 0 данной деформации (наборы из 32 нитей) должна быть выровнена на 64, 128 или 256 байтов для 4, 8 и 16байтные операнды, соответственно, и 2) когда ваши данные находятся в разделяемой памяти, вы можете развернуть цикл в 2 раза (для краткости) или 4 раза (для символа), чтобы смежные потоки ссылались на смежные 32-битные слова, чтобы избежать банка разделяемой памятиконфликты.

...