跳转至

simd笔记

1. 语义

1. 绝对值(一元运算)

其实就是将一个X个Y比特的数做一次绝对值运算,比如下面对16个16位有符号数做了16次abs运算,但只有一条指令

__m256i _mm256_abs_epi16(__m256i a)

2. 加减法之类(二元运算)

  • 简单理解为a+b就行;
  • 还有理解饱和加法(防止溢出)的指令就OK,其实就是溢出了取最大值

3. 位运算(二元运算)

类似and,or,也有组合运算,比如andnot,这里区分是针对谁做not就行

4. 混合操作

其实有点像选择器,输入两个向量和一个mask,然后根据mask来选择,这里有些api非常迷惑,因为mask是8bit的,然后avx256可能会拆分成两个128bit然后执行两次

__m256i _mm256_blend_epi16 (__m256i a, __m256i b, const int imm8)
比如这里,实际上对于a和b来说,他们是16个16bit的整数,但imm8只有8bit,所以语义上相当于__mm128_blend_epi16(_m128i a, __m128i b, const int imm8)执行两次

这里的执行逻辑是: 根据mask,如果某个bit为1,则选择左边的a(8*16位)对应的元素,否则选择b

5. 广播指令

有点像python的'a' * 16的感觉,其实就是针对某个元素快速复制或者扩展N份

__m256i _mm256_broadcastw_epi16 (__m128i a)
将低16位扩展16个位置

6. 数据加载和存储指令(其实就是输入输出)

内存数据加载到向量寄存器或者将向量寄存器的值写入到内存中,有区分内存地址对齐的版本和不对齐的版本;还有带mask的加载,只加载特定的数据,注意这里的mask其实是128位向量,然后用最高位来决定是否加载(这个向量一般来自于比较指令)

__m128d _mm_loadu_pd (double const* mem_addr)

7. 比较与测试指令

这里需要注意新接口,有些api是有mask的

8. 置换与指令重排(Swizzle类指令)

调整向量中元素的顺序,支持固定模式或动态索引重排,常用于数据格式转换、矩阵转置,比如图像通道分离、合并(rgb <-> bgr)、行列重排、数据对齐调整。

//
//
//

reference