Parallelization of elementary multiplication of two matrices in F #

I am trying to parallelize an element by multiplying the elements by two matrices in F #. I can’t figure it out. I keep trying to create tasks, but he never wants to compile. My inoperative messy code looks like this:

let myBigElemMultiply (m:matrix) (n:matrix) = let AddTwoRows (row:int) (destination:matrix) (source1:matrix) (source2:matrix) = for i in 0 .. destination.NumCols destination.[row, i] <- source1.[row,i] + source2.[row,i] destination let result = Matrix.zero(m.NumRows) let operations = [ for i in 0 .. m.NumRows -> AddTwoRows i result mn ] let parallelTasks = Async.Parallel operations Async.RunSynchronously parallelTasks result 
+4
source share
3 answers

You made some small mistakes, for example, you did not understand how to perform matrix multiplication.

 let myBigElemMultiply (m:matrix) (n:matrix) = let AddTwoRows (row:int) (destination:matrix) (source1:matrix) (source2:matrix) = for col=0 to destination.NumCols-1 do let mutable sum = 0.0 for k=0 to m.NumCols-1 do sum <- sum + source1.[row,k] * source2.[k,col] destination.[row,col] <- sum let result = Matrix.zero m.NumRows n.NumCols let operations = [ for i=0 to m.NumRows-1 do yield async { AddTwoRows i result mn} ] let parallelTasks = Async.Parallel operations Async.RunSynchronously parallelTasks |> ignore result 

It should be noted that this code will work very poorly, because m.[i,j] is an inefficient way to access the elements in the matrix. You better use a 2D array:

 let myBigElemMultiply2 (m:matrix) (n:matrix) = let AddTwoRows (row:int) (destination:matrix) (source1:matrix) (source2:matrix) = let destination = destination.InternalDenseValues let source1 = source1.InternalDenseValues let source2 = source2.InternalDenseValues for col=0 to Array2D.length2 destination - 1 do let mutable sum = 0.0 for k=0 to Array2D.length1 source2 - 1 do sum <- sum + source1.[row,k] * source2.[k,col] destination.[row,col] <- sum let result = Matrix.zero m.NumRows n.NumCols let operations = [ for i=0 to m.NumRows-1 do yield async { AddTwoRows i result mn} ] let parallelTasks = Async.Parallel operations Async.RunSynchronously parallelTasks |> ignore result 

Testing:

 let r = new Random() let A = Matrix.init 280 10340 (fun ij -> r.NextDouble() ) let B = A.Transpose 

some time:

 > myBigElemMultiply AB;; Real: 00:00:22.111, CPU: 00:00:41.777, GC gen0: 0, gen1: 0, gen2: 0 val it : unit = () > myBigElemMultiply2 AB;; Real: 00:00:08.736, CPU: 00:00:15.303, GC gen0: 0, gen1: 0, gen2: 0 val it : unit = () > A*B;; Real: 00:00:13.635, CPU: 00:00:13.166, GC gen0: 0, gen1: 0, gen2: 0 val it : unit = () > 

Check here using ParallelFor, which should have better performance than asynchronous.

+4
source

Here, at least, is some code that compiles, maybe this will lead you in the right direction?

 let myBigElemMultiply (m:matrix) (n:matrix) = let AddTwoRows (row:int) (destination:matrix) (source1:matrix) (source2:matrix) = async { for i in 0 .. destination.NumCols do destination.[row, i] <- source1.[row,i] + source2.[row,i] } let result = Matrix.zero m.NumRows m.NumCols let operations = [ for i in 0 .. m.NumRows -> AddTwoRows i result mn ] let parallelTasks = Async.Parallel operations Async.RunSynchronously parallelTasks |> ignore result 
+2
source

It makes no sense. Extra-segment multiplication of a pair of matrices is a bit more than copying, in which one core will gladly use the entire memory bandwidth of your computer to the maximum, and adding more kernels will not improve performance. So it's almost certainly a waste of time.

+1
source

Source: https://habr.com/ru/post/1311811/


All Articles