Ottenendo il valore massimo in un vettore __m128i con SSE?

Ho appena iniziato a utilizzare SSE e sono confuso su come ottenere il valore intero massimo ( max ) di un __m128i . Per esempio:

 __m128i t = _mm_setr_ps(0,1,2,3); // max(t) = 3; 

La ricerca in giro mi ha portato all’istruzione MAXPS ma non riesco a trovare come usarlo con "xmmintrin.h" .

Inoltre, c’è qualche documentazione per "xmmintrin.h" che consiglieresti, piuttosto che esaminare il file di intestazione stesso?

Se ti ritrovi a dover eseguire operazioni orizzontali sui vettori, specialmente se si trova all’interno di un ciclo interno, di solito è un segno che ti stai avvicinando all’implementazione SIMD nel modo sbagliato. A SIMD piace operare in base agli elementi sui vettori – “verticalmente” se vuoi, non in orizzontale.

Per quanto riguarda la documentazione, c’è un riferimento molto utile su intel.com che contiene tutti gli opcode e gli elementi intrinseci per qualsiasi cosa, da MMX alle diverse versioni di SSE fino a AVX e AVX-512.

Nel caso in cui qualcuno si preoccupi e dal momento che gli intrinsechi sembrano essere la strada da percorrere in questi giorni qui è una soluzione in termini di intrinseca.

 int horizontal_max_Vec4i(__m128i x) { __m128i max1 = _mm_shuffle_epi32(x, _MM_SHUFFLE(0,0,3,2)); __m128i max2 = _mm_max_epi32(x,max1); __m128i max3 = _mm_shuffle_epi32(max2, _MM_SHUFFLE(0,0,0,1)); __m128i max4 = _mm_max_epi32(max2,max3); return _mm_cvtsi128_si32(max4); } 

Non so se sia meglio di questo:

 int horizontal_max_Vec4i(__m128i x) { int result[4] __attribute__((aligned(16))) = {0}; _mm_store_si128((__m128i *) result, x); return max(max(max(result[0], result[1]), result[2]), result[3]); } 

Secondo questa pagina , non esiste un massimo orizzontale, e devi testare gli elementi verticalmente:

 movhlps xmm1,xmm0 ; Move top two floats to lower part of xmm1 maxps xmm0,xmm1 ; Get maximum of the two sets of floats pshufd xmm1,xmm0,$55 ; Move second float to lower part of xmm1 maxps xmm0,xmm1 ; Get minimum of the two remaining floats 

Viceversa, ottenendo il minimo:

 movhlps xmm1,xmm0 minps xmm0,xmm1 pshufd xmm1,xmm0,$55 minps xmm0,xmm1 

Non esiste un opcode Maximum Horizontal in SSE (almeno fino al punto in cui ho smesso di tenere traccia delle nuove istruzioni SSE).

Quindi sei bloccato a fare un po ‘di mischia. Quello con cui finisci è …

 movhlps %xmm0, %xmm1 # Move top two floats to lower part of %xmm1 maxps %xmm1, %xmm0 # Get minimum of sets of two floats pshufd $0x55, %xmm0, %xmm1 # Move second float to lower part of %xmm1 maxps %xmm1, %xmm0 # Get minimum of all four floats originally in %xmm0 

http://locklessinc.com/articles/instruction_wishlist/

MSDN ha i mapping di funzioni intrinseche e macro documentate

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