умножение матриц в cuda - PullRequest
       9

умножение матриц в cuda

3 голосов
/ 05 октября 2010

скажем, я хочу умножить две матрицы вместе, 50 на 50. У меня есть 2 способа упорядочить потоки и блоки.

a) один поток для вычисления каждого элемента матрицы результатов. Таким образом, у меня есть цикл в потоке умножает одну строку и один столбец.

б) один поток для каждого умножения. Каждый элемент матрицы результата требует 50 потоков. После умножения я могу использовать двоичное сокращение для суммирования результатов.

Я не был уверен, какой путь взять, поэтому я взял б. Это не было идеальным. На самом деле это было медленно. Есть идеи почему? Я думаю, что слишком много потоков и они большую часть времени ждут ресурсов, это правда?

Ответы [ 4 ]

4 голосов
/ 05 октября 2010

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

Если вы используете один поток, выполните одно умножение, затем для этого потока вы должны извлечь две части данных из памяти, умножить их, а затем выполнить некоторое логарифмическое число операций добавления. Это три обращения к памяти для mult и add и немного - арифметическая интенсивность очень низкая. Хорошая новость заключается в том, что таким образом существует множество задач, каждый из которых требует лишь небольшого объема памяти / регистров, что хорошо для заполнения; но отношение памяти к работе плохое.

Простой однопоточный подход, использующий одноточечный продукт, имеет такую ​​же проблему - для каждого умножения требуется два доступа к памяти для загрузки. Хорошая новость заключается в том, что для всего продукта точка есть только одно хранилище в глобальной памяти, и вы избегаете двоичного сокращения, которое также не масштабируется и требует большой синхронизации; обратная сторона в том, что теперь стало намного меньше потоков, что, по крайней мере, ваш (b) подход помог вам.

Теперь вы знаете, что должен быть какой-то способ сделать больше операций для доступа к памяти, чем этот; для квадратных NxN-матриц умножение выполняется N ^ 3, но только 3xN ^ 2 элемента - так что вы должны быть в состоянии найти способ выполнить более 1 вычисления за 2 обращения к памяти.

Подход, принятый в CUDA SDK, является наилучшим способом - матрицы разбиты на фрагменты, и используется ваш (b) подход - один поток на элемент вывода. Но ключ в том, как устроены темы. Извлекая целые маленькие подматрицы из медленной глобальной памяти в разделяемую память и выполняя вычисления оттуда, можно делать многократные умножения и добавлять каждое число, которое вы считали из памяти. Этот подход является наиболее успешным подходом во многих приложениях, потому что получение данных - будь то по сети, или из основной памяти для ЦП, или вне-чипового доступа для графического процессора - часто занимает гораздо больше времени, чем обработка данных.

На страницах CUDA от NVidia есть документы (особенно http://developer.nvidia.com/object/cuda_training.html), которые очень хорошо описывают пример SDK.

3 голосов
/ 05 октября 2010

Вы смотрели документацию CUDA: Модель программирования Cuda

Кроме того, пример исходного кода: Умножение матриц

1 голос
/ 05 октября 2010

Вы смотрели на

$SDK/nvidia-gpu-sdk-3.1/C/src/matrixMul

т.е. пример умножения матриц в SDK?

0 голосов
/ 23 апреля 2012

Если вам не нужно реализовывать это самостоятельно, просто используйте библиотеку - CUBLAS, MAGMA и т. Д., Предоставьте настроенные реализации умножения матриц.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...