2010-06-04 2 views
4

F #에서 두 행렬의 요소 곱셈을 통해 요소를 병렬 처리하려고합니다. 나는 그것을 생각할 수 없다. 나는 계속 작업을 만들려고 노력하지만 결코 컴파일하고 싶지 않습니다. 내 작동하지 않는 지저분한 코드는 다음과 같은 : 당신은, 예를 들어, 당신은 행렬 곱셈을 수행하는 방법을 생각하지 않은, 몇 가지 작은 실수를 한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 

답변

4

. 주목해야 할

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 

일부 타이밍 : ParallelFor를 사용하여

> 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 =() 
> 

확인 here, 비동기보다 더 나은 성능을 가져야한다.

+0

FWIW, 2D 배열도 액세스하기에 비효율적입니다 ... –

+1

OP는 실제로 요소 별 승산을 요구했습니다. 즉,. * 연산자가 수행하는 것이지, 내가 설명한 것으로 생각하는 행렬 - 행렬 곱셈이 아닙니다. –

2

컴파일하는 코드가 적어도 있습니다. 아마도 올바른 방향으로 나아갈 수 있습니까?

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 
1

아무런 의미가 없습니다. 하나의 코어가 기꺼이 머신의 전체 메모리 대역폭을 극대화하고 더 많은 코어를 추가하면 성능이 향상되지 않는다는 점에서, 한 쌍의 매트릭스를 요소 단위로 곱하면 좀 더 많습니다. 따라서 거의 확실한 시간 낭비입니다.