Hi, ich hatte heute morgen einen Einfall: kann man auf einer 32-Bit MCU (in meinem Fall einen STM32 (Cortex m3), die an sich keine SIMD-Befehle kennt, 16-Bit Daten Parallel rechen? Ich mein, eigentlich wäre es naheliegend, ich sehe nur ein paar Probleme. Wenn ich jetzt Daten von zum Beispiel dem DMA an eine Stelle im Speicher bringen lasse, und dann jeweils zwei aufeinander folgende uint16_t als einen uint32_t auffasse, dann kann ich mit den 32-Bit Zahlen rechnen, und so zwei 16-Bit Rechnungen einsparen, oder? Beispiel für Addition: int32 summand_a, summand_b: 0xxxxxxxxxxxxxxx0xxxxxxxxxxxxxxx ^ ^ Beginn Wert1 Beginn Wert2 (erste Stelle muss 0 sein, damit keine Überläufe passieren können) int32 ergebnis = summand_a + summand_b; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ^ ^ Beginn Wert1 Beginn Wert2 (Jetzt ist die erste stelle möglicherweise auch belegt) Analog sollte auch die Mulatiplikation gehen, nur dass ich da dann eben mehr Platz brauche, um Überläufe zu vermeiden. Bis jetzt denke ich, dass das ganze noch ganz gut möglich sein müsste, aber wenn ich statt mit integern mit Fixkommazahlen arbeite, wird das schwierig: Bei einer Fixkomma-Multiplikation muss ich nach der normalen Multiplikation ja nochmal durch den Skalierungsfaktor teilen, normalerweise mache ich das, indem ich einen Skalierungsfaktor habe, der eine zweierpotenz ist, und dann einfach Linkschifts ausführe. Der Cortex-M3 kann schönerweise direkt im gleichen Takt nach einer Addition, Subtraktion oder Muliplikation eine Schiftoperation ausführen, sodass. Aber wenn ich jetzt mit meinen Ergebnissen weiterrechnen will, habe ich das Problem, dass in meinem unteren Halbwort ja jetzt dann Quasi die Datenleichen des oberen Halbwortes liegen. Und wenn ich jetzt weiterrechne, dann machen die mein Ergebnis zwar nicht falsch, aber in sofern anders, als dass ich dann im oberen Halbwort mit einer Genauigkeit rechne, die beim unteren Halbwort (wie es nunmal bei Fixkommarechnung üblich ist) abgeschnitten ist. Um das zu vermeiden, müsste ich also die die Ergebnisse mit einer Maske von den Datenleichen befreien, quasi so: //skalierungsfaktor = 16 = (2^4) => uint16_t Wert = xxxxxxxxxxxx,xxxx uint32_t ergebnis = uint32_t multiplikator * uint32_t multiplikant; ergebnis = (ergebnis>>4); erbehnis = (ergebnis & (00001111111111110000111111111111); Und damit habe ich doch im Prinzip den Vorteil, den ich mit dem doppelten Rechnen gewonnen habe wieder verspielt, oder? Zumindest, wenn die Multiplikation nur einen Taktzyklus dauert. Additionen sollten damit bei geeigneten eingangsdaten um den Faktor zwei schneller gerechnet werden können, bei Multiplikationen seh ich jetzt noch keinen Vorteil, wenn die Rechnungen vergleichbar sein sollen, weil wenn man die Maskierung weglässt, dann werden die Ergebnisse ja auch nicht falsch, sondern nur eines genauer. Man muss dann nur zum Schluss, wenn man wieder mit einzelnen Datenteilen Weiterarbeitet einmalig die Maskierung machen. Jedenfalls wollte ich diese Idee mal mit euch teilen, vielleicht hilft es jemandem, vielleicht hat jemand eine Idee, wie man an dem ganzen noch etwas verbessern kann. Gruß, Mox-Mox
Ich denk nicht, daß ma damit nen Blumentopf gewinnt. Zum einen müssen die Daten ein- und ausgepackt werden, was Zeit und Speicherplatz kostet, zum anderen kann man kaum was mit dem Zeug machen ausser addieren, und je mehr Additionen man auf den gleichen Daten macht, desto kleiner werden die erlaubten Datenbereiche. Oder man muss nach jeder Addition ne Maske drüberlegen. Die Einschränkungen an Subtraktion sind noch unangenehmer. Ein SIMD-Ansatz ist erst dann sinnvoll, wenn alle Instruktionen, die man so braucht, ohne größeren Widerstand umsetzbar sind. Am ehesten geht das für die Gruppe der Bitoperationen wie &,|,~,^ Sobald das, was man an Operationen braucht, darüber hinausgeht, wird's echt eklig und ausser dem dauernden Ein-/Auspacken verunstaltet man die Quelle durch Makros/Inline-Funktionen oder Builtins.
Moritz Nöltner schrieb: > Hi, ich hatte heute morgen einen Einfall: kann man auf einer 32-Bit MCU > (in meinem Fall einen STM32 (Cortex m3), die an sich keine SIMD-Befehle > kennt, 16-Bit Daten Parallel rechen? Man könnte sich auch einfach zurücklehnen und auf Cortex-M4 Devices warten. Den hat ST schließlich ebenfalls lizensiert. -- Marcus
Johann L. schrieb: > Zum einen müssen die Daten ein- und ausgepackt werden, was Zeit und > Speicherplatz kostet,.. Ich weis nicht genau, wo Du beim Ein- und Auspacken ein Problem siehst. Wenn man eine Anwendung hat, bei der man größere Datenmengen anfallen, dann wird man die (sofern man das wie bei den STM32 kann) die Daten von dem DMA dahin bringen lassen, wo man sie haben will. Zum Beispiel liefern mir die beiden ADC jweils einen 12-Bit Wert, aber es werden schon immer zwei Werte auf einmal von der DMA übertragen und wahlweise auch so abgelegt (ist die die schnellste Art Daten zu verschicken, so gehn die in einem Bustakt durch die Leitung, sonst wären es mehr). Und damit habe ich, wenn ich die ADC-Werte hintereinander im Speicher ablege, meine Daten perfekt angeordnet. Und dann kommt es nur noch drauf an, als was ich sie denn nun anspreche. Kostet also keinen (zusätzlichen) Speicherplatz und eigentlich auch keine Zeit. (kann man einfach ein riesiges Union draus machen:
1 | union |
2 | { |
3 | array_32[x]; |
4 | array_16[2x]; |
5 | } |
Johann L. schrieb: > ...zum anderen kann man kaum was mit dem Zeug machen > ausser addieren, und je mehr Additionen man auf den gleichen Daten > macht, desto kleiner werden die erlaubten Datenbereiche. Naja, das ist doch aber immer so bei Fixkommaberechnungen, oder? Ich mein, wenn ich da nicht nach jeder Operation auf nen Überfluss prüfen will, dann werde ich das so auslegen müssen, dass da nix überläuft. Mit allen Konsequenzen, und eben auch, dann ich genau überlegen muss, wieviel Bits ich brauche. Wenn 16-Bit Rechnungen nicht reichen, dann ist der Ansatz zugegebenermaßen nicht verwendbar. Andererseits gibts genügent Dinge, die sich mit 8-Bit rechnen lassen, siehe AVR und Co. Johann L. schrieb: > Oder man muss > nach jeder Addition ne Maske drüberlegen. Inwiefern sollte denn eine Maske helfen, überläufe bei Additionen abzufangen? Damit würde ich ja nur bestenfalls meine jeweiligen MSBs abschneiden. Marcus Harnisch schrieb: > Man könnte sich auch einfach zurücklehnen und auf Cortex-M4 Devices > warten. Den hat ST schließlich ebenfalls lizensiert. Klar kann man. ST hat da einige Süppchen am kochen, auf die ich mich freu. Aber ich will jetzt was machen, und eigentlich denk ich, das der STM32 schon fast zu groß wär dafür, wenn ich nicht Wert darauf legen würde, dass es wirklich schnell geht. Also versuch ich doch eher, das, was ich habe, effizient zu nutzen.
Moritz Nöltner schrieb: > Aber ich will jetzt was machen, und eigentlich denk ich, das der > STM32 schon fast zu groß wär dafür, wenn ich nicht Wert darauf legen > würde, dass es wirklich schnell geht. Also versuch ich doch eher, das, > was ich habe, effizient zu nutzen. Klar. Aber, da Du Dir anscheinend bereits Gedanken über Nebeneffekte gemacht hast, warum versuchst Du es nicht einfach? Aber vergiss nicht, das Ergebnis mit "normalem" Code zu vergleichen. Ich vermute, dass sich der Aufwand dieses "SIMD für Arme" nicht lohnt. Was Dich Deinem Ziel etwas näher bringen könnte und relativ wenig Stress macht ist das Laden der Wertepaare mit einem einzelnen Wortzugriff (array of unions, anstatt union of arrays). Lokal werden die Worte dann wieder aufgeteilt. Spart ein paar Speicherzugriffe. Gruß Marcus
Jau, wenn ich dazu komm, und noch ein paar andere Unbekannte klarer sind (zum Beispiel die Dimensionierung von Fixpnktzahlen) dann werd ich das testen. Aber für jetzt mal danke für die Antworten.
Die Idee mit dem Software-SIMD (also eben ohne H/W-SIMD Unterstützung) hatte schon jemand vor Dir: Stefan Kraemer, Rainer Leupers, Gerd Ascheid, Heinrich Meyr: SoftSIMD - exploiting subword parallelism using source code transformations Proceedings of the Conference on Design, Automation and Test in Europe http://portal.acm.org/citation.cfm?id=1266660&dl=GUIDE&coll=GUIDE&CFID=89273050&CFTOKEN=43293959 Murkser
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.