Matrix multiplication: Difference between revisions
Content added Content deleted
m (→[[Matrix multiplication#ELLA]]: move to E section.) |
m (→[[Matrix multiplication#ALGOL 68]]: use BOLD as per specification.) |
||
Line 142: | Line 142: | ||
Alternatively, for multicore CPUs, the following recursive algorithm can be used: |
Alternatively, for multicore CPUs, the following recursive algorithm can be used: |
||
'''int''' default upb := 3; |
|||
'''mode''' '''field''' = '''long''' '''real'''; |
|||
'''mode''' '''vector''' = [default upb]'''field'''; |
|||
'''mode''' '''matrix''' = [default upb, default upb]'''field'''; |
|||
¢ crude exception handling ¢ |
¢ crude exception handling ¢ |
||
'''proc''' '''void''' raise index error := '''void''': '''goto''' exception index error; |
|||
'''sema''' idle cpus = '''level''' ( 8 - 1 ); ¢ 8 = number of CPU cores minus parent CPU ¢ |
|||
¢ define an operator to slice array into quarters ¢ |
¢ define an operator to slice array into quarters ¢ |
||
'''op''' '''top''' = ('''matrix''' m)'''int''': ( ⌊m + ⌈m ) %2, |
|||
'''bot''' = ('''matrix''' m)'''int''': '''top''' m + 1, |
|||
'''left''' = ('''matrix''' m)'''int''': ( 2 ⌊m + 2 ⌈m ) %2, |
|||
'''right''' = ('''matrix''' m)'''int''': '''left''' m + 1, |
|||
'''left''' = ('''vector''' v)'''int''': ( ⌊v + ⌈v ) %2, |
|||
'''right''' = ('''vector''' v)'''int''': '''left''' v + 1; |
|||
'''prio''' '''top''' = 8, '''bot''' = 8, '''left''' = 8, '''right''' = 8; ¢ Operator priority - same as LWB & UPB ¢ |
|||
'''op''' × = ('''vector''' a, b)'''field''': ( ¢ dot product ¢ |
|||
'''if''' (⌊a, ⌈a) ≠ (⌊b, ⌈b) '''then''' raise index error '''fi'''; |
|||
'''if''' ⌊a = ⌈a '''then''' |
|||
a[⌈a] × b[⌈b] |
a[⌈a] × b[⌈b] |
||
'''else''' |
|||
'''field''' begin, end; |
|||
[] |
[]'''proc''' '''void''' schedule=( |
||
'''void''': begin:=a[:'''left''' a] × b[:'''left''' b], |
|||
'''void''': end :=a['''right''' a:] × b['''right''' b:] |
|||
); |
); |
||
'''if''' '''level''' idle cpus = 0 '''then''' ¢ use current CPU ¢ |
|||
'''for''' thread '''to''' ⌈schedule '''do''' schedule[thread] '''od''' |
|||
'''else''' |
|||
'''par''' ( ¢ run vector in parallel ¢ |
|||
schedule[1], ¢ assume parent CPU ¢ |
schedule[1], ¢ assume parent CPU ¢ |
||
( ↓idle cpus; schedule[2]; ↑idle cpus) |
( ↓idle cpus; schedule[2]; ↑idle cpus) |
||
) |
) |
||
'''fi'''; |
|||
begin+end |
begin+end |
||
'''fi''' |
|||
); |
); |
||
'''op''' × = ('''matrix''' a, b)'''matrix''': ¢ matrix multiply ¢ |
|||
'''if''' (⌊a, 2 ⌊b) = (⌈a, 2 ⌈b) '''then''' |
|||
a[⌊a, ] × b[, 2 ⌈b] ¢ dot product ¢ |
a[⌊a, ] × b[, 2 ⌈b] ¢ dot product ¢ |
||
'''else''' |
|||
[⌈a, 2 ⌈b] |
[⌈a, 2 ⌈b] '''field''' out; |
||
'''if''' (2 ⌊a, 2 ⌈a) ≠ (⌊b, ⌈b) '''then''' raise index error '''fi'''; |
|||
[] |
[]'''struct'''('''bool''' required, '''proc''' '''void''' thread) schedule = ( |
||
( |
( '''true''', ¢ calculate top left corner ¢ |
||
'''void''': out[:'''top''' a, :'''left''' b] := a[:'''top''' a, ] × b[, :'''left''' b]), |
|||
( ⌊a ≠ ⌈a, ¢ calculate bottom left corner ¢ |
( ⌊a ≠ ⌈a, ¢ calculate bottom left corner ¢ |
||
'''void''': out['''bot''' a:, :'''left''' b] := a['''bot''' a:, ] × b[, :'''left''' b]), |
|||
( 2 ⌊b ≠ 2 ⌈b, ¢ calculate top right corner ¢ |
( 2 ⌊b ≠ 2 ⌈b, ¢ calculate top right corner ¢ |
||
'''void''': out[:'''top''' a, '''right''' b:] := a[:'''top''' a, ] × b[, '''right''' b:]), |
|||
( (⌊a, 2 ⌊b) ≠ (⌈a, 2 ⌈b) , ¢ calculate bottom right corner ¢ |
( (⌊a, 2 ⌊b) ≠ (⌈a, 2 ⌈b) , ¢ calculate bottom right corner ¢ |
||
'''void''': out['''bot''' a:, '''right''' b:] := a['''bot''' a:, ] × b[, '''right''' b:]) |
|||
); |
); |
||
'''if''' '''level''' idle cpus = 0 '''then''' ¢ use current CPU ¢ |
|||
'''for''' thread '''to''' ⌈schedule '''do''' (required →schedule[thread] | thread →schedule[thread] ) '''od''' |
|||
'''else''' |
|||
'''par''' ( ¢ run vector in parallel ¢ |
|||
thread →schedule[1], ¢ thread is always required, and assume parent CPU ¢ |
thread →schedule[1], ¢ thread is always required, and assume parent CPU ¢ |
||
( required →schedule[4] | ↓idle cpus; thread →schedule[4]; ↑idle cpus), |
( required →schedule[4] | ↓idle cpus; thread →schedule[4]; ↑idle cpus), |
||
Line 209: | Line 209: | ||
( required →schedule[2] | ↓idle cpus; thread →schedule[2]; ↑idle cpus) |
( required →schedule[2] | ↓idle cpus; thread →schedule[2]; ↑idle cpus) |
||
) |
) |
||
'''fi'''; |
|||
out |
out |
||
'''fi'''; |
|||
'''format''' real fmt = $g(-6,2)$; ¢ width of 6, with no '+' sign, 2 decimals ¢ |
|||
'''proc''' real matrix printf= ('''format''' real fmt, '''matrix''' m)'''void''':( |
|||
'''format''' vector fmt = $"("n(2 ⌈m-1)(f(real fmt)",")f(real fmt)")"$; |
|||
'''format''' matrix fmt = $x"("n(⌈m-1)(f(vector fmt)","lxx)f(vector fmt)");"$; |
|||
¢ finally print the result ¢ |
¢ finally print the result ¢ |
||
printf((matrix fmt,m)) |
printf((matrix fmt,m)) |
||
Line 222: | Line 222: | ||
¢ Some sample matrices to test ¢ |
¢ Some sample matrices to test ¢ |
||
'''matrix''' a=((1, 1, 1, 1), ¢ matrix A ¢ |
|||
(2, 4, 8, 16), |
(2, 4, 8, 16), |
||
(3, 9, 27, 81), |
(3, 9, 27, 81), |
||
(4, 16, 64, 256)); |
(4, 16, 64, 256)); |
||
'''matrix''' b=(( 4 , -3 , 4/3, -1/4 ), ¢ matrix B ¢ |
|||
(-13/3, 19/4, -7/3, 11/24), |
(-13/3, 19/4, -7/3, 11/24), |
||
( 3/2, -2 , 7/6, -1/4 ), |
( 3/2, -2 , 7/6, -1/4 ), |
||
( -1/6, 1/4, -1/6, 1/24)); |
( -1/6, 1/4, -1/6, 1/24)); |
||
'''matrix''' c = a × b; ¢ actual multiplication example of A x B ¢ |
|||
print((" A x B =",new line)); |
print((" A x B =",new line)); |
||
real matrix printf(real fmt, c) |
real matrix printf(real fmt, c). |
||
exception index error: |
exception index error: |