Вы находитесь на странице: 1из 6

Лекция 8

Умножение матриц
Пусть даны матрица А размерностью m×q и матрица B размерностью q×n. Напомним,
если число столбцов матрицы А равно числу строк матрицы В, то эти матрицы называются
согласованными. Пусть для примера m=3, q=2, n=2, тогда произведение матрицы А на В за-
пишется в виде
 a11 a12  a b + a b a11b12 + a12b22 
   b11 b12   11 11 12 21
C = AB = a21 a22  = a21b11 + a22b21 a21b12 + a22b22 
  b21 b22   
a31 a32  a31b11 + a32b21 a31b12 + a32b22 
Введём обозначения:

a1 = [a11, a12 ], a2 = [a21, a22 ]; b1 = [b11, b21]T , b2 = [b12, b22 ]T .


С учетом этих обозначений произведение матриц можно представить в виде:
 a1   (a1 , b1 ), (a1 , b2 )
  [ ] 
C = AB = a2  ⋅ b1 , b2 = (a 2 , b1 ), (a2 , b2 ) ,
 a3   (a3 , b1 ), (a3 , b2 )
 
или в общем случае
 (a1 , b1 ), K , (a1 , bn ) 
 
C = AB =  L ,
(a m , b1 ), K , (a m , bn )
 
q
где (a i b j ) = ∑ aik bkj - скалярное произведение векторов.
k =1
Идеальный случай для реализации данного алгоритма - если матрица А размещается в
памяти по строкам, а матрица В - по столбцам, и в векторной машине аппаратно реализована
операция скалярного умножения векторов.
При реализации на обычной последовательной машине код на языке С может быть та-
ким:
for(i=0;i<m;i++)
for(j=0;j<n;j++) (1a)
for(k=0;k<q;k++)
с[i][j]=c[i][j]+a[i][k]*b[k][j];

Такая реализация произведения матриц называется методом внутренних произведений. По-


следовательность вычисления произведений компонентов векторов для нашего примера ус-
ловно можно изобразить так:
1 2 3 4 
5 6 7 8  .
 
9 10 11 12

Существует аналогичный этому метод: двойственный метод внутренних произведений.


Для него в алгоритме (1а) переставим местами циклы по i и j, т.е.
2
for(j=0;j<n;j++)
for(i=0;i<m;i++) (2a)
for(k=0;k<q;k++)
с[i][j]=c[i][j]+a[i][k]*b[k][j];

А последовательность вычисления произведений компонентов векторов будет такой:


1 2 7 8 
3 4 9 10 .
 
5 6 11 12

Рассмотрим другой алгоритм, который называется методом средних произведений.


Введем обозначения:

a1 = [a11 , a21 , a31 ]T , a2 = [a12 , a22 , a32 ]T , b1 = [b11 , b21 ]T , b21 = [b12 , b22 ]T .
2 2
Тогда можем записать C = AB = ( Ab1 , Ab2 ) = ( ∑ b j1a j , ∑ b j 2 a j ) , действительно:
j =1 j =1
 
  a11   a12   a11   a12  
C = AB = b11 ⋅ a21  + b21 ⋅ a22  ,
   b12 ⋅ a21  + b22 ⋅ a22   , или, обобщая
 
  a31   a32   a31   a32  
 
q q
C = AB = ( ∑ b j1a j , K∑ b jn a j )
j =1 j =1

Для последовательной машины алгоритм средних произведений выглядит так:


for(j=0;j<n;j++)
for(k=0;k<q;k++)
for(i=0;i<m;i++)
с[i][j]=c[i][j]+a[i][k]*b[k][j];

Последовательность вычисления произведений компонентов векторов будет следующей:


1 4 7 10
2 5 8 11
 
3 6 9 12

Этот алгоритм удобен при хранении матрицы А по столбцам.


Существует и его двойственный алгоритм средних произведений. Обозначим строки
матриц А и В следующим образом:

a1 = [a11 , a21 ] , a2 = [a21 , a22 ] , a3 = [a31 , a32 ] ; b1 = [b11 , b12 ] , b2 = [b21 , b22 ] .
Тогда:

Высокопроизводительные вычислительные системы и параллельное программирование. Кудерметов Р.К.


3

 2 
 ∑ a1 j b j 
 j =1 
 a1B   2 
  
C = AB = a2 B  =  ∑ a2 j b j  , или для общего случая
 a3 B   j =1 
 2 
 ∑ a3 j b j 
 j =1 

 n 
 ∑ a1 j b j 
 a1 B   j =1 

C = AB =  L  =   L .
 n 
a m B   a b 
 ∑ mj j 
 j =1 
Для последовательной машины этот алгоритм запишется в виде:
for(i=0;i<m;i++)
for(k=0;k<n;k++)
for(j=0;j<q;j++)
c[i][j]=c[i][j]+a[i][k]b[k][j];

Последовательность вычисления произведений:


1 3 2 4 
5 7 6 8 
 
9 11 10 12

Этот алгоритм эффективен, когда матрица В хранится по строкам.


Далее рассмотрим ещё одну модификацию алгоритма умножения матриц, который на-
зывается алгоритмом внешних произведений:
for(k=0;k<q;k++)
for(j=0;j<n;j++)
for(i=0;i<m;i++)
c[i][j]=c[i][j]+a[i][k]*b[k][j];

Последовательность вычислений:
1 7 4 10
2 8 5 11
 
3 9 6 12

Очевидно, этот способ выгоден при хранении матрицы А по столбцам, а порядок хра-
нения В не существенен.
И, наконец, двойственный алгоритм внешних произведений:
for(k=0;k<q;k++)
for(i=0;i<m;i++)
for(j=0;j<n;j++)
c[i][j]=c[i][j]+a[i][k]*b[k][j];

Высокопроизводительные вычислительные системы и параллельное программирование. Кудерметов Р.К.


4

1 7 2 8 
3 9 4 10
 
5 11 6 12

Этот алгоритм эффективен, если матрица В хранится по строкам.


Таким образом, мы рассмотрели шесть возможных алгоритмов умножения матриц.
Эффективность каждого из них будет определяться типом векторных или параллельных
компьютеров, реализацией компиляторов, размером матриц.
Рассмотрим более подробно возможные организации умножения матриц на параллель-
ных вычислительных системах. Не теряя общности предположим что матрицы, которые не-
обходимо умножить – квадратные. Гипотетический случай, когда число процессоров равно
числу элементов матрицы легко себе представить. Введем следующие обозначения для строк
матрицы A и столбцов матрицы B:

[ ] [ ] [ ] [ ]
a0 = a0,0 , a0,1,... , a1 = a1,0 , a1,1,... , ...; b0 = b0,0 , b0,1,... T , b1 = b0,1, b1,1,... T , ...,
Тогда можно построить распределение вычислений между процессорами, при котором каж-
дый процессор умножает скалярно строку матрицы A на столбец матрицы B (рис.8.1). В каж-
дом процессоре, таким образом, вычисляется один элемент результирующей матрицы C.
Предположим, что число процессоров равно, числу строк матрицы A, тогда, располо-
жив в каждом процессоре по строке этой матрицы и полностью матрицу B, получим вариант
когда в каждом процессоре вычисляется одна строка результирующей матрицы C (рис.8.2).

Рис. 8.1 Рис. 8.2

Аналогично можно построить схему, при которой число процессоров равно числу
столбцов матрицы B (рис.8.3). В этом случае в каждом процессоре должна быть расположена
вся матрица A и вычисляется один столбец матрицы C.
Если число процессоров меньше, чем число строк матрицы, то общее число строк раз-
делить на равные части по числу процессоров, тогда в каждом процессоре будет вычисляться
несколько строк матрицы C. (рис.8.4). Аналогично можно представить схему, при которой
столбцы матрицы B равномерно распределяются между процессорами, число которых мень-
ше числа столбцов.

Высокопроизводительные вычислительные системы и параллельное программирование. Кудерметов Р.К.


5

Рис. 8.3 Рис. 8.4

Рассмотрим теперь принципиально другой подход к умножению матриц – блочно-


ориентированный. Пусть множество процессоров образуют квадратную двумерную сетку и
число процессоров равно P. Разобьем матрицу из n 2 элементов на блоки размерности
n n n2
× , т.е. в каждом блоке будет по элементов. Обозначим блоки таким образом:
P P P

 a0,0 a0,1 ... a n 


 0, −1

P
 
 a1,0 a1,1 ... a n
1, −1 
A0,0 =  P ,
 ... ... ... ... 
 
 a n a n ... a n n 
−1,0 −1,1 −1, −1
 P P P P 

или для примера, взяв матрицу размерностью 9 × 9 и число процессоров, равное 9, можем,
таким образом разбить матрицы на блоки:
 a 0, 0 a0,1 a0,2  a0,3 a0,4 a0,5 
   
A0,0 =  a1,0 a1,1 a1,2  , A0,1 =  a1,3 a1,4 a1,5  и.д.
a2,0 a2,1 a2,2  a2,3 a2,4 a2,5 
 
b0,0 b0,1 b0,2 
 
B0,0 =  b1,0 b1,1 b1,2  и т.д.
b2,0 b2,1 b2,2 

Тогда исходные матрицы A и B запишутся в блочном виде:
 A0,0 A0,1 A0,2   B0,0 B0,1 B0,2 
   
A =  A1,0 A1,1 A1,2  , B =  B1,0 B1,1 B1,2  .
 A2,0 A2,1 A2,2   B2,0 B2,1 B2,2 
 
Очевидно, что произведение матриц A и B при их блочном представлении можно полу-
чить, умножая блоки согласно правилам умножения обычных матриц. Условно, пользуясь С-
подобной нотацией, можно записать алгоритм блочного умножения:

for(i=0;i< P ;i++)
for(j=0;j< P ;j++)
for(k=0;k< P ;k++)
Высокопроизводительные вычислительные системы и параллельное программирование. Кудерметов Р.К.
6

C[i][j]+=A[i][k]×B[k][j];

где знак умножения × представляет собой подпрограмму умножения обычных матриц, знак
суммирования – подпрограмму суммирования матриц, а C[i][j] – блоки матрицы С.
Схему вычисления произведения матриц представим в виде трех подсхем (рис.8.5).

А) б) в)
Рис. 8.5
Если три схемы (рис.8.5а, б, с) наложить на матрицу процессоров, которые выполняют
умножения подматриц параллельно, то очевидно, что каждый процессор должен содержать
соответствующую подматрицу Ai, j и строку подматриц Bi .
Известен алгоритм Канона (Cannon) [ ], для которого затраты памяти равны памяти, не-
обходимой только для хранение трех подматриц (рис.8.6).

a) б)

в) г)

Рис. 8.6

Высокопроизводительные вычислительные системы и параллельное программирование. Кудерметов Р.К.

Вам также может понравиться