代码之家  ›  专栏  ›  技术社区  ›  John Palmer

加速器在f中的生命游戏

  •  4
  • John Palmer  · 技术社区  · 16 年前

    我试着用加速器v2在f中编写life,但是由于一些奇怪的原因,尽管所有数组都是正方形,但我的输出却不是正方形的-似乎除了矩阵左上角的矩形区域之外,其他所有的都被设置为false。我不知道这是怎么发生的,因为我的所有操作都应该平等地对待整个数组。有什么想法吗?

    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())
    
    2 回复  |  直到 14 年前
        1
  •  6
  •   Tomas Petricek    16 年前

    正如robert提到的,我写了一篇文章,展示了如何实现 Game of Life in F#

    不管怎样,如果你用 DX9Target 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 (几次),但如果你运行它,它会打印 只有4次,然后打印12次 false . 我去问加速器组的人,然后在这里留言。同时,您可以执行与我在示例中所做的相同的操作,即使用 FPA 避免使用 BPA 均等 .

    编辑2 :以下是加速器团队成员的回复:

    这与dx9gpu缺乏精确的整数计算有关。由于数字抖动,整数与自身的布尔比较并不总是计算得完全相等。(…)

    总之,你不能真的依赖 双酚A . 唯一的选择是按照我的建议-使用 焦磷酸 (并可能与一些小的delta邻域进行比较,以避免由gpu引起的抖动)。不过,这应该与 X86MulticoreTarget -如果你能找到一些最小的重新编程,显示在哪些情况下库崩溃,这将是非常有用的!

        2
  •  2
  •   elmattic    16 年前

    关于精度问题:dx9类gpu没有专用的整数硬件,因此整数流被解释为浮点流(缺少您遇到的精度)。

    DX10类GPU现在支持所有C位运算的精确32位整数。但这并不意味着它们有真正的32位整数alu。例如,在当前的dx10 nvidia gen integer数学运算是用24位整数单位完成的,因此模拟32位整数运算。下一代DX11 NVIDIA将带来真正的32位整数单位。

    推荐文章