使用 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<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 指令的图像最大值的主要内容,如果未能解决你的问题,请参考以下文章
使用 SSE 和 AVX 查找矩阵中的最大元素及其列和行索引