您的位置:首页 > 运维架构 > 网站架构

X86架构下SSE系列指令使用

2015-10-10 18:36 489 查看
X86架构下SSE系列指令使用

sse指令集中的指令,一条指令可以实现多项数据运算,即SIMD-Single Instruction Multiple Data。

相关资料可参考:
http://blog.chinaunix.net/uid-20385936-id-3902720.html http://blog.csdn.net/fengbingchun/article/details/18460199
下面的简短示例代码,函数f1使用sse实现了两个数组的累加:array_c = array_a + array_b;

#include <stdio.h>
#include <emmintrin.h>

int array_a[4] __attribute__ ((aligned (128))) = {1,2,3,4};
int array_b[4] __attribute__ ((aligned (128))) = {3,7,2,1};
int array_c[4] __attribute__ ((aligned (128)));

void f1(void *a, void *b, void *c)
{
__m128i big1 = _mm_load_si128((__m128i *)(a));
__m128i big2 = _mm_load_si128((__m128i *)(b));
__m128i big3 = _mm_add_epi16(big1,big2);
_mm_store_si128((__m128i *)c,big3);
}

int main()
{
int i;
f1(array_a, array_b, array_c);

for (i=0;i<4;i++)
{
printf("%d ", array_c[i]);
}

return 0;
}


编译运行效果:

# gcc test.c -msse2 -O2

# ./a.out

4 9 5 5

再看看函数f1的汇编代码,真是相当简单,3条指令就完成了数组的累加

0000000000400570 <f1>:
<span style="color:#ff0000;">  400570:	66 0f 6f 07          	movdqa (%rdi),%xmm0
400574:	66 0f fd 06          	paddw  (%rsi),%xmm0
400578:	66 0f 7f 02          	movdqa %xmm0,(%rdx)</span>
40057c:	c3                   	retq
40057d:	0f 1f 00             	nopl   (%rax)


若要使用SSE指令,需要在编译选项中增加-msse2(或-msse3, 或-msse4),当启用了高版本的的选项时,低版本的选项也就同时自动启用了。

当启用了-msse系列的选项时,编译器就可以编译使用了加速指令的嵌入式汇编代码,也可以针对代码中调用的sse系列的bultin函数(例如int __builtin_ia32_comisdgt (v2df, v2df))生成相应的sse指令代码。

如何让源代码同时适应启用与不启用-msse系列选项的情况呢?

当gcc编译命令中带了-msse系列选项时,会有相应的预定义的宏存在。

通过如下命令,就能知道,启用-msse4时,编译器会预定义哪些sse相关的宏,这就告诉了编码者,当前编译启动了何种sse。

从输出也能看出,启用高级别的sse时,低级别的sse也就自动打开了。

# gcc -dM -E -msse4 - <<<'' | grep SSE

#define __SSE4_1__ 1

#define __SSE4_2__ 1

#define __SSE2_MATH__ 1

#define __SSE_MATH__ 1

#define __SSE2__ 1

#define __SSSE3__ 1

#define __SSE__ 1

#define __SSE3__ 1

如何在代码中使用sse相关指令呢?

要么自己写嵌入式汇编代码,

要么调用相关的builtin函数(不同级别的sse有不同的builtin函数集,这些函数在编译时自动生成sse指令代码),

要么#include <emmintrin.h>并使用其中声明的接口。

通过查看/usr/lib/gcc/x86_64-redhat-linux/4.8.2/include/emmintrin.h的内容,可以发现,这个头文件,实际上是将sse2系列的相关builtin函数进行了包装。这样的话,如果直接使用emmintrin.h中的接口,相当于只能使用到sse2级别的加速指令。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: