Ich muss große Arrays von 16-Bit-Integer-Werten vom Big-Endian- in das Little-Endian-Format konvertieren.
Jetzt verwende ich zur Konvertierung die folgende Funktion:
%Vor%Ich benutze GCC. Zielplattform ist ARMv7 (Raspberry Phi 2B).
Gibt es eine Möglichkeit, es zu optimieren?
Diese Umwandlung wird benötigt, um Audio-Samples zu laden, die wie im Little-Endian-Format oder im Big-Endian-Format vorliegen können. Natürlich ist es jetzt kein Engpass, aber es dauert etwa 10% der gesamten Verarbeitungszeit. Und ich denke, das ist zu viel für solch eine einfache Operation.
Wenn Sie die Leistung Ihres Codes verbessern möchten, können Sie Folgendes machen:
1) Verarbeitung von 4 Bytes für einen Schritt:
%Vor%Wenn Sie eine 64-Bit-Plattform verwenden, ist es möglich, 8 Bytes für einen Schritt auf die gleiche Weise zu verarbeiten.
2) Die ARMv7-Plattform unterstützt SIMD-Anweisungen mit der Bezeichnung NEON. Mit der Verwendung von ihnen können Sie Code noch schneller als in 1) machen:
%Vor%wird
%Vor%Sie könnten also als (gcc-explorer: Ссылка )
geschrieben werden %Vor%was für die Schleife
sorgen sollte %Vor% Lesen Sie mehr über __builtin_bswap16
unter GCC buildin docs .
Neonvorschlag (irgendwie getestet, gcc-explorer: Ссылка ):
%Vor%was wird
%Vor%Siehe mehr über Neon-Intrinsik hier: Ссылка
Bonus von ARM ARM A8.8.386:
VREV16 (Vector Reverse in Halbworten) kehrt die Reihenfolge der 8-Bit-Elemente in jedem Halbwort des Vektors um und ordnet das Ergebnis dem entsprechenden Zielvektor zu.
VREV32 (Vektorumkehrung in Worten) kehrt die Reihenfolge von 8-Bit- oder 16-Bit-Elementen in jedem Wort des Vektors um und platziert das Ergebnis im entsprechenden Zielvektor.
VREV64 (Vector Reverse in Doppelworten) kehrt die Reihenfolge von 8-Bit-, 16-Bit- oder 32-Bit-Elementen in jedem Doppelwort des Vektors um und ordnet das Ergebnis dem entsprechenden Zielvektor zu .
Es gibt keinen Unterschied zwischen Datentypen außer der Größe.
Ich weiß nicht viel über ARM-Befehlssätze, aber ich denke, es gibt einige spezielle Anweisungen zur Endianess-Konvertierung. Anscheinend hat ARMv7 Dinge wie rev etc.
Haben Sie den Compiler intrinsic __builtin_bswap16
ausprobiert? Es sollte zu CPU-spezifischem Code, z.B. rev auf ARM. Außerdem hilft es dem Compiler zu erkennen, dass Sie tatsächlich einen Byte-Austausch durchführen, und führt andere Optimierungen mit diesem Wissen durch, z. eliminiere überflüssige Byte-Swaps vollständig in Fällen wie y=swap(x); y &= some_value; x = swap(y);
.
Ich habe ein wenig gegoogelt und in diesem Thread geht es um ein Problem mit dem Optimierungspotenzial . Laut dieser Diskussion kann der Compiler die Konvertierung auch vektorisieren, wenn die CPU dies unterstützt die Anweisung vrev
NEON.
Sie möchten messen, was schneller ist, aber ein alternativer Körper für Reorder16bit
wäre
unter der Annahme, dass Ihre Muttersprachen Little-Endian sind. Eine andere Möglichkeit:
%Vor%