Сложность времени умножения матрицы в MATLAB

Кто-нибудь знает, какой алгоритм MATLAB использует для умножения матриц и какова его временная сложность?

Ответ 1

Для полноты - как упоминалось в этот поток, Matlab использует DGEMM (двойное масштабирование матриц с помощью мыши) из BLAS (базовые подпрограммы линейной алгебры).

Обратите внимание, что нет единой реализации BLAS - она ​​настроена для конкретных архитектур процессора. Поэтому вы не можете быть абсолютно уверены, какой алгоритм используется на вашем компьютере, не выясняя, какая версия BLAS используется.

Спецификация BLAS определяет входы и выходные данные каждой подпрограммы и обеспечивает допустимые границы ошибок для вывода каждой подпрограммы. Реализации могут использовать любой алгоритм, который им нравится, поскольку они следуют спецификации.

Эталонная реализация BLAS использует алгоритм умножения блочной матрицы в DGEMM, который имеет временную сложность O (n ^ 3) для умножения две nxn-матрицы. Я считаю разумным предположить, что большинство реализаций BLAS будут более или менее соответствовать эталонной реализации.

Обратите внимание, что он не использует алгоритм наивного матричного умножения

for i = 1:N
    for j = 1:N
        for k = 1:N
            c(i,j) = c(i,j) + a(i,k) * b(k,j);
        end
    end
end

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

Существуют асимптотически более быстрые алгоритмы умножения матрицы, например алгоритм Strassen или алгоритм Coppersmith-Winograd, который имеет немного более высокую скорость, чем O (n ^ 3). Тем не менее, они, как правило, не учитывают кеш и игнорируют локальность, а это означает, что данные постоянно нужно обходить в памяти, поэтому для большинства современных архитектур общий алгоритм на самом деле медленнее, чем алгоритм оптимизации с оптимизацией блочной матрицы.

Википедические заметки о том, что алгоритм Штрассена может обеспечить ускорение для одного ядра ЦП для матричных размеров более нескольких тысяч, однако ускорение, вероятно, составит около 10% или около того, а разработчики BLAS, вероятно, не считают это стоящим для этого редкого случая (говоря, что эта статья от 1996 г. утверждает, что увеличение скорости примерно на 10% выше DGEMM для n выше примерно 200 - - хотя я не знаю, как это устаревает). С другой стороны, алгоритм Coppersmith-Winograd "дает только преимущество для столь больших матриц, что они не могут обрабатываться современным оборудованием".

Итак, ответ заключается в том, что Matlab использует наивный, но эффективный и кэш-алгоритм, чтобы получить его стремительное быстрое умножение матрицы.


Я обновил этот ответ, создав несколько видеороликов, демонстрирующих местность алгоритма умножения матрицы блоков, по сравнению с наивным алгоритмом.

В каждом из следующих видео мы визуализируем умножение двух матриц 8x8 A и B для создания продукта C= A x B. Желтая подсветка указывает, какой элемент в каждой из матриц A, B и C обрабатывается на каждом шаге алгоритма. Вы можете видеть, как умножение матричной матрицы работает только на небольших блоках матрицы за раз и повторно использует каждый из этих блоков несколько раз, так что количество раз, которое данные должны быть сдвинуты в и из локальной памяти, сведено к минимуму.