Domanda

Sto cercando di scrivere la vita in F # con acceleratore v2, ma per qualche strana ragione la mia uscita non è quadrata, nonostante tutte le mie matrici essendo quadrato - Sembra che tutto, ma un'area rettangolare in alto a sinistra della matrice è essere impostato su false. Non ho idea di come questo potrebbe accadere come tutti i miei operazioni dovrebbe trattare l'intero array altrettanto. Tutte le idee?

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())
È stato utile?

Soluzione

Come Robert detto, ho scritto un articolo che mostra come implementare gioco della vita in F # utilizzando Accelerator v2, in modo da poter dare un'occhiata a che per una versione di lavoro. Mi ricordo di aver problema simile, ma non so esattamente in quale scenario.

In ogni caso, se si sta utilizzando DX9Target allora il problema potrebbe essere che questo obiettivo non dovrebbe supportare le operazioni con i numeri interi (a causa emulando aritmetica interi su GPU non è proprio solo possibile utilizzando DX9). Credo che questo è anche un motivo per cui ho finito per usare FloatParallelArray nella mia implementazione. Avete qualche possibilità di provare il X64MulticoreTarget per vedere se questo avrebbe funzionato?

Modifica : Ho fatto alcune ulteriori indagini e (a meno che non mi manca qualcosa di importante) sembra essere un bug con il metodo CompareEqual. Ecco un esempio molto più semplice che mostra il problema:

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

Il risultato atteso sarebbe true (più volte), ma se lo si esegue, esso stampa true solo 4 volte e quindi stampa 12 volte false. Chiederò qualcuno del team di acceleratore e post una risposta qui. Nel frattempo, si può fare la stessa cosa che ho fatto nel mio esempio -. Che è, simulare le operazioni booleane utilizzando FPA ed evitare di usare BPA e CompareEqual

Modifica 2 : Ecco una risposta da parte dei membri del team Accelerator:

  

Ciò è dovuto alla mancanza di calcoli interi precise su GPU DX9. A causa di jitter numerica, un confronto booleano un intero con sé non è sempre calcolata come esattamente uguali. (...)

Così, in sintesi, non si può davvero fare affidamento su BPA. L'unica opzione è quella di fare quello che ho suggerito - simulare booleani utilizzando FPA (ed eventualmente confrontare il numero con qualche piccolo delta-quartiere per evitare le oscillazioni causate dalla GPU). Questo shoudl però lavorare con il X86MulticoreTarget - se si può trovare un po 'di Repro minimo che mostra in quali situazioni i crash di libreria, che sarebbe davvero utile

Altri suggerimenti

A proposito di problemi di precisione:. GPU DX9 di classe non hanno hardware intero dedicato, in modo da flussi di interi sono interpretati come i flussi in virgola mobile (con la mancanza di precisione che hai incontrato)

GPU DX10-classe non supportano ora precise 32 bit interi con tutte le operazioni C bit per bit. Ma questo non significa necessariamente che non hanno veri 32 bit interi ALU. Ad esempio sulla DX10 corrente NVIDIA generazione calcolo integer si realizza con unità intere 24-bit, così 32 bit op interi vengono emulati. Next Gen DX11 di NVIDIA porterà veri unità integer a 32 bit.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top