SSE Shift-Intrinsics



  • Hallo,
    Ich habe mich in den letzten Tagen ein wenig mit SSE beschäftigt, aber zum Teil findet man zu den unterschiedlichen Funktionen nur wenig Beispiele, die mir weiterhelfen könnten.

    Im Folgenden habe ich ein m128 register und möchte auf jeden der 4 int's den Rechts-Shift Operator anwenden. Dazu folgender Code:

    __m128i test=_mm_set1_epi32(128);
        __m128i SHIFT=_mm_set_epi32(1,1,1,1);
    
        __m128i ergb =_mm_srl_epi32(test,SHIFT);
    
         int output =_mm_cvtsi128_si32(ergb);
        std::cout<<output<<std::endl;
    

    Als Ergebnis erhalte ich hier 0, würde aber eigentlich 64 erwarten.
    Habe alle Informationen zu der Funktion in der Dokumentation von Intel gefunden https://msdn.microsoft.com/en-us/library/w486zcfa(v=vs.90).aspx

    Laut Dokumentation, falls ich das richtig verstehe, müsste das Ergebnis eigentlich 64 sein.

    Würde mich freuen, wenn sich Jemand, der Erfahrung mit SSE hat, dazu einmal melden könnte

    Gruss

    Robin Messemer



  • Die Doku sieht für mich so aus als würde der 2. Operand von _mm_srl_epi32 nicht als Vektor interpretiert sondern einfach als 128 Bit Integer. Probier mal _mm_srli_epi32(test, 1) statt dessen.



  • CheckersGuy schrieb:

    Habe alle Informationen zu der Funktion in der Dokumentation von Intel gefunden https://msdn.microsoft.com/en-us/library/w486zcfa(v=vs.90).aspx

    Das ist nicht die Doku von Intel, sondern die von MS. Es empfielt sich, tatsächlich mal bei Intel nachzuschlagen:

    https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srl_epi32&expand=5110,5080

    Diese Doku ist auf jeden Fall deutlich informativer, vor allem da man für jede Funktion im Zweifelsfall den angegebenen Pseudocode konsultieren kann,
    und auch die Performance-Angaben sind praktisch für etwaige Mikro-Optimierungen.

    Bezüglich deines Ergebnisses passiert wohl folgendes (richtig getippt, @hustbaer):
    count wird zwar in einem 128-Bit-Register übergeben, davon werden aber nur die unteren 64 Bit für den count herangezogen.
    Ist dieser count größer als 31 werden alle 4 Integer auf 0 gesetzt (alle Bits rechts rausgeshiftet) - siehe Pseudocode.
    Nun setzt du allerdings mit _mm_set_epi32() jeden der 4 32-Bit-Integer auf 1, d.h. die unteren 64 Bit sind 1 << 32 + 1 = 4294967297 .
    Das ist definitiv größer als 31 😉

    Versuchs mal mit der von hustbaer vorgeschlagenen Funktion, oder mit:

    __m128i SHIFT=_mm_set_epi32(0,0,0,1);
    

    Ich denke das liefert das Ergebnis, das du erwartest.

    Zusatz: Die Funktion _mm_srlv_epi32() verhält sich so, wie du es wahrscheinlich hier erwartet hast (unabhängige Shift-Counts für jeden der 4 Integer).
    Diese ist jedoch eine AVX2-Funktion (ab Haswell, Mitte 2013) - bei meiner betagten Mühle, auf der ich das hier gerade schreibe, wäre das ein Illegal-Instruction-Crash ;).


Log in to reply