avx2入门

什么是SIMD

SIMD是什么意思

SIMD 是 Single Instruction, Multiple Data 的缩写,意思是单指令多数据,是一种在计算机或微处理器中实现并行处理的设计方式,它可以同时对多个数据执行相同的操作,提高处理效率。SIMD 也有时被称为向量运算或向量处理,在图像处理应用以及多媒体处理上应用非常多。

SIMD指令集有哪些?

SIMD指令集有很多种,不同的CPU架构有不同的SIMD指令集。

以x86架构为例,常见的SIMD指令集有:
MMX:MultiMedia eXtensions,是Intel在1997年推出的第一个SIMD指令集,主要使用64位的MM0~MM7寄存器34。
SSE:Streaming SIMD Extensions,是Intel在1999年推出的一系列SIMD指令集,主要使用128位的XMM0~XMM15寄存器,分为SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2等版本154。
AVX:Advanced Vector Extensions,是Intel在2011年推出的一系列SIMD指令集,主要使用256位的YMM0~YMM15寄存器,分为AVX,AVX2,AVX-512等版本54。
ARM的NEON。

这些指令集的发展过程?

SIMD指令集的发展历程可以大致分为以下几个阶段:

年份指令集
1997Intel推出了第一个SIMD指令集——MultiMedia eXtensions(MMX),主要用于图像、音频、视频等多媒体处理,使用了8个64位的MM0~MM7寄存器
1999Intel在Pentium III对SIMD做了扩展,名为Streaming SIMD eXtensions(SSE),增加了8个128位的XMM0~XMM7寄存器,以及一些新的指令,主要用于浮点数的运算
2001Intel在Pentium 4中推出了SSE2,扩展了XMM寄存器的数量到16个,并且增加了对整数的支持,以及一些新的指令
2004Intel在Pentium 4中推出了SSE3,增加了一些新的指令,主要用于改善线程切换和循环展开等
2006Intel在Core 2 Duo中推出了Supplemental SSE3(SSSE3),增加了一些新的指令,主要用于加密解密和字符串处理等
2008Intel在Core i7中推出了SSE4,分为SSE4.1和SSE4.2,增加了一些新的指令,主要用于视频编解码和文本处理等
2011Intel在Sandy Bridge中推出了Advanced Vector Extensions(AVX),扩展了XMM寄存器的大小到256位,并且增加了一些新的指令,主要用于浮点数的运算
2013Intel在Haswell中推出了AVX2,扩展了对整数的支持,并且增加了一些新的指令,主要用于矩阵乘法和混合运算等
2015Intel在Broadwell中推出了Advanced Vector Extensions 512(AVX-512),扩展了XMM寄存器的大小到512位,并且增加了一些新的指令,主要用于科学计算和机器学习等

AVX2

immintrin.h

c++中提供了库函数,在immintrin.h头文件中定义,把汇编指令进行了打包,便于编写SIMD函数。
immintrin全称是immediate intrinsics,意为直接的内部函数。
immintrin.h头文件是AVX指令集的头文件,它包含了之前的所有SIMD指令集的头文件,比如MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2等12。

变量

主要变量:

__m256,是一个256位的向量,可以存储8个单精度浮点数,比如__m256 a = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f}。
__m256d,是一个256位的向量,可以存储4个双精度浮点数,比如__m256d b = {1.0, 2.0, 3.0, 4.0}。
__m256i,是一个256位的向量,可以存储8个32位整数,或者4个64位整数,或者16个16位整数,或者32个8位整数,比如__m256i c = {1, 2, 3, 4, 5, 6, 7, 8}。
__m128,是一个128位的向量,可以存储4个单精度浮点数,或者2个双精度浮点数,或者4个32位整数,或者2个64位整数,或者8个16位整数,或者16个8位整数,比如__m128 d = {1.0f, 2.0f, 3.0f, 4.0f}。
__m128d,是一个128位的向量,可以存储2个双精度浮点数,或者4个32位整数,或者2个64位整数,或者8个16位整数,或者16个8位整数,比如__m128d e = {1.0, 2.0}。
__m128i,是一个128位的向量,可以存储4个32位整数,或者2个64位整数,或者8个16位整数,或者16个8位整数,比如__m128i f = {1, 2, 3, 4}。

命名规则:

_ + _ + m + 位数 + [类型]

函数

函数类型
类型功能
加载和存储函数用于将内存中的数据加载到向量变量中,或者将向量变量中的数据存储到内存中
算术函数用于对向量变量中的元素进行加减乘除等基本运算
逻辑函数用于对向量变量中的元素进行按位与或非等逻辑运算
比较函数用于对向量变量中的元素进行大小或相等等比较
转换函数用于将向量变量中的元素转换为不同的类型
置换函数用于对向量变量中的元素进行重新排列或复制
广播函数用于将向量变量中的某个元素复制到其他位置
混合函数用于将不同的向量变量中的元素按照一定的规则组合起来
缩减函数用于将向量变量中的元素进行求和或求最大最小值等操作
其他函数用于实现一些特殊的功能,比如_mm256_extractf128_pd,_mm256_zeroall等。
加载和存储函数
函数名函数解释
_mm256_load_pd用于将内存中的4个连续的双精度浮点数加载到一个__m256d变量中,要求内存地址对齐。
_mm256_loadu_pd用于将内存中的4个连续的双精度浮点数加载到一个__m256d变量中,不要求内存地址对齐。
_mm256_load_ps用于将内存中的8个连续的单精度浮点数加载到一个__m256变量中,要求内存地址对齐。
_mm256_loadu_ps用于将内存中的8个连续的单精度浮点数加载到一个__m256变量中,不要求内存地址对齐。
_mm256_load_si256用于将内存中的256位整数加载到一个__m256i变量中,要求内存地址对齐。
_mm256_loadu_si256用于将内存中的256位整数加载到一个__m256i变量中,不要求内存地址对齐。
_mm256_store_pd用于将一个__m256d变量中的4个双精度浮点数存储到内存中,要求内存地址对齐。
_mm256_storeu_pd用于将一个__m256d变量中的4个双精度浮点数存储到内存中,不要求内存地址对齐。
_mm256_store_ps用于将一个__m256变量中的8个单精度浮点数存储到内存中,要求内存地址对齐。
_mm256_storeu_ps用于将一个__m256变量中的8个单精度浮点数存储到内存中,不要求内存地址对齐。
_mm256_store_si256用于将一个__m256i变量中的256位整数存储到内存中,要求内存地址对齐。
_mm256_storeu_si256用于将一个__m256i变量中的256位整数存储到内存中,不要求内存地址对齐。

函数名理解:
|函数名分解|解释|
|_mm|内部指令函数,用于操作多媒体指令集(MMX),用于直接操作寄存器或内存的数据|
|256|用于处理256位的数据|
|load|加载函数,将内存中的数据加载到寄存器中|
|u|这是一个不对齐函数 unaligned,不要求地址对齐|
|ps|这是一个单精度浮点数,packed single|

si:signed int
ps: packed single
pd: packed double

算术函数
函数名函数解释
_mm256_add_epi8/16/32/64这些函数可以对两个 __m256i 类型的变量进行 8/16/32/64 位的整数加法
_mm256_sub_epi8/16/32/64这些函数可以对两个 __m256i 类型的变量进行 8/16/32/64 位的整数减法
_mm256_mul_epi32/lo_epi32/lo_epi16这些函数可以对两个 __m256i 类型的变量进行 32/32/16 位的整数乘法
_mm256_div_epi8/16/32/64这些函数可以对两个 __m256i 类型的变量进行 8/16/32/64 位的整数除法
_mm256_add_ps/pd这些函数可以对两个 __m256/ __m256d 类型的变量进行单精度/双精度的浮点数加法
_mm256_sub_ps/pd这些函数可以对两个 __m256/ __m256d 类型的变量进行单精度/双精度的浮点数减法
_mm256_mul_ps/pd这些函数可以对两个 __m256/ __m256d 类型的变量进行单精度/双精度的浮点数乘法
_mm256_div_ps/pd这些函数可以对两个 __m256/ __m256d 类型的变量进行单精度/双精度的浮点数除法

ep:扩展精度(extended precision)的缩写,它是一种表示高精度的数据的方法
epi:扩展精度的整数
epu:扩展精度的无符号整数

逻辑函数
函数名函数解释
_mm256_and_si256这个函数可以对两个 __m256i 类型的变量进行按位与(bitwise and)运算
_mm256_or_si256这个函数可以对两个 __m256i 类型的变量进行按位或(bitwise or)运算
_mm256_xor_si256这个函数可以对两个 __m256i 类型的变量进行按位异或(bitwise xor)运算
_mm256_andnot_si256这个函数可以对两个 __m256i 类型的变量进行按位与非(bitwise andnot)运算
_mm256_testz_si256这个函数可以对两个 __m256i 类型的变量进行按位测试(bitwise test),并返回一个布尔值(boolean value)

按位测试的意思是,如果两个变量的所有位都为 0,那么返回 1,否则返回 0。这个函数可以用来判断两个变量是否相等,或者是否有某些位被设置

比较函数
函数名函数解释
_mm256_cmp_ps比较两个256位的单精度浮点向量,根据指定的条件返回一个掩码向量。
_mm256_cmp_pd比较两个256位的双精度浮点向量,根据指定的条件返回一个掩码向量。
_mm256_cmpeq_epi8比较两个256位的8位整数向量,返回一个包含相等比较结果的向量。
_mm256_cmpeq_epi16比较两个256位的16位整数向量,返回一个包含相等比较结果的向量。
_mm256_cmpeq_epi32比较两个256位的32位整数向量,返回一个包含相等比较结果的向量。
_mm256_cmpeq_epi64比较两个256位的64位整数向量,返回一个包含相等比较结果的向量。
_mm256_cmpgt_epi8比较两个256位的8位整数向量,返回一个包含大于比较结果的向量。
_mm256_cmpgt_epi16比较两个256位的16位整数向量,返回一个包含大于比较结果的向量。
_mm256_cmpgt_epi32比较两个256位的32位整数向量,返回一个包含大于比较结果的向量。
_mm256_cmpgt_epi64比较两个256位的64位整数向量,返回一个包含大于比较结果的向量。
_mm256_cmplt_epi8比较两个256位的8位整数向量,返回一个包含小于比较结果的向量。
_mm256_cmplt_epi16比较两个256位的16位整数向量,返回一个包含小于比较结果的向量。
_mm256_cmplt_epi32比较两个256位的32位整数向量,返回一个包含小于比较结果的向量。
_mm256_cmplt_epi64比较两个256位的64位整数向量,返回一个包含小于比较结果的向量。

eq:表示相等的比较条件
neq:表示不相等的比较条件
le:表示小于等于的比较条件
ge:表示大于等于的比较条件
gt:表示大于的比较条件
lt:less than 表示小于的比较条件

转换函数
函数名函数解释
从整数到浮点的转换例如_mm256_cvtepi32_ps可以将一个256位的32位整数向量转换为一个256位的单精度浮点向量。
从浮点到整数的转换例如_mm256_cvtps_epi32可以将一个256位的单精度浮点向量转换为一个256位的32位整数向量。
从浮点到浮点的转换例如_mm256_cvtpd_ps可以将一个256位的双精度浮点向量转换为一个256位的单精度浮点向量。
从整数到整数的转换例如_mm256_cvtepi8_epi16可以将一个256位的8位整数向量转换为一个256位的16位整数向量。
从整数到掩码的转换例如_mm256_movemask_epi8可以将一个256位的整数向量转换为一个32位的掩码整数。
从掩码到整数的转换例如_mm256_maskz_loadu_epi8可以根据一个32位的掩码整数,从一个地址加载一个256位的8位整数向量。
置换函数
函数名函数解释
单向量置换例如_mm256_permutevar8x32_epi32可以根据一个256位的32位整数向量中的索引,从另一个256位的32位整数向量中选择元素,形成一个新的256位的32位整数向量。
双向量置换例如_mm256_permute2x128_si256可以根据一个8位的控制整数,从两个256位的整数向
单向量广播例如_mm256_broadcastb_epi8可以将一个8位的整数复制到一个256位的8位整数向量的所有元素中。
双向量广播例如_mm256_broadcastsi128_si256可以将一个128位的整数向量复制到一个256位的整数向量的两个子向量中。
单向量混合例如_mm256_blend_epi16可以根据一个16位的掩码整数,从两个256位的16位整数向量中选择元素,形成一个新的256位的16位整数向量。
双向量混合例如_mm256_blendv_epi8可以根据一个256位的整数向量中的符号位,从两个256位的8位整数向量中选择元素,形成一个新的256位的8位整数向量。
广播函数
函数名函数解释
单向量广播例如_mm256_broadcastb_epi8可以将一个8位的整数复制到一个256位的8位整数向量的所有元素中。
双向量广播例如_mm256_broadcastsi128_si256可以将一个128位的整数向量复制到一个256位的整数向量的两个子向量中。
单标量广播例如_mm256_broadcastss_ps可以将一个32位的浮点数复制到一个256位的32位浮点数向量的所有元素中。
双标量广播例如_mm256_broadcastsd_pd可以将一个64位的浮点数复制到一个256位的64位浮点数向量的两个子向量中。

ss是single scalar的缩写,表示单标量,即一个32位的浮点数。
sd是double scalar的缩写,表示一个64位的浮点数
si是integer scalar的缩写,表示一个整数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值