前言
向量化简单的说就是使用SIMD指令, 来实现使用一条指令同时处理多个数据, MIC中具有32个长度为512位的向量处理单元, 每个向量处理单元可以处理16个32位或者8个64位的数据. 这里主要记录一下MIC向量化的使用方式以及一些向量指令的作用.
数据类型
MIC中使用下面的数据类型作为执行向量函数的操作数
1 | __m512, __m512i __m512d |
下面是它们的各自的作用:
__m512
- 处理单精度向量(float32 vector)__m512d
- 处理双精度向量(float64 vector)__m512i
- 处理整形向量, 包括32位和64位整形(int32/int64) 上面的数据类型直接映射到向量寄存器上(vector registers), 除此之外还有一种数据类型__mmask16 - is an unsigned short type associated with the mask register values.
我们可以使用Load Intrinsics
(为向量赋值) 和Store Intrinsics
(保存向量的值) 实现向量的存取. 下面是一个示例
1 | void test_load_store() { |
向量化函数(Intrinsics)
这里主要记录一些编译器提供的向量化函数, 完整的函数集可以在这里或者这里查询
算术运算
MIC中提供了加,减, 乘 三种算术运算函数, 这里以32位整型的加法为例:
1 |
|
输出结果为:
1 | arr_a[ 0] is: 0 arr_b[ 0] is: 16 arr_c[ 0] is : 16 |
With Mask
MIC提供的向量函数一般有两种形式
1 | // Without Mask |
一种是带Mask的, 一种是不带Mask的. 带Mask的多了两个参数: v1_old
和k1
, 其中k1
是__mmask16
类型的数据, 在上面我们知道__mmask
类型就是unsigned short
类型, 长度为16位. 关于带mask函数的解释: 将v1
的16位分别对应到_m512i
的16个整型上, 如果k1
某个位是1, 则将v2和v3中与该位对应的整型相加, 作为结果值, 如果k1
某个位为0, 就使用v1_old
向量中对应位的整型作为结果值. 例如如果k1
的第一位为1, 那么就将v2
的第一个整数和v3
的第一个整数相加, 作为结果向量的第一个整型的值. 如果k1
的第一位是0, 就将v1_old
向量中的第一个整型的值作为结果向量中第一个整型的值. 好吧, 还是看个例子吧.
1 | void mic_mask_add() { |
运行结果为:
1 | arr_a[ 0] is: 0 arr_b[ 0] is: 16 arr_old[ 0] is: 10000 arr_c[ 0] is : 16 |
Bitwise运算
MIC中提供了3中Bitwise运算函数- and
or
xor
, 其中取反元素可以通过与1异或来实现, 下面是and
操作的一个例子
1 | void mic_and() { |
其中print_binary
是一个打印二进制的函数, 这里只打印了后8位
1 | // 打印二进制 |
下面是一个取反的示例
1 | void mic_not() { |
下面是运行结果
1 | ~ 00000000 = 11111111 |
移位操作
移位操作分为算术移位和逻辑移位, 逻辑左移和算术左移的规则是一样的, 所以两者共用同一个左移函数, 而逻辑右移和算术右移不同, 逻辑右移是一直补0, 而算术右移要看符号位, 符号位为0则补0, 符号位为1, 则补1. 同时移位操作有两种形式, 一种给定一个常数, 向量中的每个元素都移该常数位, 一种是给定一个向量, 向量中的每个元素移给定向量中对应数值的位. 好吧下面还是看例子吧.
左移: 给定一个常数
1 | void mic_lshift() { |
左移:给定一个向量
1 | void mic_lshift_v() { |
执行结果为:
1 | 00000001 00010000 |
算术右移
1 | void mic_arshift() { |
执行结果为:
1 | 符号位为0: |
_mm512_alignr_epi32
函数原型为:
1 | extern __m512i __cdecl _mm512_alignr_epi32(__m512i v2, __m512i v3, const int count); |
该函数的作用就是将v2和v3拼接起来, v2在前, v3在后, 然后循环左移count个元素, 然后取最右侧的16个元素, 下面看个例子
1 | void mic_alignr() { |
执行结果为:
1 | arr_a: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |