Современные информационные технологии /2.
Вычислительная техника и программирование
Аспирант Лунин Д.В., д.т.н.,
проф. Скворцов С.В.
Рязанский государственный
радиотехнический университет, Россия
Параллельные вычисления на платформе CUDA
Интерес к использованию
графических ускорителей в качестве средств высокопроизводительных вычислений
поддерживается усилиями ведущих разработчиков аппаратуры. Так, компания nVidia предоставляет платформу CUDA [1] для вычислений на
графическом ускорителе. Аналогично, компания AMD выступила с инициативой Stream
[2].
Такие платформы
облегчают реализацию различных задач на графических ускорителях, поскольку
поддерживают модель программирования, которая более приспособлена к разработке
произвольных вычислений, по сравнению со средствами программирования графики.
Тем не менее, разработка приложений для графических ускорителей остается
достаточно сложной задачей. Разработчик должен быть знаком с устройством
графического ускорителя, он должен понимать особенности работы его компонент и
принципы организации вычислений, включая взаимодействие с центральным
процессором.
Таким образом, задача организации вычислений средствами
графических ускорителей, является актуальной и новой по сравнению как с
последовательным программированием, так и с многопоточным параллельным
программированием [3,4]. Многие аспекты этой задачи требуют достаточно
низкоуровневой реализации и оптимизации кода, подобно методам и алгоритмам,
изложенным в работах [10-12].
Современные
графические ускорители поддерживают высокую степень параллелизма, специально
приспособленную для выполнения графических задач. Использование возможностей
графических ускорителей для общецелевых вычислений требует от разработчика
понимания особенностей аппаратной платформы и модели программирования.
Возможными вариантами применения технологии CUDA являются как создание новых
параллельных приложений для решения прикладных задач, так и модификация
существующего последовательного программного обеспечения.
Программа для графического ускорителя, написанная на платформе CUDA, разделяется на две части: код для
исполнения на графическом устройстве (device code) и код для исполнения на
центральном процессоре (host code). Код для исполнения на графическом
устройстве (device) может быть
написан как на специальном низкоуровневом языке (PTX), так и на расширении
языка Си (Си для CUDA). В последнем случае ядро имеет вид функции языка Си,
описывающей поведение одного потока.
При создании
приложений, программист имеет возможность задавать количество блоков и потоков.
Оптимальным является использование от 64 до 512 потоков в блоке. Группировка
блоков в сетки позволяет применить ядро к большему числу потоков за один вызов.
Это помогает и при масштабировании. Если у графического процессора недостаточно
ресурсов, он будет выполнять блоки последовательно. В обратном случае, блоки
могут выполняться параллельно, что важно для оптимального распределения работы
на видеоплатах разного уровня.
В качестве практического примера использования CUDA разработана программа умножения
двух матриц на графическом ускорителе. Пусть исходные матрицы А и В
являются квадратными и имеют размер n*n.
Результирующая матрица C будет иметь такой же размер.
Для организации параллельного умножения матриц A и B представим результат - матрицу С
в виде совокупности квадратных подматриц размером BLOCK_SIZE*BLOCK_SIZE
таким образом, чтобы вычисление всех элементов каждой подматрицы производилось
бы последовательно в одном потоке (thread). Все подобные
потоки, сформированные в среде CUDA, выполняются
параллельно аппаратными средствами графического ускорителя (device).
Для оценки эффекта от применения распараллеливающих преобразований на
платформе CUDA были
проведены измерения скорости работы двух программ умножения матриц:
последовательная реализация на ЦП; многопоточная реализация на базе
графического ускорителя (ГУ). При этом вторая версия программы запускалась на
выполнение с тремя вариантами параметров ядра для значений BLOCK_SIZE = 16; 32;
64; 128.
При проведении экспериментов использовались следующие аппаратные
средства: ЦП Intel Core-i7; видеоплата
nVidia Quadro FX1800 с памятью 1 ГБ. Для каждого
размера матрицы выполнено по 10 опытов с разными исходными данными. Полученные
результаты представлены в таблице 1.
Таблица
1 – Среднее время умножения квадратных матриц (мс)
|
Программа умножения матриц |
Порядок матрицы n |
||
|
256 |
512 |
1024 |
|
|
Последовательная на ЦП |
66 |
588 |
6621 |
|
Многопоточная на ГУ (BLOCK_SIZE = 16) |
21 |
167 |
1318 |
|
Многопоточная на ГУ (BLOCK_SIZE = 32) |
2.35 |
6.32 |
10.73 |
|
Многопоточная на ГУ (BLOCK_SIZE = 64) |
0.53 |
1.33 |
4.26 |
|
Многопоточная на ГУ (BLOCK_SIZE = 128) |
0.86 |
1.52 |
4.69 |
Полученные результаты показывают, что использование
графического ускорителя позволяет значительно увеличить скорость работы
многопоточных программ. Так при n = 1024 время
выполнения многопоточной версии программы по сравнению с последовательной
однопоточной сокращается примерно в 300 раз. Для матриц, состоящих из
небольшого числа элементов, выигрыш составляет около 40 раз. Важно отметить,
что скорость работы многопоточной программы сильно зависит от параметра BLOCK_SIZE, значение которого должно выбираться
экспериментально.
Дальнейшие
исследования в данном направлении предполагают разработку дополнительных
алгоритмов для распараллеливания и оптимизации кода для графических
ускорителей, а также оценку их эффективности при различных режимах запуска
ядра.
Литература:
1. CUDA
Parallel Computing Platform. [Электронный ресурс]. URL: http://www.nvidia.com/cuda
(дата обращения 28.03.14).
2. AMD Quick Stream Technology. [Электронный
ресурс]. URL:
http://www.amd.com/es/solutions/software/pages/quick-stream-technology.aspx (дата обращения 28.03.14).
3. Камерон Х., Трейси Х. Параллельное и распределенное программирование с использованием C++.
М.: Вильямс, 2004. 672 с.
4. Эндрюс Г.
Основы многопоточного, параллельного и распределенного программирования. М.: ИД
”Вильямс”, 2003. 512 с.
5. Козлов М.А., Скворцов С.В. Алгоритмы параллельной
сортировки данных и их реализация на языке Clojure // Вестник Рязанского
государственного радиотехнического университета. 2013. № 4-1 (46). С. 92-96.
6. Першин А.С., Скворцов С.В. Распределение регистровой
памяти в системах параллельной обработки данных // Системы управления и
информационные технологии. 2007. № 1 (27). С. 65-70.
7. Рудаков В.Е., Скворцов С.В. Построение базового множества
независимых путей потокового графа для тестирования программных модулей //
Системы управления и информационные технологии. 2012. Т. 50. № 4. С. 67-70.
8. Михеева Л.Б., Скворцов С.В. Синтез параллельного кода для RISC-процессоров с оптимизацией загрузки регистровой памяти // Информационные технологии. 2002. № 7. С. 2-9.