关于SSE指令集

时间:2022-01-19 01:04:05
1. 一般来讲,所有SSE指令函数都有3个部分组成,中间用下划线隔开:
 
    _mm_set_ps1
 
  mm表示多媒体扩展指令集
 
  set表示此函数的含义缩写
 
ps1表示该函数对结果变量的影响,由两个字母组成,第一个字母表示对结果变量的影响方式,p表示把结果作为指向一组数据的指针,每一个元素都将参与运算,S表示只将结果变量中的第一个元素参与运算;第二个字母表示参与运算的数据类型。s表示32位浮点数,d表示64位浮点数,i32表示32位定点数,i64表示64位定点数。

2. 内存对齐
(1)VS中使用SSE DEBUG正常RELEASE下出错的解决方法
from:http://magicyang.blog.51cto.com/2226589/1065700
       __m128i* p_aoffsets = (__m128i*)aoffsets;
        __m128i* p_boffsets = (__m128i*)boffsets;
        int n_count = MATCH_MASK / 8 + 1;
        for(int i = 0; i < n_count; ++i)
        {
            p_aoffsets[i] = _mm_subs_epi16(p_aoffsets[i], p_boffsets[i]);
        }
如上一段代码,DEBUG模式下可以正常运行,但RELEASE时第一次循环就会出错,根本原因还是在于内存未对齐造成的。参见http://bbs.csdn.net/topics/360044337。

#pragma pack(16),__declspec(align(16))就是两坨屎,想搞
SSE,绝对,千万,永远,不要用!!! 我用了一整年的movupd啊!!!!!!
最后找遍了整个中文世界没有,还是请教写汇编的老外得到了精华,
想对齐16字节,最好的办法是人肉手动对齐内存...

整理后的对齐函数:
static inline void* align(const void* x, int n)
{
    int p = (int)x;
    p = (p % n == 0)? (p) : (p + n - p % n);
    return (void*)p;
}

使用时先分配比需要的字节数多n个字节(n为希望的对齐数),然后调用函数返回对齐后的地址,示例:
char a_block_head[MATCH_MASK * 2 + 16u] = {0};
uint16_t* aoffsets = align(a_block_head, 16);

最后,赞同那位老兄说的,#pragma pack和__declspec(align())的确是两坨屎,哈哈。

(2)  from:http://blog.csdn.net/delphihero/article/details/1270069
float __declspec(align(16)) Array[ARRAYCOUNT];   
这里要注意一下,我使用了__declspec(align(16))做为数组定义的修释符,这表示该数组是以16字节为边界对齐的,因为SSE指令只能支持这种格式的内存数据。