2010-10-18 14 views
6

Ich implementiere derzeit eine zweidimensionale FFT für reale Eingabedaten mit opencl (genauer gesagt eine schnelle 2D-Faltung mit FFTs, also brauche ich nur etwas, das sich ähnlich genug verhält, um die Faltung anzuwenden). Die 2D-FFT wird unter Verwendung einer 1D-FFT auf den Zeilen und anschließend einer 1D-FFT auf den Spalten implementiert.Effiziente 2D FFT an realen Eingabedaten?

Um dies effizienter zu machen, versuche ich die Symmetrien von FFTs mit realem Eingang zu verwenden, um kleinere FFTs berechnen zu können. Ich habe herausgefunden, dass ich zwei Zeilen zu einer kombinieren kann, indem ich die erste als reelle Komponente, die zweite als imaginäre Komponente, die erste 1D FFT für die resultierende Zeile und dann die Symmetrieeigenschaften verwende, um die Ergebnisse der 1D FFTs des Individuums zu konstruieren Zeilen davon. Also was ich tue ist im Grunde Folgendes:

Lassen Sie f und g Zeilen aus der Matrix sein.

  1. Construct x = f + i * g
  2. F(x) = F(f) + i * F(g) Symmetrien
  3. benutzen Sie Trans F(f) und F(g) von F(x)

extrahieren kann ich nicht aber Eingang nur die Ergebnisse direkt in die zweite 1D FFT, weil In diesem Fall würde ich nicht die gesamte Matrix, sondern zwei Submatrizen transformieren. Das Extrahieren der Daten zwischen den Transformationen bedeutet jedoch, dass entweder mehr Daten gespeichert werden (n/2+1 Einträge, um das Ergebnis einer 1D FFT an realen Eingaben auszudrücken) oder die Elemente mit Index 0 und Index n/2 zu einem Element kombiniert werden (kombiniert mit demselben Trick, da beide Zahlen sind garantiert echt) und verwenden die gleiche Menge an Speicherplatz, müssen aber in meiner Faltung einen besonderen Fall dafür machen.

Da ich versuche, Puffer so viel wie möglich zu verwenden (aufgrund der begrenzten RAM verfügbar auf der GPU) mit mehr Speicher ist keine nette Lösung. Darüber hinaus sind meine Algorithmen nicht für Matrixgrößen geeignet, die keine Potenz von 2/Vielfachen von 16 sind (variiert von Kernel zu Kernel). Ich würde es auch lieber vermeiden, Sonderfälle einzuführen, da diese meine Kernel komplexer machen würden, was die Effizienz beeinträchtigt (ich habe bereits Probleme, die von jedem Kernel verwendete Registeranzahl zu minimieren).

Also meine Frage ist, ob es eine elegante Herangehensweise an dieses Problem gibt, gemeint ist eine, die funktioniert, ohne entweder mehr Speicher oder Sonderfälle für bestimmte Elemente zu verwenden?

Idealerweise würde ich gerne die ganze FFT machen können, ohne meine kombinierten Daten in der Mitte der FFT zu teilen, aber ich bin mir nicht sicher, ob das möglich ist.

+3

Wird dies in absehbarer Zeit als Taschenbuch heraus sein? –

+0

Müssen Sie wirklich eine komplexe FFT machen? Wahrscheinlich nicht. – phkahler

+0

gute Frage, hatte ich fast das gleiche Problem während der Durchführung von FFT für die Erkennung von Steganographie. aber ich habe damals nicht gemerkt, dass stackoverflow existiert;/ – dfens

Antwort

2

Hmmm ... meine beiden Referenzen sind:

http://www.engineeringproductivitytools.com/stuff/T0001/PT10.HTM http://images.apple.com/acg/pdf/FFTapps_20090909.pdf

Ich denke, dass auf ein "hermitesch" Daten zu begehen Struktur, mit den Werten 0 und n/2, die in das erste Element gepackt sind, ist der Weg zu gehen, da vorwärts/inverse und hermitesche Strukturen besser funktionieren werden.

Auf diese Weise haben Sie rUnWrap (FFT (n/2, gerade (x) + i * ungerade (x))) = rFFT (x), und die riFFT kann auf dem "hermitian" Array arbeiten, die Paar von Arrays Even und Odd, was wiederum die ursprüngliche Struktur ergibt.

Es gibt auch andere Samplings, die durchgeführt werden können, wobei das ursprüngliche Array in 4 n/2xn/2 Arrays mit Wurzeln bei (0,0), (0,1), (1,0) aufgeteilt ist. , (1,1) und dann am Ende gewickelt, mit einem letzten radix-4 pass ... vielleicht ist das besser für den GPU-Speicher ... Ich weiß es nicht.

alan