Frage an avx, sse, c – Wie führe ich eine elementweise Linksverschiebung mit __m128i durch?

4

Die SSE-Verschiebungsanweisungen, die ich gefunden habe, können bei allen Elementen nur um den gleichen Betrag verschoben werden:

_mm_sll_epi32()_mm_slli_epi32()

Diese verschieben alle Elemente, jedoch um den gleichen Verschiebungsbetrag.

Gibt es eine Möglichkeit, den verschiedenen Elementen unterschiedliche Verschiebungen zuzuweisen? Etwas wie das:

__m128i a,  __m128i b;  

r0:=    a0  <<  b0;
r1:=    a1  <<  b1;
r2:=    a2  <<  b2;
r3:=    a3  <<  b3;

Deine Antwort

3   die antwort
7

_mm_shl_epi32() intrinsic das macht genau das.

http://msdn.microsoft.com/en-us/library/gg445138.aspx

Es erfordert jedoch dieXOP-Befehlssatz. Nur AMD Bulldozer- und Interlagos-Prozessoren oder höher verfügen über diese Anweisung. Es ist auf keinem Intel-Prozessor verfügbar.

Wenn Sie es ohne XOP-Anweisungen tun möchten, müssen Sie es auf die harte Tour tun: Ziehen Sie sie heraus und tun Sie sie nacheinander.

Ohne XOP-Anweisungen können Sie dies mit SSE4.1 unter Verwendung der folgenden Eigenschaften tun:

_mm_insert_epi32()_mm_extract_epi32()

http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011/compiler_c/intref_cls/common/intref_sse41_reg_ins_ext.htm

Mit diesen können Sie Teile eines 128-Bit-Registers in reguläre Register extrahieren, um die Verschiebung durchzuführen und sie zurückzusetzen.

Wenn Sie sich für die letztgenannte Methode entscheiden, wird sie fürchterlich ineffizient sein. Deshalb_mm_shl_epi32() existiert in erster Linie.

0

In einigen Fällen kann dies ersetzen_mm_shl_epi32(a, b):

_mm_mullo_ps(a, 1 << b);

Im Allgemeinen erfordert diesb einen konstanten Wert zu haben - ich kenne keinen effizienten Weg zu berechnen(1 << b) mit älteren SSE-Anweisungen.

2

unt-Arguments steuern können, können Sie verwenden_mm_mullo_pi16 da das Multiplizieren mit einer Potenz von zwei dasselbe ist wie das Verschieben mit dieser Potenz.

Zum Beispiel, wenn Sie Ihre 8 16-Bit-Elemente in einem SSE-Register um verschieben möchten<0, 1, 2, 3, 4, 5, 6, 7> Sie können mit 2 multiplizieren, das heißt mit<0, 2, 4, 8, 16, 32, 64, 128>.

Danke, ich habe es mit _mm_mullo_epi32 (SSE4.1) geschafft. Hmm ..., könnte es einen besseren Weg für die Intel-CPU geben? user1468756

Verwandte Fragen