Хорошей отправной точкой является прекрасная книга Роберта А. ван де Гейна и Энрике С. Кинтана-Орти «Наука о программировании матричных вычислений ». Они предоставляют бесплатную версию для загрузки.
BLAS разделен на три уровня:
Уровень 1 определяет набор функций линейной алгебры, которые работают только с векторами. Эти функции выигрывают от векторизации (например, от использования SSE).
Функции уровня 2 - это операции матрица-вектор, например, некоторое произведение матрица-вектор. Эти функции могут быть реализованы в виде функций Уровня 1. Однако вы можете повысить производительность этих функций, если можете предоставить специальную реализацию, которая использует некоторую многопроцессорную архитектуру с общей памятью.
Функции уровня 3 - это операции, подобные произведению матрицы на матрицу. Опять же, вы можете реализовать их в терминах функций Level2. Но функции Level3 выполняют O (N ^ 3) операций с данными O (N ^ 2). Поэтому, если ваша платформа имеет иерархию кеша, вы можете повысить производительность, если предоставите специальную реализацию, оптимизированную для кеширования / дружественную кеш-памяти . Это прекрасно описано в книге. Основным преимуществом функций Level3 является оптимизация кеша. Это повышение значительно превышает второе повышение от параллелизма и других аппаратных оптимизаций.
Кстати, большинство (или даже все) высокопроизводительных реализаций BLAS НЕ реализованы на Фортране. ATLAS реализован на C. GotoBLAS / OpenBLAS реализован на C, а его критические для производительности части - на Assembler. В Фортране реализована только эталонная реализация BLAS. Однако все эти реализации BLAS предоставляют интерфейс Fortran, так что он может быть связан с LAPACK (LAPACK получает всю свою производительность от BLAS).
Оптимизированные компиляторы играют второстепенную роль в этом отношении (а для GotoBLAS / OpenBLAS компилятор вообще не имеет значения).
ИМХО ни одна реализация BLAS не использует такие алгоритмы, как алгоритм Копперсмита – Винограда или алгоритм Штрассена. Я не совсем уверен в причине, но это мое предположение:
- Возможно, невозможно обеспечить реализацию этих алгоритмов, оптимизированную для кеширования (т.е. вы потеряете больше, чем выиграете)
- Эти алгоритмы численно нестабильны. Поскольку BLAS является вычислительным ядром LAPACK, это недопустимо.
Изменить / обновить:
Новым и новаторским документом по этой теме являются документы BLIS . Они исключительно хорошо написаны. Для моей лекции «Основы программного обеспечения для высокопроизводительных вычислений» я реализовал матрично-матричное произведение после их статьи. Фактически я реализовал несколько вариантов матричного произведения. Простейшие варианты полностью написаны на простом C и содержат менее 450 строк кода. Все остальные варианты просто оптимизируют циклы.
for (l=0; l<MR*NR; ++l) {
AB[l] = 0;
}
for (l=0; l<kc; ++l) {
for (j=0; j<NR; ++j) {
for (i=0; i<MR; ++i) {
AB[i+j*MR] += A[i]*B[j];
}
}
A += MR;
B += NR;
}
Общая производительность матричного продукта зависит только от этих циклов. Здесь проводится около 99,9% времени. В других вариантах я использовал встроенные функции и код ассемблера для повышения производительности. Вы можете увидеть, как в руководстве рассматриваются все варианты здесь:
ulmBLAS: Учебник по GEMM (матрично-матричный продукт)
Вместе с документами BLIS становится довольно легко понять, как библиотеки, такие как Intel MKL, могут добиться такой производительности. И почему не имеет значения, используете ли вы основное хранилище строк или столбцов!
Вот и финальные тесты (мы назвали наш проект ulmBLAS):
Тесты для ulmBLAS, BLIS, MKL, openBLAS и Eigen
Другое редактирование / обновление:
Я также написал учебник о том, как BLAS используется для решения задач численной линейной алгебры, таких как решение системы линейных уравнений:
Факторизация LU с высокими характеристиками
(Эта факторизация LU, например, используется Matlab для решения системы линейных уравнений.)
Я надеюсь найти время, чтобы расширить руководство, чтобы описать и продемонстрировать, как реализовать хорошо масштабируемую параллельную реализацию факторизации LU, как в PLASMA .
Хорошо, вот и все: кодирование оптимизированной для кэша параллельной факторизации LU
PS: Я также провел несколько экспериментов по повышению производительности uBLAS. На самом деле повысить (да, игра словами :)) производительность uBLAS довольно просто:
Эксперименты на uBLAS .
Вот похожий проект с BLAZE :
Эксперименты на BLAZE .