Vermutlich simpel, aber komme gerade nicht drauf: es geht um rechenzeit-optimiertes Kopieren von Buffern.
Gegegeben ist ein größerer uint8_t-Buffer der prozesssicher in einem Mehrkern-uC als Ringbuffer mit 16 Bit-Wörter gefüllt wird. Zyklisch werden bei ausreichendem Füllstand wieder 16-Bit-Werte entnommen.
So wie im Beispiel funktioniert die Sache, aber geht das nicht effizienter ohne schieben und addieren? Also direkt aus dem 8 Bit Buffer zwei Wörter zu einem 16 Bit Wort kopieren?
Muss man den Endian-Mode beachten, letztlich läuft das auf einem ARM.
Wie sähe der C-Syntax dafür aus?
Alignment aufpassen! Wenn man Zugriffe mit 16 oder 32 bit grösse macht, etwarten viele Architekturen auch addressen die 16 oder 32bit aligned sind. Aus einer 8bit char buffer kann man deswegen nicht immer gleich 32 bit auskopieren. Klar wenn alignment stimmt geht.
Sonst ein memcpy müsste eigentlich das können. Gut implementationen sehen nach ob man am anfang oder ende noch 8bit weise kopiert. Dazwischen aber 32 bit weise. Teilweise gibt es architekturen wo der RAM eh 64bit breit ist (oder noch breiter) wegen ECC. Da kann man richtig gas geben, denn man kann 64bit weise kopieren.
Teilweise gibt es architekturen wo der RAM
eh 64bit breit ist (oder noch breiter) wegen ECC. Da kann man richtig
gas geben, denn man kann 64bit weise kopieren.
Das landet doch sowieso zuerst in den CPU Caches, da wird der RAM vermutlich keinen unterschied sehen.
Danke für die Hinweise.
Hat auch auf dem ARM funktioniert. Das Alignment müsste man vermutlich beim Anlegen des Buffers prüfen?
Wäre jetzt davon Ausgegangen, dass der Compiler das nicht schräg über Wortgrenzen legt.
Gegegeben ist ein größerer uint8_t-Buffer der prozesssicher in einem
Mehrkern-uC als Ringbuffer mit 16 Bit-Wörter gefüllt wird. Zyklisch
werden bei ausreichendem Füllstand wieder 16-Bit-Werte entnommen.
Warum dann nicht gleich ein int16_t Array anlegen? Dann stimmt auch das Alignment.
Brauchst du wirklich eine kopie, oder reicht dir der Zugriff auf 8Bit bzw. 16Bit Ebene? Wenn es Keine Kopie sein muss, dann kannst du auch ein Union anlegen.
Falls es doch eine Kopie sein soll:
kopieren via Pointer (Dann gleich mit maximaler Bitbreite kopieren(32Bit?)
Auch auf allen anderen Architekturen sollte man nichts eigenes machen.
Die Compiler optimieren meist besser als man selber.
Wenn du als Optimierung -O3 eingestellt hast, wird er vermutlich Intrinsic Funktionen nutzen.
Das einzige auf was man selber achten sollte ist das Alignment wie oben beschrieben.
Gegegeben ist ein größerer uint8_t-Buffer der prozesssicher in einem
Mehrkern-uC als Ringbuffer mit 16 Bit-Wörter gefüllt wird. Zyklisch
werden bei ausreichendem Füllstand wieder 16-Bit-Werte entnommen.
Sorry für die verzögerte Reaktion, komme heute nur sehr sporadisch Zugriff zum Forum. Irgendwas hakelt.
Endian Mode dürfte in der Tat egal sein, da ja alles auf einem Prozessor läuft. Kann doch eigentlich nur beim Transport über Grenzen schief gehen. Denke, dass ARM big endian ist. Und x86 little endian. Jedenfalls sah die Byteanordnung im Testprogramm auf dem PC so aus.
RING_BUFFER_SIZE_TYPE ist uint16_t, uint8_t* vals mit dem eigentlichen Bufferspeicher verbunden. ring_buffer_t eine Struktur.
Letztlich gab es noch eine einfachere Variante die 16-Bit-Wörter aus dem 8-Bit Bufferspeicher zu ziehen, aber das konntet ihr mangels Infos nicht ahnen und ich bin mir nicht sicher ob der (uint8_t *)-Cast auf ein int16_t-Array guter Stil ist. Funktionieren tut es, decodebuf enthält die gewünschten 16Bit-Werte.
DMA. Der Pico hat so viele Kanäle davon, dass man die sogar gefahr- und
kostenlos nutzen kann.
eh, guter Tipp. Vier werden bereits benutzt, aber da ist noch Luft. Versuche ich beim Optimieren.
Leider ist das SDK qualitätsmäßig so mies, dass man den Debugger nicht nutzen kann. stdio_init_all(); stürzt zuverlässig ab.
Normales Compilieren und Laden geht, aber ohne Debugger äußerst lästig.
So wie im Beispiel funktioniert die Sache, aber geht das nicht
effizienter ohne schieben und addieren? Also direkt aus dem 8 Bit Buffer
zwei Wörter zu einem 16 Bit Wort kopieren?
Müsste mit logischen Operationen gehen.
Das Hintergrundproblem ist hier die Umwandlung des Datenformats.
Schaut man sich ein wenig um, könnte man sich noch auf memcpy stürzen (schneller machen), bzw. sich auf das Allignment konzentrieren, und memcpy weitgehend weglassen.
Teilweise sind die angesprochenen Sachen hier sehr Hardware- bzw. Compilerabhängig.
Eine eigene Frage?
Dieser Thread ist über 11 Monate alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.