4

アクセラレータ v2 を使用して 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())
4

2 に答える 2

6

Robert が述べたように、私はAccelerator v2 を使用して F# で Game of Lifeを実装する方法を示す記事を書いたので、実際に動作するバージョンを参照してください。同様の問題があったことを覚えていますが、どのシナリオで正確にわかりません。

とにかく、使用してDX9Targetいる場合、問題は、このターゲットが整数を使用した操作をサポートすることになっていないことである可能性があります (GPU で整数演算を正確にエミュレートすることは、DX9 を使用して不可能であるため)。これが、実装に使用することになった理由でもあるとFloatParallelArray思います。それが機能するかどうかを試す機会はありますX64MulticoreTargetか?

編集:さらに調査を行いましたが、(重要なものが欠けていない限り)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(数回) ですが、実行するとtrue4 回しか印刷されず、その後 12 回印刷されfalseます。Accelerator チームの誰かに尋ねて、ここに回答を投稿します。それまでの間、私の例で行ったのと同じことを行うことができます。つまり、を使用してブール演算をシミュレートし、 and を使用しFPAないようにします。BPACompareEqual

編集 2 : アクセラレータ チーム メンバーからの返信は次のとおりです。

これは、DX9 GPU での正確な整数計算の欠如に関連しています。数値ジッターのため、整数とそれ自体のブール比較は、常に正確に等しいとは限りません。(...)

したがって、要約すると、本当に信頼することはできませんBPA。唯一のオプションは、私が提案したことを実行することです-ブール値を使用してシミュレートしますFPA(そして、GPUによって引き起こされるジッターを回避するために、数値をいくつかの小さなデルタ近傍と比較する可能性があります)。ただし、この shoudl はX86MulticoreTarget、ライブラリがクラッシュする状況を示す最小限の再現を見つけることができれば、非常に便利です。

于 2010-03-22T11:35:55.227 に答える
2

精度の問題について:DX9クラスのGPUには専用の整数ハードウェアがないため、整数ストリームは浮動小数点ストリームとして解釈されます(精度が不足しています)。

DX10クラスのGPUは、すべてのCビット演算で正確な32ビット整数をサポートするようになりました。ただし、これは必ずしも、真の32ビット整数ALUがあることを意味するわけではありません。たとえば、現在のDX10では、NVIDIA gen整数演算は24ビット整数単位で実行されるため、32ビット整数演算がエミュレートされます。次世代のDX11NVIDIAは、真の32ビット整数ユニットを提供します。

于 2010-03-25T13:45:24.203 に答える