質問

Accelerator 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())
役に立ちましたか?

解決

ロバートが述べたように、私は実装方法を示す記事を書きました F#の人生のゲーム Accelerator V2を使用して、作業バージョンについてはそれを見ることができます。同様の問題を抱えていることを覚えていますが、どのシナリオを正確に知りません。

とにかく、あなたが使用しているなら 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 (数回)、しかしあなたがそれを実行すると、それは印刷します true わずか4回、12回印刷します false. 。アクセラレータチームの誰かに尋ねて、ここに答えを投稿します。それまでの間、あなたは私の例で私がしたのと同じことをすることができます - つまり、ブール操作を使用してシミュレートする FPA 使用しないでください BPACompareEqual.

編集2: :Acceleratorチームメンバーからの返信は次のとおりです。

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

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

他のヒント

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

DX10クラスGPUは、すべてのCビットワイズ操作で正確な32ビット整数をサポートしています。しかし、これは、それらが真の32ビット整数のアルスを持っていることを意味するものではありません。たとえば、現在のDX10 Nvidia Gen integer Mathは24ビット整数ユニットで行われるため、32ビット整数OPがエミュレートされます。次のGen DX11 Nvidiaは、真の32ビット整数ユニットをもたらします。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top