Question

I am developing a performance critical application which has to be ported into Intel Atom processor which just supports MMX, SSE, SSE2 and SSE3. My previous application had support for SSSE3 as well as AVX now I want to downgrade it to Intel Atom processor(MMX, SSE, SSE2, SSE3).

There is a serious performance downgrade when I replace ssse3 instruction particularly _mm_hadd_epi16 with this code

RegTemp1 = _mm_setr_epi16(RegtempRes1.m128i_i16[0], RegtempRes1.m128i_i16[2], 
                          RegtempRes1.m128i_i16[4], RegtempRes1.m128i_i16[6],
                          Regfilter.m128i_i16[0],   Regfilter.m128i_i16[2],
                          Regfilter.m128i_i16[4],   Regfilter.m128i_i16[6]);

RegTemp2 = _mm_setr_epi16(RegtempRes1.m128i_i16[1], RegtempRes1.m128i_i16[3],
                          RegtempRes1.m128i_i16[5], RegtempRes1.m128i_i16[7],
                          Regfilter.m128i_i16[1],   Regfilter.m128i_i16[3],
                          Regfilter.m128i_i16[5], Regfilter.m128i_i16[7]);

RegtempRes1 = _mm_add_epi16(RegTemp1, RegTemp2);

This is the best conversion I was able to come up with for this particular instruction. But this change has seriously affected the performance of the entire program.

Can anyone please suggest a better performance efficient alternative within MMX, SSE, SSE2 and SSE3 instructions to the _mm_hadd_epi16 instruction. Thanks in advance.

Était-ce utile?

La solution 2

If your goal is to take the horizontal sum of 8 16-bit values you can do this with SSE2 like this:

__m128i sum1  = _mm_shuffle_epi32(a,0x0E);             // 4 high elements
__m128i sum2  = _mm_add_epi16(a,sum1);                 // 4 sums
__m128i sum3  = _mm_shuffle_epi32(sum2,0x01);          // 2 high elements
__m128i sum4  = _mm_add_epi16(sum2,sum3);              // 2 sums
__m128i sum5  = _mm_shufflelo_epi16(sum4,0x01);        // 1 high element
__m128i sum6  = _mm_add_epi16(sum4,sum5);              // 1 sum
int16_t sum7  = _mm_cvtsi128_si32(sum6);               // 16 bit sum

Autres conseils

_mm_hadd_epi16(a, b) can be simulated with the following code:

/* (b3, a3, b2, a2, b1, a1, b0, a0) */
__m128i ab0 = _mm_unpacklo_epi16(a, b);
/* (b7, a7, b6, a6, b5, a5, b4, a4) */
__m128i ba0 = _mm_unpackhi_epi16(a, b);

/* (b5, b1, a5, a1, b4, b0, a4, a0) */
__m128i ab1 = _mm_unpacklo_epi16(ab0, ba0);
/* (b7, b3, a7, a3, b6, b2, a6, a2) */
__m128i ba1 = _mm_unpackhi_epi16(ab0, ba0);

/* (b6, b4, b2, b0, a6, a4, a2, a0) */
__m128i ab2 = _mm_unpacklo_epi16(ab1, ba1);
/* (b7, b5, b3, b1, a7, a5, a3, a1) */
__m128i ba2 = _mm_unpackhi_epi16(ab1, ba1);


/* (b6+b7, b4+b5, b2+b3, b0+b1, a6+a7, a4+a5, a2+a3, a0+a1) */
__m128i c = _mm_add_epi16(ab2, ba2);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top