A GPU-resident Memory-Aware Algorithm for Accelerating Bidiagonalization of Banded Matrices
Ringoot, Alomairy, Edelman
The reduction of a banded matrix to a bidiagonal form is a crucial step in the Singular Value Decomposition (SVD), a cornerstone of scientific computing and AI. Despite being a highly parallel algorithm, it was previously believed to be unsuitable for GPU computation because it is memory bandwidth-bound. Recent developments in GPU hardware, including larger L1 memory per Streaming Multiprocessor/Compute Unit, have changed that. We present the first GPU algorithm for reducing a banded matrix to bidiagonal form as part of the NextLA.jl open-source software package. Our algorithm is based on previous CPU-based multicore parallel cache-efficient bulge chasing algorithms and adapted to optimize for GPU throughput. We leverage Julia Language's Array abstractions and KernelAbstractions to implement a single hardware- and data precision-agnostic function on NVIDIA, AMD, Intel, and Apple Metal GPUs for half, single, and double precision, and examine performance optimization across hardware architectures and data precision. We also develop a hardware-aware performance model and identify key hyperparameters, such as inner tilewidth and block concurrency, that govern optimal GPU execution for bandwidth-bound workloads. We demonstrate highly parallel bandwidth-bound algorithm on the GPU can outperform CPU-based implementations: the GPU algorithm outperforms multithreaded CPU High-Performance libraries PLASMA and SLATE as of matrix size 1024 x 1024 and by a factor over 100 for matrices of 32k x 32k. In addition, the performance of the algorithm increases linearly with matrix bandwidth size, making faster reduction of larger matrix bandwidths now also possible. With this work, we break memory bandwidth barriers, as well as matrix bandwidth barriers, resulting in orders-of-magnitude faster algorithms for the reduction of banded matrices to bidiagonal form on the GPU.
academic
GPU-резидентный алгоритм с учётом памяти для ускорения бидиагонализации ленточных матриц
В данной работе предлагается первый GPU-резидентный алгоритм с учётом памяти для ускорения приведения ленточных матриц к бидиагональной форме, что является критическим этапом в разложении по сингулярным значениям (SVD). Несмотря на высокую параллелизуемость алгоритма, ранее считалось, что он непригоден для GPU-вычислений из-за ограничений пропускной способности памяти. Развитие GPU-оборудования, в частности увеличение объёма L1-памяти на каждый потоковый мультипроцессор/вычислительный блок, изменило эту ситуацию. Авторы адаптировали предыдущий алгоритм bulge-chasing, эффективный по кэшу для многоядерных CPU, и оптимизировали его для пропускной способности GPU. Алгоритм реализован в виде единственной функции, независимой от оборудования и точности данных, на GPU NVIDIA, AMD, Intel и Apple Metal, поддерживающей вычисления с половинной, одинарной и двойной точностью. Экспериментальные результаты показывают, что GPU-алгоритм превосходит многопоточные CPU-библиотеки высокого производства PLASMA и SLATE начиная с матриц размером 1024×1024, а на матрицах размером 32k×32k достигает ускорения более чем в 100 раз.
Разложение по сингулярным значениям (SVD) является фундаментальным инструментом численных методов в научных вычислениях, машинном обучении и анализе данных, широко применяясь в анализе главных компонент, скрытом семантическом индексировании, низкоранговой аппроксимации и восполнении матриц. Современное SVD на крупномасштабном оборудовании обычно использует трёхэтапный процесс:
Приведение плотной матрицы к ленточной форме
Приведение ленточной матрицы к бидиагональной форме (bulge-chasing)
Приведение бидиагональной матрицы к диагональной форме
Хотя GPU-реализации первого и третьего этапов широко изучены, второй этап остаётся недостаточно исследованным на современных GPU. Dongarra и соавторы в 2014 году отметили, что «ускорители плохо справляются с обработкой мелкозернистых вычислительных задач, ограниченных памятью (таких как bulge chasing), что ограничивает потенциальные выгоды от GPU-реализации второго этапа».
Первый GPU-резидентный алгоритм bulge-chasing с учётом памяти: предложен первый нативный GPU-алгоритм для приведения ленточной матрицы к бидиагональной форме, полностью использующий превосходные характеристики памяти новейшего поколения высокопроизводительных GPU, обеспечивающий ускорение в 10-100 раз по сравнению с оптимизированными CPU-реализациями.
Стратегия кэш-эффективного bulge-chasing для матриц с большой полосой пропускания: благодаря новой кэш-эффективной стратегии постепенного сокращения полосы пропускания GPU-алгоритм может обрабатывать большие полосы пропускания, чем ранее, изменяя оптимальный компромисс полосы пропускания между первым и вторым этапами в крупномасштабном SVD.
Открытая реализация, независимая от оборудования и точности данных: библиотека с открытым исходным кодом, реализованная на основе абстракций языка Julia, с единственной функцией, поддерживающей вычисления с одинарной, половинной и двойной точностью на GPU NVIDIA, AMD, Intel и Apple.
Дана ленточная матрица A ∈ ℝⁿˣⁿ с полосой пропускания BW. Целью является приведение её к бидиагональной матрице B посредством ортогональных преобразований таким образом, чтобы A = UBVᵀ, где U и V — ортогональные матрицы.
Алгоритм 1: Приведение ленточной матрицы к бидиагональной форме
с использованием векторов Хаусхолдера
Входные данные: полоса пропускания BW, внутренняя ширина плитки TW, размер матрицы n
1: for сокращение полосы пропускания i = (BW-1)/TW → 1 do
2: целевая полоса пропускания TBW = 1 + i·TW
3: for параллельно: каждая строка R = 1→n do
4: bulge строки k = R
5: for каждый bulge строки: j = 0, j+=1 do
6: if 3(R-1) < j и k ≤ n then
7: вычислить вектор HH для строки k для исключения TW элементов
и применить к строкам ниже
8: вычислить вектор HH для самого левого порождённого bulge столбца
и применить к столбцам справа
9: обновить значение k
10: end if
11: end for
12: end for
13: end for
Алгоритм 2: GPU-ядро с учётом памяти, TPB потоков на блок
1: память потока: Ai (TW+1)
2: память блока: X (TW+1)
3: все потоки в блоке совместно: X ← A[k,..]
4: синхронизация потоков
5: все потоки в блоке совместно: HH(X)
6: все потоки в блоке совместно: A[k,..]← X
7: синхронизация потоков
8: for l: 0→(CBW + TW)/TPB - 1 do
9: поток i: вычислить строку r = k + l·CPB + i
10: Ai ← A[r, ...]
11: HH(X, Ai)
12: A[r, ...]← Ai
13: end for
Матрица разбивается на плитки полосы пропускания, приведение выполняется по последовательным блокам полосы пропускания, а не за один раз для всей полосы. Эта стратегия разбиения обеспечивает:
Введён параметр Max blocks, ограничивающий количество одновременных блоков потоков на каждый исполнительный блок GPU. Когда количество требуемых блоков bulge-chasing превышает лимит, применяется развёртывание цикла на уровне программного обеспечения, при котором один блок получает несколько задач и выполняет их последовательно в рамках одного запуска ядра.
Для обеспечения корректности и включения параллелизма алгоритм принудительно применяет трёхциклову развязку между последовательными сканированиями строк. То есть после завершения трёх bulge строк следующая строка может начать сканирование без перекрытия доступа к данным.
В отличие от решателей SVD, двухэтапные решатели для симметричных ленточных задач собственных значений на гибридных CPU-GPU системах имеют обширную литературу, однако исследования несимметричного приведения ленточной матрицы к бидиагональной форме отстают.
Первоначально предложен как параллельный алгоритм, но исследования случая бидиагональной матрицы на CPU крайне редки. В сравнении, исследования bulge-chasing для симметричного приведения ленточной матрицы к трёхдиагональной форме и верхней форме Хессенберга более обширны.
Преодоление барьера пропускной способности памяти: доказано, что алгоритмы линейной алгебры, ограниченные памятью, не только осуществимы на современных GPU, но и могут значительно превосходить производительность CPU
Важность характеристик оборудования: отношение задержки L1/L2-кэша к размеру более критично, подчёркивая важность низколатентного быстрого доступа к памяти
Принципы проектирования алгоритмов: оптимальная производительность достигается благодаря принципиальному проектированию алгоритмов, параметризации с учётом кэша и переносимой инфраструктуре компилятора
Модель занятости GPU: алгоритм имеет значительно меньше блоков GPU на начальных этапах, чем доступных исполнительных блоков, требуя достаточно больших матриц для полного использования ресурсов GPU
Переполнение регистров: высокая внутренняя ширина плитки может привести к переполнению регистров, влияя на производительность
Зависимость от оборудования: значительные различия в производительности между различными архитектурами GPU требуют аппаратно-специфической настройки
Статья цитирует 86 соответствующих источников, охватывающих GPU-вычисления, алгоритмы линейной алгебры, экосистему языка Julia и другие важные работы в различных областях, обеспечивая прочную теоретическую основу для исследования.