使用 SSE 指令的图像最大值

Posted

技术标签:

【中文标题】使用 SSE 指令的图像最大值【英文标题】:Image maximum value with SSE instruction 【发布时间】:2014-02-02 12:46:34 【问题描述】:

我正在尝试放弃一个使用 SSE 指令返回图像最大值的函数。我有一个奇怪的结果,最大值设置为 -356426400(值应该是 254)。

这是我的代码:

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




【问题讨论】:

你的图片是什么格式的?它真的是每像素 32 位(假设 int 是 32 位)还是每个 int 真的是 RGBA ?如果是 RGB,那么您要寻找什么样的最大值?每个组件单独的最大值,还是什么? 【参考方案1】:

1) 我没有看到任何处理对齐的代码

2) 无符号整数和 _mm_max_epi8 不匹配,后者比较 8 位有符号整数 (http://msdn.microsoft.com/en-us/library/bb514045(v=vs.90).aspx)

3) 我假设你有一个 h*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;

我假设 memcpy 在您的代码中是必要的邪恶,因为没有任何其他关于内存对齐的信息。如果你有什么要处理的,自己动手,会好很多。

【讨论】:

for(int i=0; i&lt;h*w; i += w) - 此迭代仅在图像宽度为 16px 时才能正常工作 感谢您的回答。我在 linux 中工作,不知道应该如何编写代码(我不知道 _STATIC_ASSERT(sizeof(unsigned int) == sizeof(BYTE )*4); if( w % 4 != 0) return; // 错误 不能这样做,需要 4 多行或做一些对齐! unsigned int aligned_src = (unsigned int) _aligned_malloc(hwsizeof(unsigned int), 16); // _mm_load_si128 需要 16 字节对齐内存 memcpy(aligned_src, src, sizeof(unsigned int)*h*w); __declspec(align( 16)) __m128i 最大值 = 0,0,0,0; 您可以删除它们,我想确保无符号整数是 4 个系统定义的字节,并且该矩阵的宽度是 4 个整数的倍数。 _aligned_malloc 是特定于 Windows 的,在 linux 上您可以使用:man7.org/linux/man-pages/man3/posix_memalign.3.html。对于 __declspec 有 gcc 的属性:gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html。 @Yossarian 你说得对,抱歉,修复了代码.. 请注意,您不需要在每次迭代时存储负载和存储最大向量。 我是 SSE 的新手,我试图模拟用户的代码。顺便感谢您的提示,我 +1!

以上是关于使用 SSE 指令的图像最大值的主要内容,如果未能解决你的问题,请参考以下文章

在 32 位整数中查找最大值

SIMD/SSE:短点积和短最大值

使用 SSE 和 AVX 查找矩阵中的最大元素及其列和行索引

AVX 或 SSE 上的水平尾随最大值

SIMD指令集——一条指令操作多个数,SSE,AVX都是,例如:乘累加,Shuffle等

__m128, SSE4 中最大绝对值的符号