关于指令集AVX AVX2学习笔记

X86 SSE/AVX 指令集

指令集介绍:

SSE/AVX 指令集是Intel公司设计的、对X86体系的SIMD的拓展指令集,基于向量化技术,提高硬件的并行计算能力,增强X86多核向量处理器的图像处理和视频处理能力。

查看电脑支持的指令集

Lscpu

相关概念:

寄存器:寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。

X86: Intel x86是英特尔公司于1978年推出的16位微处理器。

x86泛指一系列基于Intel 8086且向后兼容的中央处理器指令集架构

向量化运算

向量化操作和非向量化操作对比:

 

理论在向量化后的优化可以达到 8倍的优化比

1、操作对象:向量化是对cpu寄存器的充分利用,多线程是对线程和cpu多核心的并行优化

2、向量化和多线程是可以同时使用,在优化比上是一个相乘的关系。

3、向量化和多线程并行都可以达到并行优化效果

4、向量化和多线程并行都可以由编译器自主完成

函数命名

Intel ICC和开源的GCC编译器支持SSE/AVX指令的C语言接口(intrinsic,内置函数),在intrinsic.h头文件中(头文件可能有所不同)

函数命名:

第一部分:mm/mm256。mm表示SSE指令集,操作长度为64位或128位。mm256表示使用AVX指令集、操作位位256位。

第二部分:操作函数名称——如 add、load、mul....

第三部分:操作对象及数据类型— ps表示操作向量数据为单精度、

pd表示操作的向量数据为双精度等。

函数命名举例(AVX2):

_mm256_add_ps:使用AVX 256位寄存器,进行加法操作,操作的向 量数据位单精度。

_mm256_mul_pd:使用AVX 256位寄存器,进行乘法操作,操作的向 量数据类型为双精度。

1、用__m256定义三个寄存器变量

2、使用load对齐加载数据到寄存器

3、使用add函数来执行加操作

4、添加头文件immintrin.h

5、编译时添加-mavx -mavx2(注意对应) 进行编译

简单的指令集实例

#include<bits/stdc++.h>
​
#include<immintrin.h>
​
#include<omp.h>
​
using namespace std;
​
typedef chrono::high_resolution_clock Clock;
​
void out(int D[])
​
{
​
  for(int i=0;i<8;i++)
​
  {
​
    cout<<D[i]<<" ";
​
  }
​
  cout<<endl;
​
}
​
int main()
​
{
​
  __m256i x;
​
  __m256i y;
​
  __m256i z;
​
 
​
  int A[8]={1,2,3,4,5,6,7,8};
​
  int B[8]={1,2,3,4,5,6,7,8};
​
  int ans[8];
​
  
​
  x = _mm256_loadu_si256((__m256i*)&A[0]);
​
  y = _mm256_loadu_si256((__m256i*)&B[0]);
​
  z = _mm256_add_epi64(x,y); 
​
_mm256_storeu_si256((__m256i*)&ans[0],z);
​
  out(A);
​
  out(B);
​
  out(ans);
​
  return 0;
​
}

编译指令:g++ avx-add.cpp -o avx-add -mavx -mavx2 && ./avx-add

运行结果:

 

代码分析:

#include<immintrin.h>包含对应AVX指令集库,不同指令集对应不同的库,详细请查阅Intel官网。

代码实现一维数组加法,正常思路时循环对应相加。但使用AVX指令集可以同时操作8个int型数。因此省去了循环。

__mm256_loadu_si256:加载数据到寄存器上,起始坐标为数组的开头,即A[0];

__mm256_add_epi64:相加操作,即寄存器对应位置数据进行相加。

__mm256_storeu_si256:寄存器数据写入到结果数组Z内。

类比:

int a;        __m256i x;

int b;        __m256i y;

int c;         __m256i z;

a=1;         x=256_loadu_si256((m256i*)&A[0]);

b=1;         y=_mm256_loadu_si256((__m256i*)&B[0]);

a+b;         z=_mm256_add_epi64(x,y);

c=a+b;     _mm256_storeu_si256((__m256i*)&ans[0],z);

指令集实际功能很丰富,种类繁多,比如非对齐加载,绕过缓存直接写入内存等等,这些都是提升性能的方法。

当作并行比赛时,在修改数据结构的基础上,往往会用到指令集技术,增大带宽,减少访存往往是制胜的法宝。

此文章仅为自己学习过程中的一些笔记与理解,不合理之处还请指出并万分感谢!

指令集介绍官网:Intel® Intrinsics Guide

  • 22
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值