FFT Benchmark auf einem STM32F4 Microcontroller, Beagle Bone Black und PC

Da ich demnächst eine FFT für ein Projekt für den Beagle Bone brauche, und letztens die Frage aufkam, habe ich mal die Kiss FFT Library auch für mein STM3F4Discovery Devboard ausprobiert. Hier die Library:

formatting link

(KISS ist Programmiererslang und bedeutet soviel wie das Gegenteil von Feature Creep, was man bei anderen FFT-Libraries gerne sieht:

formatting link
)

Hier das gesamte Testprojekt:

formatting link

Ist recht groß, da ich das gesamte Projekt mal zusammengepackt habe, hier der relevante Sourcecode für den Test:

formatting link

Ich habe es mit cs-make von CodeSourcery compiliert, mit einem GCC

4.6.1. Im Hintergrund habe ich noch zwei I2S Datentransfers per DMA laufen lassen, mit 96 kHz Samplefrequenz und 32 Bit Wortbreite, Daten gesendet und empfangen, im Full-Duplex und Double-Buffering Betrieb, mit zusätzlicher Zwischenspeicherung und Lesen aus einem Ringbuffer. Das macht aber nicht viel aus, ohne Transfer läuft es nur ca. 6% schneller.

Hier die Messergebnisse pro FFT-Berechnung, wenn der ARM-Core mit der maximalen Geschwindigkeit von 168 MHz läuft:

size: 256, time: 0.257400 ms, with dB: no, sum: 12798979072.000000 size: 256, time: 3.709400 ms, with dB: yes, sum: 252872096.000000 size: 512, time: 0.698600 ms, with dB: no, sum: 25597667328.000000 size: 512, time: 7.601900 ms, with dB: yes, sum: 526377920.000000 size: 1024, time: 1.164700 ms, with dB: no, sum: 51200745472.000000 size: 1024, time: 14.972600 ms, with dB: yes, sum: 1180834944.000000 size: 2048, time: 3.057900 ms, with dB: no, sum: 102385901568.000000 size: 2048, time: 30.673901 ms, with dB: yes, sum: 2318690560.000000

Ich habe einmal nur die FFT berechnen lassen und die Ergebnisse summiert (damit eine eventuelle Optimierung das nicht wegoptimiert), was die Angabe "with dB: no" ist. Ein etwas praxisrevelanteres Beispiel ist dann, "10 * log10f(r * r + i * i)" auf jedem Ergebniswert zu berechnen. Das scheint die Zeit ziemlich zu erhöhen.

Eigentlich hat der verwendete ARM eine Floating-Point Einheit, aber die hat glaube ich keine transzendente oder logarithmischen Funktionen. Also wenn man schnell bleiben will, sollte man in der quadratischen Ebene die Daten weiterverarbeiten, oder ggf. eine schnellere Näherung für den Logarithmus verwenden. Sieht aber generell recht gut aus, wenn man irgendwas realtime-mäßiges damit machen wollte. Ich will demnächst mal den FFT-Overlap-Add Algorithmus damit ausprobieren, da man damit lange FIR-Filter sehr schnell in der Frequenzdomäne berechnen kann und dann in Echtzeit Audiosignale damit bearbeiten.

Hier die Ergebnisse von einem Beagle Bone Black, mit dem darauf installierten Compiler compiliert (und leicht modifiziertem Testcode mit dem Qt-Framework für die Zeitmessung, da ich das für die eigentliche Anwendung später auch brauche), der mit 1 GHz läuft:

size: 256, time: 0.440500 ms, with dB: no, sum: 12798979072.000000 size: 256, time: 0.590400 ms, with dB: yes, sum: 252872096.000000 size: 512, time: 0.955500 ms, with dB: no, sum: 25597667328.000000 size: 512, time: 1.300000 ms, with dB: yes, sum: 526377920.000000 size: 1024, time: 2.060500 ms, with dB: no, sum: 51200745472.000000 size: 1024, time: 2.743500 ms, with dB: yes, sum: 1180834944.000000 size: 2048, time: 4.627700 ms, with dB: no, sum: 102385901568.000000 size: 2048, time: 5.991300 ms, with dB: yes, sum: 2318690560.000000

Interessanterweise langsamer, als auf dem STM3F4, aber der Logarithmus läuft merkwürdigerweise bedeutend schneller. Ist bei der CodeSourcery Library etwa die Mathematik-Library ohne die Floating-Point-Einheit compiliert worden und auf dem Beagle Bone Black alles nur per Software Emulation berechnet? Bin jetzt zu faul nachzuschauen, ob der eine Hardware Floating-Point-Einheit hat, wie es der ARM Core auf dem Raspberry Pi bietet und mit dem "hardfp" Debian Wheezy.

Und schließlich zum Vergleich die Messung mit dem gcc von mingw von Qt Creator im Release-Modus für Windows compiliert, ausgeführt auf einem Intel Xeon mit 2,4 GHz Takt:

size: 256, time: 0.008000 ms, with dB: no, sum: 12798615552.000000 size: 256, time: 0.014900 ms, with dB: yes, sum: 252872080.000000 size: 512, time: 0.019200 ms, with dB: no, sum: 25597716480.000000 size: 512, time: 0.034500 ms, with dB: yes, sum: 526377888.000000 size: 1024, time: 0.033800 ms, with dB: no, sum: 51195023360.000000 size: 1024, time: 0.064900 ms, with dB: yes, sum: 1180834944.000000 size: 2048, time: 0.085000 ms, with dB: no, sum: 102391111680.000000 size: 2048, time: 0.147700 ms, with dB: yes, sum: 2318690560.000000

Ist also 40 bis 250 mal (für die log10-Berechnung) schneller, als auf dem STM32F4. Man sieht auch kleinere Unterschiede in der Summe, obwohl alle ja eigentlich floats mit 4 Bytes verwenden, was vielleicht daran liegt, daß der Intel intern mit höherer Genauigkeit rechnet.

Den I2S Datentransfer mit DMA Transfer zu programmieren war übrigens nicht so einfach, da es kein genau passendes Beispiel für meinen Anwendungsfall gab (ich wollte einen externen Chip per I2S3/I2S3Ext-Modul ansprechen). Ich dachte bin ich vielleicht in 1-2 Stunden fertig, aber war dann 350 Zeilen und zwei Tage später froh, daß es endlich läuft. Eine falsche Zeile und nichts läuft mehr, was die Fehlersuche interessant macht.

Die STM32 Library ist auch zu low-level, sodaß man leicht Fehler machen kann oder was vergessen kann (DMA_IT_TCIF5 statt DMA_FLAG_TCIF5 für den DMA_ClearITPendingBit-Aufruf verwendet? Interrupt-Sturm). Und das Datenblatt ist nicht immer genau: Reference-Manual sagt "examples of DMA request mappings", "depends on the product implementation", aber man findet es nicht im Datasheet des betreffenden Prozessors. Und es stellte sich heraus, daß es nicht nur ein Beispiel ist, sondern daß es anders als dort angegeben erst gar nicht läuft. Wieder ein paar Stunden weg mit Fehlersuche.

Mir sind auch noch ein paar Sachen etwas unklar, vielleicht werde ich mal den Support anschreiben. Aber letztens meinte jemand, daß der gar nicht erst antwortet. Schade, denn der Microcontroller ist wirklich gut, was ich bis jetzt so gesehen habe und ich konnte auch noch keinen Chip-Fehler bei meinen Experimenten feststellen, wie man es schonmal bei manchen Chips von Atmel hat. Fehlt nur noch eine einfacherere anzuwendende Library, wenn man nicht die Register alle selbst programmieren will.

Oder noch besser: ein GUI mit Codegenerator, wie es die PSoC IDE von Cypress bietet. Da kann man schon von vorneherein keine Fehler bei der Registerkonfiguration machen, da das GUI jeweils nur die gültigen Auswahlmöglichkeiten zur Verfügung stellt. Ich bin ja eigentlich nicht ein Fan von Codegeneratoren, aber die machen einem das Programmiererleben wirklich leichter.

--
Frank Buss, http://www.frank-buss.de 
electronics and more: http://www.youtube.com/user/frankbuss
Reply to
Frank Buss
Loading thread data ...

Interessant. Ich hab leider gerade etwas wenig Zeit sonst haette ich es mal mit meinem SH2A verglichen.

Wenn du Vergleiche zulassen willst dann musst du die ganzen aktiven Compilerswitches mit angeben.

Was mich an der DMA-Sache beim SH2A immer fasziniert hat, man kann irgendeinen Fehler machen der die CPU total abstuerzt, aber er spielt dann die letzten 5-10s meiner Musik aus dem Ram einfach weiter. Selbst wenn man das Programm im Debugger anhaelt.

Antworten tun sie schon, sie brauchen nur viele Tage bis Wochen und haben bei mir keinen besonders kompetenten Eindruck hinterlassen. Und dabei habe ich den Vorteil auf meiner Visitenkarte einen Firmennamen stehen zu haben der die Verkaeufertypen normalerweise sehr befluegelt. Als ein Kollege letztens bei TI angerufen hat, da hat es drei Tage gedauert und zwei Ings von denen standen in der Tuer um uns zu erklaeren wie man deren Problem umgehen kann. :)

Mit dem F4 habe ich selber auch nur ein bisschen privat rumgespielt. Dafuer habe ich einiges mit dem STM32L1 gemacht das jetzt in Stueckzahlen laeuft. Da habe ich schon einen Bug gefunden.

Ich mag soetwas nicht so besonders. Schon garnicht wenn Fehler drin sind und der Hersteller zu faul ist ein Datenblatt fuer jede CPU zu schreiben, es also nur ein gemeinsames Datenblatt fuer alle Modelle gibt. So koennen z.B nicht alles Zaehler im L1 als Up und Downcounter arbeiten. Die Libary akzeptiert es aber das man das Richtungsbit auch bei einem Zaehler setzt der es nicht kann.

Solche Libary machen einem die ARbeit zuerst ein bisschen einfacher, aber sie kosten hinterher das doppelte der gesparten Zeit wenn man merkwuerdige Fehler suchen muss.

Du kannst dir ja mal die Geckos anschauen. Da gibt es wohl soetwas auch. Liess dir aber vorher die Erratas durch und stelle fest das die teilweise jeden Monat eine neue Liste rausbringen.

Olaf

Reply to
Olaf Kaluza

Hier die relevanten Switches was der Make-Prozess ausgibt, für die Compilierung für den STM32F4:

arm-none-eabi-gcc -O2 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16

-mfloat-abi=softfp -mthumb

Bei der Cypress-IDE lief das bisher recht gut, habe ich schonmal für ein Projekt eingesetzt. Die generierte Code-Qualität, Dokumentation der zusammenklickbaren Funktionen usw. war gut und man konnte relativ schnell eine Lösung für eine Aufgabe zusammenklicken. Der eigene Code beschränkt sich dann nur noch auf die Aufgabe selbst, nicht mehr die ganze Chipverwaltung. Ich habe den Chip auch einmal ohne GUI programmiert, aber dafür ist die PSoC-Architektur eigentlich zu komplex.

--
Frank Buss, http://www.frank-buss.de 
electronics and more: http://www.youtube.com/user/frankbuss
Reply to
Frank Buss

[...]

Das war ich :-)

Bei uns haben sie ueberhaupt nicht geantwortet und das war auch nicht das erste Mal. Daher habe ich entschieden, deren uC nicht einzusetzen. Von ST nehme ich nur noch Wald- und Wiesenteile wie Opamps, nichts was auch nur irgendwie mal Support brauchen koennte.

Support ist oft ein Riesenproblem bei grossen EU-Firmen.

[...]
--
Gruesse, Joerg 

http://www.analogconsultants.com/
Reply to
Joerg

Frank Buss :

Hast du auch mal andere Switches ausprobiert? Gibt da z.B. auch "-mfloat- abi=hard" "-mthumb-interwork" usw... Die schneckenlahmen trigon.-Funktionen haben wir auch schon beobachtet - Vorherberechnung und Tabelle brachte da nen ziemlichen Geschwindigkeitsgewinn (und nach den Optimierungen lief das auf Intel dann fast zu schnell :-).

M.

Reply to
Matthias Weingart

Mit -mfloat-abi=hard kommen nur Fehlermeldungen dieser Art:

failed to merge target specific data of file [...] uses VFP register arguments

Das könnte aber bedeuten, daß es vielleicht doch einiges emuliert war und man noch einiges an Geschwindigkeit herausholen kann, wenn man die Compiler Switches Wissenschaft einmal gelernt hat.

-mthumb-interwork gibt so eine Fehlermeldung:

error: target CPU does not support ARM mode

Das macht Sinn, da die kleineren Cortex-Cores den ARM-Mode tatsächlich nicht unterstützen.

Ich habe es aber eben mal auch auf meinem Raspberry Pi compiliert, wo das komplette System mit allen Libraries mit hardfp compiliert ist. Hier die Zeiten:

size: 256, time: 0.068000 ms, with dB: no, sum: 12798979072.000000 size: 256, time: 0.176000 ms, with dB: yes, sum: 252872096.000000 size: 512, time: 0.186000 ms, with dB: no, sum: 25597667328.000000 size: 512, time: 0.401000 ms, with dB: yes, sum: 526377920.000000 size: 1024, time: 0.392000 ms, with dB: no, sum: 51200745472.000000 size: 1024, time: 0.826000 ms, with dB: yes, sum: 1180834944.000000 size: 2048, time: 1.244000 ms, with dB: no, sum: 102385901568.000000 size: 2048, time: 2.065000 ms, with dB: yes, sum: 2318690560.000000

Der läuft nur mit 700 MHz, der Benchmark ist aber interessanterweise ca. dreimal so schnell, wie der 1 GHz Beaglebone.

Sieht also wirklich so aus, als ob die log10-Implementierung die ich verwende, nicht die floating-point Einheit auf dem ST32F4 verwendet. Da muss ich wohl noch ein wenig experimentieren und andere Cross-Compiler ausprobieren, oder mir selber einen bauen.

Hier der angepasste Test, ohne alles Qt drumherum:

formatting link

So auf dem Raspberry Pi getestet:

gcc -O2 -lm main.c kiss_fft.c ; ./a.out

Sollte auf jedem Unix-ähnlichen System laufen. Habe es spaßeshalber auch mal auf meinem Webserver laufen lassen, einer VPS Installation bei 1&1:

size: 256, time: 0.007000 ms, with dB: no, sum: 12798979072.000000 size: 256, time: 0.030000 ms, with dB: yes, sum: 252872096.000000 size: 512, time: 0.022000 ms, with dB: no, sum: 25597667328.000000 size: 512, time: 0.061000 ms, with dB: yes, sum: 526377920.000000 size: 1024, time: 0.037000 ms, with dB: no, sum: 51200745472.000000 size: 1024, time: 0.108000 ms, with dB: yes, sum: 1180834944.000000 size: 2048, time: 0.100000 ms, with dB: no, sum: 102385901568.000000 size: 2048, time: 0.240000 ms, with dB: yes, sum: 2318690560.000000

Zum Number-Crunching sollte man also wohl besser einen dedicated Server oder was in einer Wolke mieten :-)

--
Frank Buss, http://www.frank-buss.de 
electronics and more: http://www.youtube.com/user/frankbuss
Reply to
Frank Buss

Am 01.12.2013 20:09, schrieb Frank Buss:

......

Als Ergänzung. Werte ermittelt auf einem STM32F4 Discovery for STM32F429. Clock 180 MHz, IDE Rowley (GCC), FPU on, optimization level

3, handgestoppt.

size: 256, time: 0.26 ms, with dB: no size: 256, time: 0.49 ms, with dB: yes size: 512, time: 0.64 ms, with dB: no size: 512, time: 1.08 ms, with dB: yes size: 1024, time: 1.1 ms, with dB: no size: 1024, time: 1.95 ms, with dB: yes size: 2048, time: 2.75 ms, with dB: no size: 2048, time: 4.44 ms, with dB: yes

Jetzt wäre noch ein Vergleich mit der CMSIS DSP Bibliothek interessant. Vielleicht hat das schon mal jemand gemacht?

Gruss Rolf

Reply to
Rolf Mennekes

Rolf Mennekes :

Interessant liegt dann wohl doch am schlechten Compiler. Pauls Compiler sind wirklich gut, da geht dann meist wirklich nicht mehr viel mehr rauszuquetschen aus den CPU's (selbst wenn man es mit Assembler selber versucht). Schade nur, dass er den MSP430-Compiler jetzt - mangels Nachfrage

- einstellt.

M.

Reply to
Matthias Weingart

Wieso muß man einen Compiler einstellen? Nicht mehr weiterentwickeln oder nicht mehr updaten würde ich verstehen, aber ist ja nicht so, daß ein Compiler Lagerkosten verursachen würde :-)

--
Frank Buss, http://www.frank-buss.de 
electronics and more: http://www.youtube.com/user/frankbuss
Reply to
Frank Buss

Frank Buss :

Anpassung an neue Modelle, gibt da immer mal andere Registersätze usw. - das beeinflusst ja nicht nur die Headerfiles, sondern auch den Debugger und die Flashprogrammierung. Ich versteh das schon, wenn er da gar keine mehr verkauft, hat er da auch keinen Anlass mehr, was dran zu tun - schliesslich bekommt man fast das gleiche kostenlos per Download von TI's Webseite. (Dass der Code 20% groesser wird, stört wohl kaum jemanden). Die andren beiden Compileranbieter Quadravox und ImageCraft sind da wohl auch auf dem Rückzug. Bleiben bloss noch IAR und TI's eigner (mit gcc).

M.

Reply to
Matthias Weingart

Ist doch logisch. Der kostet nur Geld un bringt nix. IMHO wird aber gerade da über Kundenbindung oder -abwanderung entschieden. Gruss Uwe

--------- cut here with a very sharp knife ---------

Uwe Naumann eMail: uwe[at]vieledinge[dot]de

Web:

formatting link
formatting link

Reply to
Uwe Naumann

Exactamente, und einer ist gerade abgewandert. Wird jetzt entweder Freescale, NXP oder TI. Das haette nicht sein muessen und solche Design-Entscheidungen sind nachher de fakto irreversibel. In meinem ersten Job hatte ich das schon, ein Vertriebix war in meinem Buero und flehte mich fast an. Er koenne auch am Preis noch was machen. Ich konnte ihm nur sagen, dass die Entscheidung gefallen ist und ich die ECO nicht neu schreiben werde, weil das viel Arbeit sei. Der hatte fast Traenen in den Augen, weil sein Chef erwartete, dass er mit einem Auftrag zurueck kommt. Den gab's jetzt aber nicht mehr.

Den TSV524 von ST werde ich natuerlich weiterhin einsetzen. Das ist ein gutes Produkt und man braucht keinen Support. Doch damit machen sie keinen fetten Reibach.

--
Gruesse, Joerg 

http://www.analogconsultants.com/
Reply to
Joerg

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.