2017-01-12 2 views
3

Ich möchte maximal zwei Vektoren mit 8 x 16 Bit unsigned int Elemente finden.SSE2 intrinsics - finden Sie Max von zwei vorzeichenlosen kurzen Vektoren

__m128i vi_A= _mm_loadu_si128(reinterpret_cast<const __m128i*>(&pSrc[0])); // 8 16-Bit Elements 
__m128i vi_B= _mm_loadu_si128(reinterpret_cast<const __m128i*>(&pSrc1[0])); // 8 16-Bit Elements 
__m128i vi_Max = _mm_max_epi16(vi_A,vi_B); //<-- Error 

Aber diese _mm_max_epi16 ist ein signierter int Vergleich und dieser Überlauf verursacht. Also habe ich versucht, die unsignierte Version zu verwenden, indem SSE4.1- intrinsische

vi_Max = _mm_max_epu16(vi_A,vi_B); 

verwenden, aber ich bin nicht zu verwenden SSE4.1- intrinsics erlaubt. Was ist der effiziente Weg, das Maximum dieser Elemente zu finden?

Antwort

4

One (etwas ineffizient) so, wie es ist, um die Eingangswerte von 0x8000 zu versetzen und dann hinzuzufügen, dies zu tun, um das Ergebnis Offset zurück, zum Beispiel:

#ifndef __SSE4_1__ 
inline __m128i _mm_max_epu16(const __m128i v0, const __m128i v1) 
{ 
    return _mm_add_epi16(
       _mm_max_epi16(
        _mm_sub_epi16(v0, _mm_set1_epi16(0x8000)), 
        _mm_sub_epi16(v1, _mm_set1_epi16(0x8000))), 
       _mm_set1_epi16(0x8000)); 
} 
#endif 

gcc oder clang diese Instruktion eine Last erzeugt für die konstante und vier arithmetische Anweisungen.


Beachten Sie, dass Sie _mm_xor_si128 anstelle von _mm_add_epi16/ _mm_sub_epi16, das ist wohl klare Absicht verwenden können, und ein bessere Leistung auf der Zielarchitektur geben können:

#ifndef __SSE4_1__ 
inline __m128i _mm_max_epu16(const __m128i v0, const __m128i v1) 
{ 
    return _mm_xor_si128(
       _mm_max_epi16(
        _mm_xor_si128(v0, _mm_set1_epi16(0x8000)), 
        _mm_xor_si128(v1, _mm_set1_epi16(0x8000))), 
       _mm_set1_epi16(0x8000)); 
} 
#endif 
+1

für Ihre schnelle Antwort Danke Wow! Es funktionierte wie Charme! –

+0

XORing ist sehr wahrscheinlich schneller, aber noch wichtiger, es beseitigt die Möglichkeit eines Überlaufs. –

+1

@CodyGray was Überlauf? das Addieren/Subtrahieren/Xorieren eines 16Bit Int mit 0x8000 sind alle genau gleich, ohne Kantenfälle – harold

Verwandte Themen