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;
编译运行效果:
# gcc test.c -msse2 -O2
# ./a.out
4 9 5 5
再看看函数f1的汇编代码,真是相当简单,3条指令就完成了数组的累加
若要使用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级别的加速指令。
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级别的加速指令。
相关文章推荐
- 手机网站左侧栏弹出,固定整个页面,不让页面滚动
- MMORPG服务器架构
- 11个超棒的iOS开发学习网站
- AllJoyn架构
- 理解RESTful架构
- 网站测试总结
- 盘点国内外十大免费CDN网站加速服务
- #推荐网站#SketchFab
- Dubbo学习总结(2)——Dubbo架构详解
- 关于手机、电脑、单片机等的架构、速度和相关术语
- C/S和B/S架构的区别
- 可以让你越来越聪明的网站
- Hadoo总结二:HA高可用性原理
- Hadoop系统架构
- 《大型网站技术架构核心原理与案例分析读书笔记》
- 安卓的相关网站
- rdesktop架构解析(RDP协议分析)
- breeze技术架构发布
- 网站的伸缩性架构
- 如何制作一个类似狗耳朵的网站