C/C++ 调用AVX/SSE函数的注意事项及准备工作

本文档详细介绍了在Win10和CentOS环境中使用AVX指令集的步骤,涉及头文件引入、__m256i等数据类型及其内存操作函数,如加载、存储和算术运算,以及遇到问题时的官方文档查找和博客参考。

1. 环境

OS: win10 和 centos7,其他的linux应该都差不多。(参考这篇文章,作者也在ubuntu18.04以及Archlinux上进行过对应的测试均可)
gcc: 如果使用AVX指令集在编写cmake或者makefile文件时需要加上 -mavx2 参数。低版本的gcc 不支持 -mavx2 参数,具体是在哪个版本加进来的不知道,试试就知道了。
CPU: 其实处理器也需要支持这个指令集,比如avx512需要Intel四代之后才有,可以去对应厂家的官网上查询,或者直接跑代码,看下耗时。

2. 头文件

SIMD的相关头文件包含如下:

#include <mmintrin.h>  //MMX
#include <xmmintrin.h> //SSE(include mmintrin.h)
#include <emmintrin.h> //SSE2(include xmmintrin.h)
#include <pmmintrin.h> //SSE3(include emmintrin.h)
#include <tmmintrin.h> //SSSE3(include pmmintrin.h)
#include <smmintrin.h> //SSE4.1(include tmmintrin.h)
#include <nmmintrin.h> //SSE4.2(include smmintrin.h)
#include <wmmintrin.h> //AES(include nmmintrin.h)
#include <immintrin.h> //AVX(include wmmintrin.h)
#include <intrin.h>    //(include immintrin.h)

3.部分数据类型(以AVX指令集为例)

typedef float __m256 __attribute__ ((__vector_size__ (32),__may_alias__));
typedef long long __m256i __attribute__ ((__vector_size__ (32),__may_alias__));
typedef double __m256d __attribute__ ((__vector_size__ (32),__may_alias__));

4.部分函数实例(以long long类型的__m256i类型数据为例)

将连续32字节的内存复制到__m256i 类型变量中:

extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm256_loadu_si256 (__m256i_u const *__P)
{
  return *__P;
}

extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm256_load_si256 (__m256i const *__P)
{
  return *__P;
}

上边两个函数的区别在: 前者没有u,后者有u。带u的表示即使需要复制的内存起始地址不是32的倍数也没事,应该是汇编那层给处理了,至少不会出错;不带u的,如果起始地址不是32的倍数,运行的时候就会segmentation fault(core dumped)

extern __inline __m256i
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm256_xor_si256 (__m256i __A, __m256i __B)
{
  return (__m256i) ((__v4du)__A ^ (__v4du)__B);
}

extern __inline __m256i
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm256_subs_epu8 (__m256i __A, __m256i __B)
{
  return (__m256i)__builtin_ia32_psubusb256 ((__v32qi)__A, (__v32qi)__B);
}

部分运算函数,这些操作暂时没遇到比较特殊的要求。

extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm256_storeu_si256 (__m256i_u *__P, __m256i __A)
{
  *__P = __A;
}

extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm256_store_si256 (__m256i *__P, __m256i __A)
{
  *__P = __A;
}

4.遇到问题如何查找

4.1 官方的函数说明

https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=3828,5597&techs=AVX,AVX2
注意举一反三,在查找某一类函数时注意观察他们的特性。

4.2比较好的博客

1 http://www.cnblogs.com/zyl910/archive/2012/10/22/simdsumfloat.html
2 http://www.cnblogs.com/zyl910/archive/2012/08/27/intrin_table_gcc.html
3 http://blog.csdn.net/zyl910/article/category/1128358
4 http://stackoverflow.com/questions/4468420/segmentation-fault-due-to-memory-alignment-in-sse

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

daijingxin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值