f# - 带加速器的 F# 生命游戏

标签 f# gpu accelerator conways-game-of-life

我正在尝试使用加速器 v2 在 F# 中编写生命,但由于某些奇怪的原因,尽管我的所有数组都是正方形,但我的输出不是正方形 - 看起来除了矩阵左上角的矩形区域之外的所有内容都是正方形的被设置为 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())

最佳答案

正如 Robert 提到的,我写了一篇文章,展示了如何实现 Game of Life in F#使用 Accelerator v2,因此您可以查看它的工作版本。我记得有过类似的问题,但不知 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。我会询问加速器团队的人员并在此处发布答案。同时,您可以执行与我在示例中所做的相同的操作 - 即使用 FPA 模拟 bool 运算,并避免使用 BPACompareEqual.

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

This is related to the lack of precise integer calculations on DX9 GPUs. Because of numerical jitter, a Boolean comparison of an integer with itself is not always computed as exactly equal. (...)

因此,总而言之,您不能真正依赖 BPA。唯一的选择是按照我的建议进行操作 - 使用 FPA 模拟 bool 值(并可能将数字与一些小的增量邻域进行比较,以避免 GPU 引起的抖动)。然而,这应该与X86MulticoreTarget一起使用 - 如果您能找到一些最小的重现来显示库在哪些情况下崩溃,那将非常有用!

关于f# - 带加速器的 F# 生命游戏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2490920/

相关文章:

internet-explorer - Internet Explorer 加速器 - 打开默认浏览器

f# - 显式声明内联函数签名

f# - Fsyacc:添加了具有相同键的项目

f# - F# Async.Parallel 会加快计算速度吗?

java - 显示两个非模态 JDialog 后 JMenuItem 加速器不起作用? (仅限 Mac?)

java - 按住撤消加速键时性能不佳

f# - 如何避免更改参数顺序

objective-c - 将 CIImage 绘制到 NSOpenGLView(不访问主内存)

cuda - 使用 Vulkan VkImage 作为 CUDA cuArray

python - nvidia-docker : failed call to cuInit: CUDA_ERROR_UNKNOWN 中的 TensorFlow