How to rewrite this code to sse intrinsics

折月煮酒 提交于 2019-12-06 16:06:32

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.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!