GPGPU или зачем все эти упражнения
Все предыдущие
и более ранние мои упражнения были сделаны в качестве «подхода к снаряду», нужна
была baseline для более интересной задачи: вычислений общего назначения на видеокарте.
Эта тема в последние год-полтора (а особенно, в последние полгода) очень сильно нагрелась.
В то же время, в варианте от NVidia hardware и софт общедоступны, покупаешь видеокарту
и развлекаешься.
Приборы и материалы: NVidia CUDA и прочие
Настоящий общедоступный сдвиг произошел меньше месяца назад: 6 февраля 2006 г. вышла
вторая версия NVidia CUDA Toolkit, она же первая публичная (и первая более-менее работающая), она же
версия 0.8.
Эта версия доступна всем желающим без
подписания NDA, следовательно результаты тестов можно открыто публиковать.
Тема исследования, как обычно, умножение матриц. Задача очень простая алгоритмически, но
со своими особенностями. В силу простоты задачи, изучать особенности одно удовольствие.
Рассматривались три доступных умножителя матриц:
- SGEMM в составе библиотеки CUBLAS.
- Тестовый пример от NVidia, который очень подробно разобран в документации.
- Реализация SGEMM от RapidMind.
Сравнивалось все с результатами вычислений на доступных мне компьютерах общего назначения:
- Dual Opteron 275 (2.2 Ghz) - долгое время это был "предпоследний процессор в линейке"
т.е. наиболее разумный выбор по цена/качество. - Dual Xeon 5140 - текущий оптимум по цена/производительность.
Стоимости решений
Видеокарта сама по себе не работает, поэтому интересно сравнить "платформы", состоящие
из процессора, материнской платы, пары гигабайт памяти и видео. В минимальном варианте
три разных системы будут стоить на сегодня (по московским ценам):
- Вычислитель на G80: NVidia 8800GTX + современная недорогая обвязка (процессор,
память): $1200-1300, половину суммы составляет видеокарта. - Вычислитель на Dual Opteron 275: $1200-1300, половину стоимости составляют
два процессора. - Вычислитель на Dual Xeon 5140: $1600-1700 из которых около 1000 за два процессора.
Xeon - существенно дороже, но как мы помним по прошлым тестам, он примерно в 1.6 раза быстрее
на вычислениях.
Результаты тестов
Вычисления на видеокарте проходят в три этапа:
- Загрузка данных в видеопамять
- Запуск вычислительного модуля, исполняемого GPU
- Выгрузка данных в основную память компьютера
В-принципе, загрузка-выгрузка могут осуществляться одновременно с
расчетами (если области видеопамяти не пересекаются), поэтому при
оценке быстродействия интересны два времени: чистое время на исполнение
(это быстродействие мы получим, если у нас есть много данных для расчетов)
и с учетом ввода-вывода (это время обсчета одной задачи).
| Быстродействие на перемножении матриц (MFLOP/s) | ||||
|---|---|---|---|---|
| Платформа | размер задачи | |||
| 1024 | 2048 | 4096 | ||
| Вычисления на CPU | ||||
| 2xOpteron 275, Goto BLASsingle precision, 4 threads | 23 091 | 28 971 | 30 272 | |
| 2xXeon 5140, Goto BLASsingle precision, 4 threads | 26 512 | 45 935 | 47 556 | |
| NVidia G8800GTX: Чистое время вычислений | ||||
| RapidMind 2.0b3 | 109 653 | -* | -* | |
| пример из CUDA toolkit | 46 403 | 46 562 | 46 299 | |
| cuBLAS SGEMM | 97 713 | 99 890 | 98 738 | |
| NVidia G8800GTX: Вычисления + загрузка-выгрузка данных в видеокарту | ||||
| RapidMind 2.0b3 | 33 314 | -* | -* | |
| пример из CUDA toolkit + IO | 25 230 | 35 911 | 40 879 | |
| NVidia G8800GTX, cuBLAS SGEMM | 58 703 | 73 670 | 83 473 | |
| * — Стандартный пример от RapidMind ограничен матрицами 1020x1020 | ||||
Обсуждение результатов
RapidMind
Пример от RapidMind не использует аппаратных особенностей G80 и должен работать
на любой DX9-видеокарте. Используется операция MAD (Multiply-Add) над векторными
(4 компонента) операциями. По всей видимости, MAD работает, получающаяся производительность
весьма вкусная. К несчастью, пример плохо масштабируется, программировать в терминах
4-векторов очень мучительно. А убивает все скорость копирования данных из видеокарты:
стандартные средства DX9 очень медленные и неудобные.
Пример от NVIdia
Умножение матриц в примере от NVidia сделано с большой претензией: блоки данных
копируются в сверхбыструю shared-memory, где и умножаются. Однако shared-памяти мало,
16 килобайт на мультпроцессор (всего, соответственно, 256kb полмегабайта, исправлено 01.10.07) и весь пар уходит
в свисток: синхронизацию всех тредов. Результат получается хуже, чем у более сложного
кода для CuBLAS.
CuBLAS
Про внутренности CuBLAS неизвестно ничего. По внешним признакам, там нет глупостей
с оптимизацией на кратность матрицы размеру блока в shared memory и прекрасно
сделано копирование данных в(из) видеопамять.
Выводы
На несложной задаче без ручных оптимизаций NVidia G80 делает в 2-3 раза
вычисления на мощных современных CPU (двух двухядерных). Исследования надлежит
продолжать.