2014-02-02 1 views
1

Я пытаюсь уступить функцию, которая возвращает максимальное значение изображения с использованием инструкции SSE. У меня странный результат максимального значения, установленного как -356426400 (значение должно быть 254).Максимальное значение изображения с инструкцией SSE

это мой код:

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]; 
} 
} 

} 
+0

Любая помощь пожалуйста ??? –

+0

Какой формат является вашим изображением? Действительно ли это 32 бита на пиксель (при условии, что int 32 бит) или каждый int действительно, скажем, RGBA? И если это RGB, то какой максимум вы ищете? Раздельный максимум для каждого компонента или что? –

ответ

2

1) Я не вижу какой-либо код дела с выравниванием

2) Там несоответствие между беззнаковым целым и _mm_max_epi8 которого comapares 8-разрядным целые числа (http://msdn.microsoft.com/en-us/library/bb514045(v=vs.90).aspx)

3) Я предполагаю, что у вас есть матрица ah * w со строками, кратными 4 (или, например, с этим дополнением)

В Windows вы могли бы сделать что-то вроде:

#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; 
} 

я предполагаю тетсру необходимое зло в вашем коде, так как нет никакой другой информации о выравнивании памяти. Если у вас есть что-то с этим, сделайте это сами, и это будет намного лучше.

+0

'for (int i = 0; i nothrow

+0

Спасибо за ваш ответ. Я работаю в Linux, любая идея как я должен написать код (я не знаю ни о _STATIC_ASSERT (sizeof (unsigned int) == sizeof (BYTE) * 4); if (w% 4! = 0) return; // ERROR Can ' t), нужно 4-кратные строки или выполнить выравнивание! unsigned int * aligned_src = (unsigned int *) _ aligned_malloc (h * w * sizeof (unsigned int), 16); // _mm_load_si128 требуется 16-байтная выровненная память memcpy (aligned_src, src, sizeof (unsigned int) * h * w); __declspec (align (16)) __m128i max = {0,0,0,0}; –

+0

Вы можете удалить их, что я хотел убедиться заключается в том, что целое число без знака было 4 байта, определяемого системой, и ширина была кратной 4 целым числам f или матрицы. _aligned_malloc является специфичным для Windows, а на linux вы можете использовать: http://man7.org/linux/man-pages/man3/posix_memalign.3.html. Для __declspec есть атрибуты gcc: http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html. @Yossarian Извините, исправлен код. –

Смежные вопросы