2017-02-17 1 views
3

Ich versuche, ein FFT zu tun ->signal manipulation ->Inverse FFT mit Project NE10 in meinem CPP-Projekt und den komplexen Ausgang zu Amplituden und Phasen für FFT und vice versa für IFFT konvertieren . Aber die Leistung meines C++ - Codes ist nicht so gut wie der SIMD-fähige NE10-Code gemäß den Benchmarks. Da ich keine Erfahrung mit Armmontage habe, suche ich nach etwas Hilfe, um Neon-Code für das nicht optimierte C-Modul zu schreiben. Beispielsweise vor IFFT ich folgendes:Neon-Code für die Umwandlung von s/w rechteckig und polaren Formen

for (int bin = 0; bin < NUM_FREQUENCY_BINS; bin++) { 
    input[bin].real = amplitudes[bin] * cosf(phases[bin]); 
    input[bin].imag = amplitudes[bin] * sinf(phases[bin]); 
} 

wo input ein Array von C structs (für komplexe Werte), amplitudes & phases sind float Arrays.

Der obige Block (O(n) complexity) benötigt etwa 0,6 ms für 8192 Bins, während NE10 FFT (O(n*log(n)) complexity) wegen SIMD-Operationen nur 0,1 ms benötigt. Nach dem, was ich bisher auf StackOverflow und anderen Orten gelesen habe, sind Intrinsics die Mühe nicht wert, also versuche ich nur in Arm Neon.

+0

Intrinsics kann * absolut * die Mühe wert sein. Insbesondere überlassen Sie die langwierige Arbeit wie die Registerzuweisung dem Compiler, was die Leistung im Vergleich zur handschriftlichen Assemblierung * verbessert *, wenn Sie * sehr * gut im Schreiben von Assembly sind und die Details der Mikroarchitektur kennen, auf der der Code ausgeführt wird. – EOF

+1

Ich habe [ein godbolt-Beispiel] (https://godbolt.org/g/te0BzE), das Aufrufe von 'cosf' und' sinf' in der Schleife zeigt. Funktionsaufrufe ergeben viel Speicheraufwand. Hier ist ein [Link hier für Sie] (http://stackoverflow.com/questions/1854254/fast-sine-cosine-for-armv7neon-looking-for-testers) und [ein anderer Link] (http: // gruntthepeon. free.fr/ssemath/neon_mathfun.html). 'cosf' und' sinf' sind verwandt, also berechnen Sie beide. Die Standard-C-Bibliothek hat eine sehr strenge Genauigkeit (oder zumindest das ist der Schwerpunkt). [sin (x)^2 + cos (x)^2 = 1] (https://de.wikibooks.org/wiki/Trigonometry/Sine_Squared_plus_Cosine_Squared). –

+0

... beides gleichzeitig über ... Das heißt, Ihre "Signalmanipulation" kann auf polar oder real/imaginär durchgeführt werden, so dass Sie diese Konvertierung nicht durchführen müssen. Wirklich müssen Sie etwas Mathe tun, um Sachen in den gleichen Koordinaten zu behalten (oder mindestens ist es wert, zu erforschen). "Convolution" könnte etwas für Sie sein, das Sie zu Ihrem Toolkit hinzufügen können? Oder zumindest der Signalmanipulationsaspekt Ihres Problems ist wahrscheinlich wichtig; Also, warum brauchen Sie die Konvertierung? –

Antwort

0

Wie ich weiß NEON unterstützt keine Vektoroperationen für geometrische Funktionen (sin, cos). Aber natürlich können Sie Ihren Code verbessern. Als Variante können Sie die Tabelle der vorberechneten Werte der Funktionen Sinus und Cosinus verwenden. Dies kann zu einer wesentlichen Verbesserung der Leistung führen.

In Bezug auf die Verwendung von intrinsischen für NEON. Ich habe versucht, beide zu verwenden, aber in den meisten Fällen geben sie praktisch das gleiche Ergebnis (für den modernen Compiler). Aber Assembler ist arbeitsintensiver. Die Hauptleistungsverbesserung wird durch die korrekte Manipulation mit Daten (Laden, Speichern) und Verwenden von Vektorbefehlen gegeben, aber diese Aktionen können unter Verwendung von Eigenarten durchgeführt werden.

Natürlich, wenn Sie 100% Auslastung der CPU erreichen möchten, müssen Sie manchmal Assembler verwenden. Aber es ist ein seltener Fall.