Кто-нибудь знает, какой алгоритм 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 обрабатывается на каждом шаге алгоритма. Вы можете видеть, как умножение матричной матрицы работает только на небольших блоках матрицы за раз и повторно использует каждый из этих блоков несколько раз, так что количество раз, которое данные должны быть сдвинуты в и из локальной памяти, сведено к минимуму.