在 F# 中并行化两个矩阵的元素乘法

发布于 2024-09-04 00:06:31 字数 566 浏览 6 评论 0原文

我正在尝试并行化 F# 中两个矩阵的逐元素乘法。我实在想不通。我一直尝试创建任务,但它永远不想编译。我的非工作混乱代码如下:

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 m n ]
  let parallelTasks = Async.Parallel operations
  Async.RunSynchronously parallelTasks
  result

I'm trying to parallelize the element by element multiplication of two matrices in F#. I can't quite figure it out thought. I keep trying to create tasks but it never wants to compile. My non-working messy code is the following:

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 m n ]
  let parallelTasks = Async.Parallel operations
  Async.RunSynchronously parallelTasks
  result

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

于我来说 2024-09-11 00:06:31

你犯了几个小错误,例如,你没有弄清楚如何进行矩阵乘法。

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 m n} ]
  let parallelTasks = Async.Parallel operations
  Async.RunSynchronously parallelTasks |> ignore
  result

需要注意的一件事是,此代码的性能会非常糟糕,因为 m.[i,j] 是访问矩阵中元素的低效方法。你最好使用二维数组:

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 m n} ]
  let parallelTasks = Async.Parallel operations
  Async.RunSynchronously parallelTasks |> ignore
  result

测试:

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

一些计时:

> myBigElemMultiply A B;;
Real: 00:00:22.111, CPU: 00:00:41.777, GC gen0: 0, gen1: 0, gen2: 0
val it : unit = ()
> myBigElemMultiply2 A B;;
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 = ()
> 

检查 这里使用ParallelFor,它应该比异步有更好的性能。

You have made several small mistakes, e.g., you haven't figured how to do 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 m n} ]
  let parallelTasks = Async.Parallel operations
  Async.RunSynchronously parallelTasks |> ignore
  result

One thing to notice is that this code would perform very badly because m.[i,j] is an inefficient way to access elements in a matrix. You'd 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 m n} ]
  let parallelTasks = Async.Parallel operations
  Async.RunSynchronously parallelTasks |> ignore
  result

testing:

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

some timing:

> myBigElemMultiply A B;;
Real: 00:00:22.111, CPU: 00:00:41.777, GC gen0: 0, gen1: 0, gen2: 0
val it : unit = ()
> myBigElemMultiply2 A B;;
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 by using ParallelFor, which should have a better performance than async.

难忘№最初的完美 2024-09-11 00:06:31

这里至少有一些可以编译的代码,也许这会让您朝着正确的方向前进?

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 m n ] 
    let parallelTasks = Async.Parallel operations 
    Async.RunSynchronously parallelTasks |> ignore
    result 

Here's at least some code that compiles, perhaps this will get you headed 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 m n ] 
    let parallelTasks = Async.Parallel operations 
    Async.RunSynchronously parallelTasks |> ignore
    result 
国产ˉ祖宗 2024-09-11 00:06:31

没有意义。一对矩阵的异地逐元素乘法与复制没什么区别,此时单个核心将愉快地最大化机器的整个内存带宽,并且添加更多核心不会提高性能。所以这几乎肯定是浪费时间。

There's no point. Out-of-place element-wise multiplication of a pair of matrices is little more that copying at which point a single core will happily max out the entire memory bandwidth of your machine and adding more cores will not improve performance. So it is almost certainly a waste of time.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文