Question

I'm trying to cede a function that return the maximum value of an image with the use of SSE instruction. I have a strange result of the maximum value set to be -356426400 (the value should be 254).

this is my code :

void max_sse(unsigned int *src, long h, long w, unsigned int *val)
{

unsigned int tab[16];
for(int i=0; i<h*w;i+=16)
{
__m128i PG=_mm_load_si128((__m128i*)(&src[i]));
__m128i max=_mm_max_epi8(max,PG);
_mm_store_si128((__m128i*)&tab, max);
}
*val=tab[0];
for (int i=0;i<16;i++)
{
if (tab[i]>*val)
{
*val=tab[i];
}
}

}
Was it helpful?

Solution

1) I don't see any code dealing with alignment

2) There's a mismatch between unsigned integers and _mm_max_epi8 which comapares 8-bit signed integers (http://msdn.microsoft.com/en-us/library/bb514045(v=vs.90).aspx)

3) I'm assuming you have a h*w matrix with rows multiple of 4 (or dealing with that with some padding for instance)

On Windows you could do something like:

#include "windows.h"
#include <malloc.h>
#include <smmintrin.h>
#include <iostream>
using namespace std;

void max_sse(unsigned int *src, long h, long w, unsigned int *val)
{
    _STATIC_ASSERT(sizeof(unsigned int) == sizeof(BYTE)*4);
    if( w % 4 != 0)
        return; // ERROR Can't do it, need 4-multiple rows or do some alignment!
    unsigned int *aligned_src = (unsigned int*)_aligned_malloc(h*w*sizeof(unsigned int), 16); // _mm_load_si128 needs 16-bytes aligned memory
    memcpy(aligned_src, src, sizeof(unsigned int)*h*w);
    __declspec(align(16)) __m128i max = {0,0,0,0};

    // Iterates the matrix
    for(int i=0; i<h*w; i+=4)
    {
        __m128i *pg = (__m128i*)(aligned_src+i);
        __m128i PG = _mm_load_si128(pg);

        __m128i newmax = _mm_max_epu32(max, PG);
        _mm_store_si128(&max, newmax);
    }
    unsigned int abs_max = 0;
    unsigned int *max_val = (unsigned int*)&max;
    for (int i=0;i<4;i++)
    {
        if (abs_max < *(max_val+i))
        {
            abs_max = *(max_val+i);
        }
    }
    _aligned_free(aligned_src);
    cout << "The max is: " << abs_max << endl;
}


int main()
{
    unsigned int src[] = {0,1,2,4, 5,6,7,8, 224,225,226,129};
    unsigned int val;
    max_sse(src, 3,4, &val);

    return 0;
}

I'm assuming the memcpy a necessary evil in your code since there isn't any other information on memory alignment. If you have something to deal with that, do it yourself and it will be a lot better.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top