سؤال

أحاول أن أكتب الحياة في 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 ثم قد تكون المشكلة أن هذا الهدف ليس من المفترض أن يدعم العمليات مع الأعداد الصحيحة (لأن محاكاة الحساب الصحيح على GPU على وجه التحديد غير ممكن باستخدام 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 بت من أعداد صحيحة مع جميع عمليات C bitwise. لكن هذا لا يعني أن لديهم 32 بت من الأعداد الصحيحة الحقيقية. على سبيل المثال على DX10 NVIDIA GEN INTEGER MATH مع وحدات عدد صحيح 24 بت ، وبالتالي يتم محاكاة عدد صحيح 32 بت. القادم Gen DX11 NVIDIA سوف يجلب وحدات عدد صحيح 32 بت حقيقي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top