Guten Morgen werte Kollegen,
Momentan bin ich dabei mich etwas näher mit der PC-Programmierung zu
beschäfitgen, vorrangig in C.
Bisher war ich nur auf dem Mikrocontroller - Embedded - Bereich tätig,
mit allen Vorzügen: einfaches Debuggen und analysieren von z.B. Timings
mittels Pin-Toggeln etc.
Nun bin ich an einem Punkt angekommen, wo ich mal ein par Hinweise und
Tips benötigen könnte (ich zähle auf euch :D):
Der Mikrocontroller sendet ADC-Daten (105 KSp/s, 24-Bit/32-Bit)per UDP
an meinen PC (Ist ein 24-Bit ADC (ADS1271), dessen Daten auf 32-Bit
erweitert werden).
Diese werden erst in einem Array gespeichert (Umwandlung in
32-Bit-Datentyp) und anschließend zum loggen in einer Datei abgelegt.
(Es werden immer 4096 Byte = 1024 Werte in 4 UDP-Paketen empfangen und
dann bearbeitet).
Das Empfangen der Daten dauert momentan ca. 10ms = 1000Werte.
Somit erhalte ich ca. 400KByte/s an Daten die auch alle fehlerfrei
empfangen werden und auch in der Datei richtig abgelegt werden.
Problem:
Diese Daten sollen nun mit der FFTW-Bibliothek analysiert werden.
Das Einbinden und benutzen der FFTW-Lib ist kein Problem und
funktioniert auch ohne Probleme.
Jedoch habe ich keine Ahnung wie lange der PC braucht um eine FFT eines
Datensatzes (1024 Byte) auszuführen.
Das Programm folgt momentan einem linearen Fluss, weshalb ich etwas
Bedenken habe, dass Daten verloren gehen, während die FFT ausgeführt
wird.
Wie erreiche ich also am besten, dass die Daten per UDP gleichzeitig
empfangen werden und verarbeitet werden?
Dabei kann ich durchaus einen kleinen zeitlichen Versatz in Kauf nehmen
nach dem Schema:
1. Fülle Buffer1 mit Daten die empfangen werden (im Hintergrund) und
bearbeite die Daten in Buffer2 währenddessen.
2. Fülle Buffer2 mit Daten die empfangen werden (im Hintergrund) und
bearbeite die Daten in Buffer1....
- Wie lautet hierzu das richtige Stichwort?
- Bin ich mit Threading richtig beraten?
- Wie kann ich genaue Timings am PC messen?
Habe keinen Prallel-Port, nur USB, Ethernet...
PC-System ist ein UBUNTU, Compiler GCC.
Mit Dank und Grüßen im Vorraus,
Tueftler
Aus dem Bauch raus würde ich die beiden Funktionen in eigenständigen
Prozessen realisieren:
-UDP Empfang ganz einfach mit nc/netcat, in eine pipe reinschaufeln
-Analyse/Visualisierung mit deinem C Programm nach Wahl
Etwas kritisch könnte die Puffergrösse der pipe sein, auf meiner Kiste
ist die nur wenige KB (ulimit -a). Die etwas zu Vergrössern schadet
sicher nix, ansonsten wird der schreibende Prozess (nc) blockieren, bis
wieder Platz frei ist.
Tueftler schrieb:> Das Empfangen der Daten dauert momentan ca. 10ms = 1000Werte.>> Somit erhalte ich ca. 400KByte/s an Daten die auch alle fehlerfrei> empfangen werden und auch in der Datei richtig abgelegt werden.>> Problem:> Diese Daten sollen nun mit der FFTW-Bibliothek analysiert werden.> Das Einbinden und benutzen der FFTW-Lib ist kein Problem und> funktioniert auch ohne Probleme.> Jedoch habe ich keine Ahnung wie lange der PC braucht um eine FFT eines> Datensatzes (1024 Byte) auszuführen.
Miss es einfach aus.
Auch auf einem PC gibt es sowas wie einen Clock-Tick, den man abfragen
kann.
Goggle mal nach clock()
Würde mich aber wundern, wenn das auf einem heutigen PC 10ms dauern
würde.
> Wie erreiche ich also am besten, dass die Daten per UDP gleichzeitig> empfangen werden und verarbeitet werden?
Ehe du dich da jetzt in Experimente mit Multithreading einlässt, miss
doch erst mal aus, ob du überhaupt ein Problem hast, das gelöst werden
muss.
Der Ethernet Stack empfängt die Daten ja sowieso schon parallel zu
deinem Programm.
Tueftler schrieb:> Diese werden erst in einem Array gespeichert (Umwandlung in> 32-Bit-Datentyp) und anschließend zum loggen in einer Datei abgelegt.> (Es werden immer 4096 Byte = 1024 Werte in 4 UDP-Paketen empfangen und> dann bearbeitet).> Das Empfangen der Daten dauert momentan ca. 10ms = 1000Werte.
Hast Du daran gedacht, das UDP Pakete auch mal verloren gehen können und
Du dich um diesen Fehlerfall in deiner Software selbst kümmern must?
Wenn möglich würde ich eher TCP verwenden, wobei man das auch später
noch ändern kann.
> Somit erhalte ich ca. 400KByte/s an Daten die auch alle fehlerfrei> empfangen werden und auch in der Datei richtig abgelegt werden.>> Problem:> Diese Daten sollen nun mit der FFTW-Bibliothek analysiert werden.> Das Einbinden und benutzen der FFTW-Lib ist kein Problem und> funktioniert auch ohne Probleme.> Jedoch habe ich keine Ahnung wie lange der PC braucht um eine FFT eines> Datensatzes (1024 Byte) auszuführen.> Das Programm folgt momentan einem linearen Fluss, weshalb ich etwas> Bedenken habe, dass Daten verloren gehen, während die FFT ausgeführt> wird.
Der Linux Kernel wird eine gewisse Menge an Daten Puffern bevor er
anfängt eingehende UDP Pakete zu verwerfen. Wieviel das ist kann ich
jedoch nicht genau sagen. Immer dann wenn dein PC genötigt wird die
Auslagerungspartition zu benutzen könnte es schwierig werden. Auch
dieses Problem würde durch Verwendung von TCP behoben
> Wie erreiche ich also am besten, dass die Daten per UDP gleichzeitig> empfangen werden und verarbeitet werden?> Dabei kann ich durchaus einen kleinen zeitlichen Versatz in Kauf nehmen> nach dem Schema:> 1. Fülle Buffer1 mit Daten die empfangen werden (im Hintergrund) und> bearbeite die Daten in Buffer2 währenddessen.> 2. Fülle Buffer2 mit Daten die empfangen werden (im Hintergrund) und> bearbeite die Daten in Buffer1....>> - Wie lautet hierzu das richtige Stichwort?> - Bin ich mit Threading richtig beraten?> - Wie kann ich genaue Timings am PC messen?> Habe keinen Prallel-Port, nur USB, Ethernet...
Ja, Multithreading ist dazu ein guter Ansatz. Du möchtest einen
Ringpuffer verwenden. Normalerweise sollte aber die Rechenleistung
locker ausreichen um das linear abzuarbeiten - auch hier, TCP hilft Dir.
Um die Timings in dem Programm zu bestimmen kannst Du gprof benutzen.
Einführung z.B. hier:
http://www.linuxfocus.org/Deutsch/March2005/article371.shtml. Mit den
richtigen Optionen kann man Timings auch für jede einzelne Programmzeile
bestimmen. Denke aber daran, das ein PC kein deterministisches System
wie ein Mikrocontroller ist. Die Timings können sich von Aufruf zu
Aufruf ändern und hängen von zig Einflüssen ab, u.a.:
- aktive Programme
- Netzwerkverkehr
- Nutzerinteraktion
Daher, nimm TCP und Du hast es viel einfacher.
Hallo,
herzlichen Dank für eure zahlreichen Antworten!
Inzwischen läuft die Sache recht gut! Zum Glück ohne weiteres Threading.
Bin
@Tom:
Tom M. schrieb:> -UDP Empfang ganz einfach mit nc/netcat, in eine pipe reinschaufeln> -Analyse/Visualisierung mit deinem C Programm nach Wahl>> Etwas kritisch könnte die Puffergrösse der pipe sein, auf meiner Kiste> ist die nur wenige KB (ulimit -a). Die etwas zu Vergrössern schadet> sicher nix, ansonsten wird der schreibende Prozess (nc) blockieren, bis> wieder Platz frei ist.
Habe anfangs auch mit NetCat experimentiert, als ich auf dem
Mikrocontroller den LwIP-Stack in Betrieb genommen habe.
Verwundert war ich darüber, dass immer maximal 1024 Byte angekommen
sind, egal wieviele ich per UDP gesendet habe... und par tout keinen
Fehler in meinem MC-Programm finden konnte. Da hat NC anscheinend einen
Bug (siehe auch Internet). Von daher war ich mit NC erstmal bedient.
@Karl:
Karl Heinz Buchegger schrieb:> Miss es einfach aus.> Auch auf einem PC gibt es sowas wie einen Clock-Tick, den man abfragen> kann.> Goggle mal nach clock()>> Würde mich aber wundern, wenn das auf einem heutigen PC 10ms dauern> würde.
Mit clock() hats leider nicht funktioniert, evtl. hat mein System-Timer
eine zu geringe Auflösung?!
Mit clock_gettime() funktioniert es und es werden sogar Nanosekunden
ausgegeben... (Wie genau das wohl ist....?!)
http://linux.die.net/man/3/clock_gettime
Habe dann die Zeitfresser identifiziert und wandle nun nur int32_t in
strings um und keine float um die Daten zu loggen.
Den größten Einfluss hatte aber immer noch die Optimierung, nun auf 3
gesetzt.
Somit benötigt die FFT über 4096 (rein Rellwertige Float-)Datenpunkte
zwischen 70...200 Micro-Sekunden.
@Andreas:
Andreas Messer schrieb:> Hast Du daran gedacht, das UDP Pakete auch mal verloren gehen können und> Du dich um diesen Fehlerfall in deiner Software selbst kümmern must?> Wenn möglich würde ich eher TCP verwenden, wobei man das auch später> noch ändern kann.
Habe mich gerade für UDP entschieden, da es einen geringeren Overhead
hat und damit vermutlich auch schneller ist?!
Momentan ist der MC mit dem PC über einen Router verbunden, an dem
nichts weiter hängt, von daher hoffe ich, dass da nichts verloren geht,
werde aber in Zukunft vielleicht noch einen Index mitschicken, der es
dann ermöglicht die Daten auf Konsistenz zu prüfen.
Vielen Dankf für den Link,
Sieht sehr interessant aus, werde ich gleich mal probieren,
Profiling-Daten zu erstellen um zu sehen, wo sich das Programm die
meiste Zeit aufhält. (Vermutlich in der UDP-Empfangsroutine, wo erstmal
16 Pakete zu je 1024Byte gesammelt werden).
So Long,
Vielen Dank,
Tueftler
Ich wuerde mit Integern arbeiten, nicht mit float und auch nicht mit
strings.
UDP ist das Mittel der Wahl wenn man ein verlorenses Packet verschmerzen
kann, wenn Geschwindigkeit wichtiger ist. zB Bild und Ton werden als UDP
uebertragen. TCP ist das mittel der Wahl wenn alles sicher ankommen
muss, zb bei eibem filetransfer.
Hallo,
falls du Multi-Threading und/oder grafische Oberfläche programmieren
möchtest könntest PureBasic benutzen.
http://www.purebasic.com/german/index.php
Die Sprache hat nur minimale Geschwindigkeitseinbusen gegenüber gutem C
Code und für Multithreading schreibt man eine ganz normale Funktion und
führt sie mit einer Befehlszeile lediglich asynchron zum Hauptprogramm
aus. Es kann auch sehr einfach auf C - Bibliotheken zugegriffen werden.
Die Hilfe ist auch außergewöhnlich gut (in Deutsch, Englisch und
Französisch vorhanden) mit sehr vielen querverweisen zu hilfreichen
Befehlen. Der Aufbau ist sehr stark mit C verwandt.
Ja, ich weiß es ist eine kostenpflichtige Sprache, allerdings halten
sich die Kosten mit 80€ in Grenzen und die Lizenzbedingungen sind
traumhaft. Zudem ist sie nahezu Plattformunabhängig (kann auf
Windows/Linux/Mac kompiliert werden).
Gruß Kai