سؤال

أحاول تجربة مفاهيم الراديو المحددة للبرامج. من هذا مقالة - سلعة لقد حاولت تنفيذ تحويل فورييه المنفصل عن GPU.

أنا متأكد تمامًا من أنني يمكن أن أتحلى مسبقًا 90 درجة من الخطيئة (i) cos (i) ثم اقلب فقط وأكرر بدلاً من ما أفعله في هذا الرمز وهذا من شأنه أن يسرع. لكن حتى الآن ، لا أعتقد حتى أنني أحصل على إجابات صحيحة. يعطي إدخال All-ZerOS نتيجة 0 كما أتوقع ، ولكن جميع المدخلات 0.5 كما تعطي مدخلات 78.9985886F (أتوقع نتيجة 0 في هذه الحالة أيضًا). في الأساس ، أنا مرتبك بشكل عام. ليس لدي أي بيانات إدخال جيدة ولا أعرف ماذا أفعل بالنتيجة أو كيفية التحقق منها.

هذا السؤال مرتبط بمشاركتي الأخرى هنا

open Microsoft.ParallelArrays
open System

 // X64MulticoreTarget is faster on my machine, unexpectedly
let target = new DX9Target() // new X64MulticoreTarget()

ignore(target.ToArray1D(new FloatParallelArray([| 0.0f |]))) // Dummy operation to warm up the GPU

let stopwatch = new System.Diagnostics.Stopwatch() // For benchmarking

let Hz = 50.0f
let fStep = (2.0f * float32(Math.PI)) / Hz
let shift = 0.0f // offset, once we have to adjust for the last batch of samples of a stream

// If I knew that the periodic function is periodic 
// at whole-number intervals, I think I could keep 
// shift within a smaller range to support streams 
// without overflowing shift - but I haven't 
// figured that out

//let elements = 8192 // maximum for a 1D array - makes sense as 2^13
//let elements = 7240 // maximum on my machine for a 2D array, but why?
let elements = 7240

// need good data!!
let buffer : float32[,] = Array2D.init<float32> elements elements (fun i j -> 0.5f) //(float32(i * elements) + float32(j))) 

let input = new FloatParallelArray(buffer)
let seqN : float32[,] = Array2D.init<float32> elements elements (fun i j -> (float32(i * elements) + float32(j)))
let steps = new FloatParallelArray(seqN)
let shiftedSteps = ParallelArrays.Add(shift, steps)
let increments = ParallelArrays.Multiply(fStep, steps)
let cos_i = ParallelArrays.Cos(increments) // Real component series
let sin_i = ParallelArrays.Sin(increments) // Imaginary component series

stopwatch.Start()
// From the documentation, I think ParallelArrays.Multiply does standard element by 
// element multiplication, not matrix multiplication
// Then we sum each element for each complex component (I don't understand the relationship 
// of this, or the importance of the generalization to complex numbers)
let real = target.ToArray1D(ParallelArrays.Sum(ParallelArrays.Multiply(input, cos_i))).[0]
let imag = target.ToArray1D(ParallelArrays.Sum(ParallelArrays.Multiply(input, sin_i))).[0]
printf "%A in " ((real * real) + (imag * imag)) // sum the squares for the presence of the frequency
stopwatch.Stop()

printfn "%A" stopwatch.ElapsedMilliseconds

تجاهل (System.Console.ReadKey ())

هل كانت مفيدة؟

المحلول

أشارككم مفاجأة أن إجابتك ليست أقرب إلى الصفر. أقترح كتابة رمز ساذج لأداء DFT الخاص بك في F# ومعرفة ما إذا كان يمكنك تتبع مصدر التناقض.

هذا ما أعتقد أنك تحاول القيام به:

let N = 7240
let F = 1.0f/50.0f
let pi = single System.Math.PI

let signal = [| for i in 1 .. N*N -> 0.5f |]

let real = 
  seq { for i in 0 .. N*N-1 -> signal.[i] * (cos (2.0f * pi * F * (single i))) }
  |> Seq.sum

let img = 
  seq { for i in 0 .. N*N-1 -> signal.[i] * (sin (2.0f * pi * F * (single i))) }
  |> Seq.sum

let power = real*real + img*img

نأمل أن تتمكن من استخدام هذا الرمز الساذج للحصول على حدس أفضل لكيفية تصرف رمز التسريع ، والذي يمكن أن يرشدك في اختبار رمز التسريع. ضع في اعتبارك أن جزءًا من سبب التناقض قد يكون ببساطة دقة الحسابات - هناك حوالي 52 مليون عنصر في المصفوفات الخاصة بك ، لذا فإن تراكم خطأ إجمالي قدره 79 قد لا يكون في الواقع سيئًا للغاية. FWIW ، أحصل على قوة ~ 0.05 عند تشغيل رمز الدقة الواحدة أعلاه ، ولكن قوة ~ 4e-18 عند استخدام رمز مكافئ بأرقام دقيقة.

نصائح أخرى

اقتراحان:

  • تأكد من أنك لست مربكًا بطريقة ما مع راديان
  • حاول القيام بذلك بلا شك ، أو فقط مع المتزامنات F#من أجل التوازي

(في F#، إذا كان لديك مجموعة من العوامات

let a : float[] = ...

ثم يمكنك "إضافة خطوة إلى كل منهم بالتوازي" لإنتاج مجموعة جديدة مع

let aShift = a |> (fun x -> async { return x + shift }) 
               |> Async.Parallel |> Async.RunSynchronously

(على الرغم من أنني أتوقع أن يكون هذا أبطأ أن مجرد القيام بحلقة متزامنة).).

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