Frage

Ich versuche, das Leben in F# mit Accelerator v2 zu schreiben, aber aus irgendeinem seltsamen Grund ist meine Ausgabe nicht quadratisch, obwohl alle meine Arrays quadratisch sind – es scheint, dass alles außer einem rechteckigen Bereich oben links in der Matrix eingestellt ist FALSCH.Ich habe keine Ahnung, wie das passieren könnte, da alle meine Operationen das gesamte Array gleich behandeln sollten.Irgendwelche Ideen?

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())
War es hilfreich?

Lösung

Wie Robert erwähnte, habe ich einen Artikel geschrieben, der zeigt, wie man es umsetzt Spiel des Lebens in F# Ich verwende Accelerator v2, Sie können also einen Blick darauf werfen, um eine funktionierende Version zu erhalten.Ich erinnere mich, dass ich ein ähnliches Problem hatte, weiß aber nicht genau, in welchem ​​Szenario.

Wie auch immer, wenn Sie es verwenden DX9Target Dann liegt das Problem möglicherweise darin, dass dieses Ziel keine Operationen mit Ganzzahlen unterstützen soll (da die genaue Emulation ganzzahliger Arithmetik auf der GPU mit DX9 einfach nicht möglich ist).Ich glaube, dass dies auch ein Grund ist, warum ich es letztendlich verwendet habe FloatParallelArray in meiner Umsetzung.Haben Sie eine Chance, das auszuprobieren? X64MulticoreTarget um zu sehen, ob das funktionieren würde?

BEARBEITEN:Ich habe einige weitere Nachforschungen angestellt und (es sei denn, ich übersehe etwas Wichtiges) es scheint ein Fehler im zu sein CompareEqual Methode.Hier ist ein viel einfacheres Beispiel, das das Problem zeigt:

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")

Das erwartete Ergebnis wäre true (mehrmals), aber wenn Sie es ausführen, wird es gedruckt true nur 4 Mal und dann 12 Mal gedruckt false.Ich werde jemanden vom Accelerator-Team fragen und hier eine Antwort posten.In der Zwischenzeit können Sie das Gleiche tun, was ich in meinem Beispiel getan habe – das heißt, boolesche Operationen mit simulieren FPA und vermeiden Sie die Verwendung BPA Und CompareEqual.

BEARBEITEN 2:Hier ist eine Antwort der Accelerator-Teammitglieder:

Dies hängt mit dem Fehlen präziser Ganzzahlberechnungen auf DX9-GPUs zusammen.Aufgrund des numerischen Jitters wird ein boolescher Vergleich einer Ganzzahl mit sich selbst nicht immer als exakt gleich berechnet.(...)

Zusammenfassend kann man also nicht wirklich darauf vertrauen BPA.Die einzige Möglichkeit besteht darin, das zu tun, was ich vorgeschlagen habe: Boolesche Werte mithilfe von zu simulieren FPA (und vergleichen Sie die Zahl möglicherweise mit einer kleinen Delta-Nachbarschaft, um den durch GPUs verursachten Jitter zu vermeiden).Dies sollte jedoch mit dem funktionieren X86MulticoreTarget - Wenn Sie eine minimale Reproduktion finden könnten, die zeigt, in welchen Situationen die Bibliothek abstürzt, wäre das wirklich nützlich!

Andere Tipps

Über Präzisionsprobleme: DX9-Klasse-GPUs haben keine dedizierte Ganzzahl-Hardware, daher werden ganzzahlige Streams als schwimmende Punktströme interpretiert (mit dem mangelnden Präzision, den Sie getroffen haben).

DX10-Klasse-GPUs unterstützen jetzt präzise 32 Bit-Ganzzahlen mit allen b-bitgewiehenen Operationen. Dies bedeutet jedoch nicht, dass sie wahre 32 Bit -Ganzzahlen Alus haben. Zum Beispiel wird die aktuelle Mathematik von DX10 NVIDIA Gen Integer Math mit 24-Bit-Ganzzahl-Einheiten durchgeführt, sodass 32-Bit-Ganzzahl-OPs emuliert werden. Die nächste Gen DX11 NVIDIA wird echte 32-Bit-Ganzzahleinheiten bringen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top