Вопрос

Я пытаюсь написать жизнь в F#, используя Accelerator v2, но по какой -то странной причине мой выход не квадрат, несмотря на то, что все мои массивы были квадратными - кажется, что все, кроме прямоугольной области в левом верхнем левом ЛОЖЬ. Я понятия не имею, как это может произойти, так как все мои операции должны относиться к всем массиву одинаково. Любые идеи?

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())
Это было полезно?

Решение

Как упоминал Роберт, я написал статью, которая показывает, как реализовать Игра жизни в F# Используя Accelerator v2, чтобы вы могли взглянуть на это для рабочей версии. Я помню, как имел подобную проблему, но я не знаю точно в каком сценарии.

В любом случае, если вы используете DX9Target Тогда проблема может заключаться в том, что эта цель не должна поддерживать операции с целыми числами (потому что эмуляция целочисленного арифметики на графическом процессоре точно невозможно с использованием DX9). Я считаю, что это также причина, по которой я в итоге использовал 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 и избегать использования BPA а также CompareEqual.

Редактировать 2: Вот ответ от членов команды Accelerator:

Это связано с отсутствием точных целочисленных расчетов на графических процессорах DX9. Из -за численного дрожания, логическое сравнение целого числа с самим собой не всегда вычисляется как ровно. (...)

Итак, в итоге, вы не можете полагаться на BPA. Анкет Единственный вариант - сделать то, что я предложил - симулировать логические FPA (и, возможно, сравните число с небольшим дельтой-инициатором, чтобы избежать дрожания, вызванного графическими процессорами). Этот Shoudl, однако, работает с X86MulticoreTarget - Если вы можете найти минимальную резо, которая показывает, в каких ситуациях библиотека сбивается, это было бы действительно полезно!

Другие советы

Что касается вопросов точности: графические процессоры класса DX9 не имеют выделенного целочисленного оборудования, поэтому целочисленные потоки интерпретируются как потоки с плавающей запятой (с отсутствием точности, с которой вы встречались).

Графические процессоры класса DX10 теперь поддерживают точные 32 бита целых числа со всеми бить. Но это не обязательно означает, что у них есть истинные 32 бита целых чисел. Например, в текущем DX10 NVIDIA Gen Integer Math выполняется с 24-разрядными целочисленными единицами, таким образом, имитация 32-разрядного целого числа. Следующее поколение DX11 NVIDIA принесет истинные 32-разрядные целочисленные единицы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top