我正在尝试使用加速器 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())
最佳答案
正如罗伯特提到的,我写了一篇文章,展示了如何使用 Accelerator v2 实现 Game of Life in F#,因此您可以查看它的工作版本。我记得有类似的问题,但我不知 Prop 体是在什么情况下。
无论如何,如果您使用的是 DX9Target
,那么问题可能在于该目标不应该支持整数运算(因为使用 DX9 无法在 GPU 上精确模拟整数运算)。我相信这也是我最终在实现中使用 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
。我会询问 Accelerator 团队的某个人并在此处发布答案。同时,您可以执行与我在示例中所做的相同的操作 - 即,使用 FPA
模拟 bool 运算并避免使用 BPA
和 CompareEqual
。编辑 2 :这是加速器团队成员的回复:
因此,总而言之,您不能真正依赖
BPA
。唯一的选择是按照我的建议去做——使用 FPA
模拟 bool 值(并且可能将数字与一些小的增量邻域进行比较以避免由 GPU 引起的抖动)。但是,这应该与 X86MulticoreTarget
一起使用 - 如果您能找到一些最小的重现来显示库在哪些情况下崩溃,那将非常有用!关于f# - 带加速器的 F# 生活游戏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2490920/