How to rewrite this code to sse intrinsics

2019-05-29 10:31发布

问题:

Im new in sse intrinsics and would appreciate some hints assistance in using this 9as this is yet foggy to me)

I got such code

for(int k=0; k<=n-4; k+=4) 
 { 

  int xc0 = 512 + ((idx + k*iddx)>>6); 
  int yc0 = 512 + ((idy + k*iddy)>>6); 

  int xc1 = 512 + ((idx + (k+1)*iddx)>>6); 
  int yc1 = 512 + ((idy + (k+1)*iddy)>>6); 

  int xc2 = 512 + ((idx + (k+2)*iddx)>>6); 
  int yc2 = 512 + ((idy + (k+2)*iddy)>>6); 

  int xc3 = 512 + ((idx + (k+3)*iddx)>>6); 
  int yc3 = 512 + ((idy + (k+3)*iddy)>>6); 

  unsigned color0 =  working_buffer[yc0*working_buffer_size_x + xc0]; 
  unsigned color1 =  working_buffer[yc1*working_buffer_size_x + xc1]; 
  unsigned color2 =  working_buffer[yc2*working_buffer_size_x + xc2]; 
  unsigned color3 =  working_buffer[yc3*working_buffer_size_x + xc3]; 

  int adr = base_adr + k; 

  frame_bitmap[adr]  = color0; 
  frame_bitmap[adr+1]= color1; 
  frame_bitmap[adr+2]= color2; 
  frame_bitmap[adr+3]= color3; 
 } 

all here is int/unsigned, this is critical part of the loop, not sure if integer sse would help here in speed but wonder if it would work at all? could someopne help with this?

(im using mingw32)

回答1:

My sse is a bit rusty, but what you should do is:

xmm0: [k, k+1, k+2, k+3] //xc0, xc1,....
xmm1: [k, k+1, k+2, k+3] //yc0, yc1,....
//initialize before the loop
xmm2: [512, 512, 512, 512]
xmm3: [idx, idx, idx, idx]
xmm4: [iddx, iddx, iddx, iddx]
xmm5: [idy, idy, idy, idy]
xmm6: [iddy, iddy, iddy, iddy]
xmm7: [working_buffer_size_x, working_buffer_size_x, working_buffer_size_x, working_buffer_size_x]

Calculations:

xmm0 * xmm4
xmm0 + xmm3
xmm0 >> 6
xmm0 + xmm2

xmm0: [xc0, xc1, xc2, xc3]
///////////////////////////////

xmm1 * xmm6
xmm1 + xmm5
xmm1 >> 6
xmm1 + xmm2

xmm1: [yc0, yc1, yc2, yc3]

xmm1 * xmm7
xmm1 + xmm0

Now xmm1 is:

xmm1: [yc0*working_buffer_size_x + xc0, yc1*working_buffer_size_x + xc1, yc2*working_buffer_size_x + xc2, yc3*working_buffer_size_x + xc3]

You are reading and writing memory in each loop (working_buffer, frame_bitmap arrays), operations that are way too slower than the calculations itself, so the speed improvement won't be as much as you expected to be.

EDIT

You need working_buffer and frame_bitmap arrays to be aligned and SSE4.1:

#include <emmintrin.h>
#include <smmintrin.h> //SSE4.1

int a[4] __attribute__((aligned(16)));
__m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7;

xmm2 = _mm_set1_epi32(512);
xmm3 = _mm_set1_epi32(idx);
xmm4 = _mm_set1_epi32(iddx);
xmm5 = _mm_set1_epi32(idy);
xmm6 = _mm_set1_epi32(iddy);
xmm7 = _mm_set1_epi32(working_buffer_size_x);

for(k = 0; k <= n - 4; k +=4){
    xmm0 = _mm_set_epi32(k + 3, k + 2, k + 1, k);
    xmm1 = _mm_set_epi32(k + 3, k + 2, k + 1, k);

    //xmm0 * xmm4
    xmm0 = _mm_mullo_epi32(xmm0, xmm4);

    //xmm0 + xmm3
    xmm0 = _mm_add_epi32(xmm0, xmm3);

    //xmm0 >> 6
    xmm0 = _mm_srai_epi32(xmm0, 6);

    //xmm0 + xmm2
    xmm0 = _mm_add_epi32(xmm0, xmm2);



    //xmm1 * xmm6
    xmm1 = _mm_mullo_epi32(xmm1, xmm6);

    //xmm1 + xmm5
    xmm1 = _mm_add_epi32(xmm1, xmm5);

    //xmm1 >> 6
    xmm1 = _mm_srai_epi32(xmm1, 6);

    //xmm1 + xmm2
    xmm1 = _mm_add_epi32(xmm1, xmm2);


    //xmm1 * xmm7
    xmm1 = _mm_mullo_epi32(xmm1, xmm7);
    //xmm1 + xmm0
    xmm1 = _mm_add_epi32(xmm1, xmm0);


    //a[0] = yc0*working_buffer_size_x + xc0
    //a[1] = yc1*working_buffer_size_x + xc1
    //a[2] = yc2*working_buffer_size_x + xc2
    //a[3] = yc3*working_buffer_size_x + xc3
    _mm_store_si128((__m128i *)&a[0], xmm1);

    unsigned color0 =  working_buffer[ a[0] ]; 
    unsigned color1 =  working_buffer[ a[1] ]; 
    unsigned color2 =  working_buffer[ a[2] ]; 
    unsigned color3 =  working_buffer[ a[3] ]; 

    int adr = base_adr + k; 

    frame_bitmap[adr]  = color0; 
    frame_bitmap[adr+1]= color1; 
    frame_bitmap[adr+2]= color2; 
    frame_bitmap[adr+3]= color3; 
}

You can optimize it even more by avoiding the _mm_store_si128((__m128i *)&a[0], xmm1); or the int adr = base_adr + k; using assembly with direct manipulation of memory.



标签: c++ c x86 mingw sse