2010-03-22 5 views
4

나는 가속기 v2를 사용하여 F #에서 생명을 쓰려고 노력하고있다. 그러나 모든 이상한 이유로 나의 모든 배열이 사각형이긴하지만 정사각형이 아니다. 행렬의 왼쪽 상단이 false로 설정됩니다. 모든 작업이 전체 배열을 동일하게 처리해야하므로 어떻게 될지 잘 모르겠습니다. 어떤 아이디어? 로버트가 언급 한 바와 같이F #에서 생명의 게임 가속기로

open Microsoft.ParallelArrays 
open System.Windows.Forms 
open System.Drawing 
type IPA = IntParallelArray 
type BPA = BoolParallelArray 
type PAops = ParallelArrays 
let RNG = new System.Random() 
let size = 1024 
let arrinit i = Array2D.init size size (fun x y -> i) 
let target = new DX9Target() 
let threearr = new IPA(arrinit 3) 
let twoarr = new IPA(arrinit 2) 
let onearr = new IPA(arrinit 1) 
let zeroarr = new IPA(arrinit 0) 
let shifts = [|-1;-1|]::[|-1;0|]::[|-1;1|]::[|0;-1|]::[|0;1|]::[|1;-1|]::[|1;0|]::[|1;1|]::[] 
let progress (arr:BPA) = let sums = shifts //adds up whether a neighbor is on or not 
            |> List.fold (fun (state:IPA) t ->PAops.Add(PAops.Cond(PAops.Rotate(arr,t),onearr,zeroarr),state)) zeroarr 
         PAops.Or(PAops.CompareEqual(sums,threearr),PAops.And(PAops.CompareEqual(sums,twoarr),arr)) //rule for life 
let initrandom() = Array2D.init size size (fun x y -> if RNG.NextDouble() > 0.5 then true else false) 

type meform() as self= 
    inherit Form() 
    let mutable array = new BoolParallelArray(initrandom()) 
    let timer = new System.Timers.Timer(1.0) //redrawing timer 
    do base.DoubleBuffered <- true 
    do base.Size <- Size(size,size) 
    do timer.Elapsed.Add(fun _ -> self.Invalidate()) 
    do timer.Start() 
    let draw (t:Graphics) = 
     array <- array |> progress 
     let bmap = new System.Drawing.Bitmap(size,size) 
     target.ToArray2D array 
     |> Array2D.iteri (fun x y t -> 
       if not t then bmap.SetPixel(x,y,Color.Black)) 
     t.DrawImageUnscaled(bmap,0,0) 

    do self.Paint.Add(fun t -> draw t.Graphics) 

do Application.Run(new meform()) 
+0

이 블로그 게시물의 GPU에 게임의 구현이 있습니다 : http://tomasp.net/blog/accelerator-life-game.aspx – Robert

답변

6

, 나는 가속기 V2를 사용하여 Game of Life in F#을 구현하는 방법을 보여줍니다 기사를 썼다, 그래서 당신은 작동하는 버전이 좀 걸릴 수 있습니다. 나는 비슷한 문제가 있음을 기억하지만, 나는 정확히 어떤 시나리오에 있는지 모른다.

어쨌든 DX9Target을 사용하는 경우 GPU에서 정수 연산을 정확하게 에뮬레이트하는 것은 DX9를 사용하는 것이 불가능하기 때문에이 타겟이 정수 연산을 지원하지 않아도되는 문제 일 수 있습니다. 나는 이것이 나의 구현에서 FloatParallelArray을 사용하는 것을 끝내었던 이유이기도하다고 생각한다. 그게 효과가 있는지보기 위해서 X64MulticoreTarget을 시도 할 기회가 있습니까?

EDIT : 나는 더 많은 조사를했고 (중요한 것을 놓치지 않는 한) CompareEqual 메서드가있는 버그 인 것으로 보입니다. 여기에 문제를 보여줍니다 훨씬 간단한 예입니다

open Microsoft.ParallelArrays 

let target = new DX9Target() 
let zeros = new IntParallelArray(Array2D.create 4 4 0) 
let trues = target.ToArray2D(ParallelArrays.CompareEqual(zeros, zeros)) 

trues |> Array2D.iter (printfn "%A") 

예상되는 결과는 true (여러 번)이 될 것입니다,하지만 당신이 그것을 실행하는 경우, 그것은 true 단지 4 번 인쇄 한 후 12 시간 false를 인쇄합니다. 나는 Accelerator 팀의 누군가에게 질문하고 대답을 게시 할 것입니다. 그 동안에도 위 예제에서했던 것과 똑같은 작업을 수행 할 수 있습니다. 즉, FPA을 사용하여 부울 연산을 시뮬레이트하고 BPACompareEqual을 사용하지 않아야합니다.

편집 2는 :

이는 DX9 GPU에서 정확한 정수 계산의 부족과 관련이 다음은 가속기 팀 멤버로부터의 응답입니다. 숫자 지터로 인해 정수 자체와 부울 비교가 항상 정확히 같은 것으로 계산되는 것은 아닙니다. (...)

따라서 요약하면 BPA에 의존 할 수 없습니다. 유일한 방법은 내가 제안한 바를 수행하는 것입니다. FPA을 사용하여 부울을 시뮬레이트합니다 (그리고 GPU로 인한 지터를 피하기 위해 작은 델타 이웃과 숫자를 비교할 수도 있습니다). 이 shoudl 그러나 X86MulticoreTarget 함께 작동 - 어떤 상황에서 라이브러리 충돌, 보여줍니다 최소한의 repro 찾을 수 있다면 정말 유용 할 것입니다!

+0

x64 대상을 사용하면 충돌이 발생합니다. FloatParallelArrays에는 사각형의 왼쪽 1/4 만 사용하면 동일한 문제가 있습니다. –

+0

실제로 버그가있는 것처럼 보입니다. –

+0

Accelerator 팀의 답변 추가 - 실제로 버그 (또는 구체적으로 현재 GPU 기술에서 해결할 수없는 기술적 한계)입니다. –

2

정밀도 문제 : DX9 급 GPU에는 전용 정수 하드웨어가 없기 때문에 정수 스트림은 부동 소수점 스트림으로 해석됩니다 (충족하지 못한 정밀도로).

DX10 클래스 GPU는 이제 모든 C 비트 연산이 포함 된 정밀한 32 비트 정수를 지원합니다. 그러나 이것이 반드시 32 비트 정수 ALU를 가지고 있음을 의미하지는 않습니다. 예를 들어 현재의 DX10 NVIDIA gen 정수 수학은 24 비트 정수 단위로 수행되므로 32 비트 정수 연산이 에뮬레이션됩니다. 차세대 DX11 NVIDIA는 진정한 32 비트 정수 단위를 가져올 것입니다.