Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

[ООП] / Лекции / Lecture_8

.pdf
Скачиваний:
35
Добавлен:
07.02.2016
Размер:
205.87 Кб
Скачать

Лекция 8

Умножение матриц

Пусть даны матрица А размерностью m×q и матрица B размерностью q×n. Напомним, если число столбцов матрицы А равно числу строк матрицы В, то эти матрицы называются согласованными. Пусть для примера m=3, q=2, n=2, тогда произведение матрицы А на В запишется в виде

a11

C = AB = a21

a31

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

a12 b11 a22 a32 b21

b

 

a11b11

+a12b21

12

 

= a21b11

+a22b21

b22

 

b

+a

 

b

a

32

 

 

 

31 11

 

21

a11b12 +a12b22 a21b12 +a22b22 a31b12 +a32b22

a =[a ,a

], a =[a ,a

];

 

=[b ,b ]T ,

 

=[b ,b

]T .

b

b

1

11

12

2

21

22

1

11

21

2

12

22

С учетом этих обозначений произведение матриц можно представить в виде:

a1

 

 

 

 

 

 

 

 

 

(a1,

 

 

 

 

 

[

 

 

 

 

]=

b1), (a1,

b2 )

 

C = AB = a

 

 

 

 

 

,

 

(a

 

 

,

 

), (a

 

,

 

 

)

,

2

b

b

2

b

2

b

 

 

 

1 2

 

 

 

 

 

 

 

1

 

2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

a3

 

 

 

 

 

 

 

 

(a3

, b1), (a3 , b2 )

 

или в общем случае

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(a1

, b1),K, (a1, bn )

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

C = AB =

 

 

 

 

 

 

 

 

 

L

 

 

 

 

 

 

 

 

 

 

 

,

 

 

 

 

 

 

(a

 

 

,

 

),K, (a

 

 

,

 

 

 

 

)

 

 

 

 

 

 

 

m

b

m

b

n

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

q

где (ai b j ) = aik bkj - скалярное произведение векторов.

k =1

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

При реализации на обычной последовательной машине код на языке С может быть та-

ким:

for(i=0;i<m;i++)

(1a)

for(j=0;j<n;j++)

for(k=0;k<q;k++)

 

с[i][j]=c[i][j]+a[i][k]*b[k][j];

 

Такая реализация произведения матриц называется методом внутренних произведений. Последовательность вычисления произведений компонентов векторов для нашего примера условно можно изобразить так:

1

2

3

4

 

 

6

7

8

 

5

.

 

10

11

 

 

9

12

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

Для него в алгоритме (1а) переставим местами циклы по i и j, т.е.

2

for(j=0;j<n;j++)

(2a)

for(i=0;i<m;i++)

for(k=0;k<q;k++)

 

с[i][j]=c[i][j]+a[i][k]*b[k][j];

 

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

1

2

7

8

 

4

9

 

3

10 .

 

6

11

 

5

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 j2a j ) , действительно:

 

 

 

 

j =1

j =1

 

 

a11

 

 

 

 

 

C = AB = b

a

21

 

+b

 

11

 

 

21

 

 

 

 

 

 

 

a31

 

 

 

 

 

 

 

 

a

 

 

 

a

 

 

a

 

 

 

12

 

 

 

11

 

 

12

 

 

 

a

22

 

,

b

a

21

 

+b

a

22

 

, или, обобщая

 

 

 

12

 

 

22

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

a32

 

 

 

a31

 

 

a32

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

q

q

C = AB = (b j1a j ,Kb 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

 

5

8

 

2

11

 

6

9

 

3

12

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

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

a1 =[a11, a21] , a2 =[a21, a22 ] , a3 =[a31, a32 ] ; b1 =[b11,b12 ] , b2 =[b21,b22 ] .

Тогда:

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

3

 

 

 

 

2

 

 

 

 

 

 

 

 

 

 

 

a1 j

 

 

 

j

 

 

 

b

 

a B

 

 

 

 

 

 

 

 

 

 

 

j =1

 

 

 

 

 

1

 

 

 

2

 

 

 

 

 

 

 

, или для общего случая

 

 

 

 

 

 

C = AB = a2 B =

a2 jb j

 

 

j =1

 

 

 

 

 

a3B

 

 

2

 

 

 

 

 

 

 

 

 

 

 

a3 j

b

j

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

j =1

 

 

 

 

 

 

 

 

 

n

 

 

 

 

 

 

 

a B

 

 

a1 j

b

j

 

1

 

 

j=1

 

 

 

 

 

 

C = AB = L

 

=

 

L

 

 

 

 

 

.

 

 

 

 

n

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

amj b j

 

am B

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

 

7

6

8

 

5

 

 

11

10

 

 

9

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

 

8

5

 

2

11

 

9

6

 

3

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

 

9

4

 

3

10

 

11

6

 

5

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. Разобьем

матрицу из n2

элементов на блоки размерности

n

×

n

, т.е. в каждом блоке будет по

n2

элементов. Обозначим блоки таким образом:

P

P

P

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

a0,0

 

 

a0,1

...

 

a

0,

 

n

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

P

 

 

 

 

 

 

 

 

a

 

 

 

a

 

...

 

a

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

n

 

 

 

 

 

 

 

A

 

1,0

 

 

1,1

 

 

 

1,

 

1

 

 

,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

P

 

 

 

 

=

...

 

 

...

...

 

 

 

 

 

 

 

 

 

 

 

 

0,0

 

 

 

 

 

 

 

 

...

 

 

 

 

 

 

 

 

 

 

a n

 

a n

 

...

a n

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1,0

1,1

 

1,

 

n

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

P

 

 

P

 

 

 

 

 

P

 

 

 

 

 

 

 

 

 

 

 

 

 

P

 

 

 

 

 

или для примера, взяв матрицу размерностью 9 ×9 и число процессоров, равное 9, можем, таким образом разбить матрицы на блоки:

 

 

a0,0

a0,1

a0,2

 

 

a0,3

a0,4

a0,5

 

 

A

=

a

a

a

 

, A

=

a

a

a

 

и.д.

0,0

 

 

1,0

 

1,1

 

1,2

0,1

 

 

1,3

 

1,4

 

1,5

 

 

 

 

a

2,0

a

2,1

a

 

 

 

 

a

2,3

a

2,4

a

2,5

 

 

 

 

 

 

 

2,2

 

 

 

 

 

 

 

 

 

b0,0

b0,1

b0,2

 

 

 

 

 

 

 

 

 

 

 

B

=

b

b

 

b

 

 

и т.д.

 

 

 

 

 

 

 

 

 

0,0

 

1,0

1,1

1,2

 

 

 

 

 

 

 

 

 

 

 

 

 

b

 

b

 

b

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2,0

2,1

2,2

 

 

 

 

 

 

 

 

 

 

 

Тогда исходные матрицы A и B запишутся в блочном виде:

 

A0,0

A0,1

A0,2

 

 

 

B0,0

B0,1

B0,2

 

A =

A

A

A

 

,

B =

B

B

B

.

 

1,0

1,1

1,2

 

 

 

1,0

1,1

1,2

 

 

A

A

A

 

 

 

B

B

B

 

 

2,0

2,1

2,2

 

 

 

2,0

2,1

2,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

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

Соседние файлы в папке Лекции