Schnelle Konvertierung von 16-Bit-Big-Endian zu Little-Endian in ARM

7

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.

    
Peter O. 26.11.2015, 06:36
quelle

5 Antworten

8

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%     
ErmIg 26.11.2015, 06:44
quelle
7

Ссылка

%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.

    
auselen 26.11.2015 09:48
quelle
6

Wenn es speziell für ARM ist, gibt es eine REV-Anweisung, speziell REV16, die zwei 16-Bit-Ints gleichzeitig ausführt.

    
Colin__s 26.11.2015 07:53
quelle
6

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.

    
Jens 26.11.2015 08:22
quelle
2

Sie möchten messen, was schneller ist, aber ein alternativer Körper für Reorder16bit wäre

%Vor%

unter der Annahme, dass Ihre Muttersprachen Little-Endian sind. Eine andere Möglichkeit:

%Vor%     
1201ProgramAlarm 26.11.2015 06:43
quelle

Tags und Links