关注SPDK/DPDK的朋友,可能对ISA-L并不陌生,作为SPDK的submodule,其为SPDK/DPDK提供了一些计算领域的算法支持,比如CRC,GZIP等。除此之外,ISA-L作为一个独立的库,也可以满足大部分大多数上层应用对压缩、哈希、EC、CRC的需求。
ISA-L分为了isa-l_pub版本和isa-l_crypto版本, 如图1所示。前者主要包含了在存储领域的一些算法,后者主要包含的是密码学的一些算法,包括在最新版本中增加了高性能SM3算法的支持。
图 1 ISA-L库概况
这次将更为详细地介绍isa-l_pub以及isa-l_crypto,本文分为以下几块:
ISA-L的运算快的主要原因是用了SIMD。那么SIMD是什么呢?
SIMD(Single Instruction Multiple Data)的中文释义是单指令流多数据流。顾名思义,就是单条指令,可以处理多条数据流。
举个具体例子,如图2所示,我们存在两个数组,分别存了4个int,如果需要下标相同的元素相加的话,正常代码需要写一个循环,分别加4次再存到数组中。而在SIMD中,只需要做一次add操作就可以完成。并且SIMD中的寄存器每一个小块的空间也是相对独立的(当然不同指令集的操作长度也不同),和数组一样,下标为1的数值相加溢出后,不会影响到下标0的数值。
图 2 SIMD add指令示例
从最早的MMX,到后来的SSE(包括SSE、SSE2、SSE3、SSE4)、AVX,AVX2,再到如今的AVX512指令集,都是SIMD的指令集。而ISA-L的核心就是对于SIMD的使用,将指令集运算细节封装,再暴露出上层C的接口,以达到加速的目的。
对于不同的SIMD指令集,运算寄存器组有如下区别:
值得一提的是,AVX512的ZMM寄存器和AVX2的YMM寄存器有着重叠的关系,AVX2的YMM寄存器组和SSE的XMM寄存器组同样存在着重叠的关系。
举个例子,当你机器同时拥有AVX512和AVX2指令集时,当你操作YMM0的时候,会改变ZMM0低位256位的寄存器组。它们的关系如图3所示:
图 3 XMM, YMM, ZMM寄存器之间的关系
所以,当你混用不同指令集的时候,需要注意指令集的操作范围,防止得出来的计算结果只能正确一部分。
SIMD基本原理介绍完了,那么ISA-L是如何使用SIMD来加速运算的呢?
首先,在项目include目录下有一个multibinary.asm汇编文件,该文件提供了一系列的汇编方法名为mbin_dispatch_init,而在ISA-L中的每一种算法都必须注册这个汇编方法,该方法会检查你的CPU flag,来获得支持的指令集,从而进行数据流的分发。举个例子,当你调用ISA-L中sha256的方法,ISA-L会检测到你的CPU只支持AVX2,那么会把数据流分发到AVX2的汇编算法进行下一步操作。
而当ISA-L分发好了数据流,选定了计算所用的指令集后,就会将数据流从内存填充到具体的寄存器,再调用具体的指令集进行算法计算。一般来说,在内存中的数据流都是由多段buffer组成的,这样对于SIMD来说是友好的。
举个例子,当用户需要计算多个数据的hash结果时,用户将数据放到内存中,组成一个char *的数组。再调用ISA-L的接口,得到一个存了所有计算好hash的数组。
而在中间过程中,无论用户放到内存中的数组有多长,ISA-L每次只取出固定lane的数据进行计算(lane指的是一次计算能处理的最大长度,比如名为sha256_mb_x16_avx512.asm实现的axv512版本的sha256,x16代表了一次可以取16个lane的数据,对应到数组为取16个元素),但是用户输入的数据中,单个元素中的char *长度可能有长有短,比如图4中的data2,因为数据过长,在第一次hash过程中,只处理了部分数据,得到了一个中间值,那么它将加入下一轮计算,而data1已经计算完成了,那么会填充到内存中,不再经过下一轮计算。
图 4 ISA-L中hash计算
除了SIMD之外,ISA-L也支持了一些比较“另类”的指令集,比如SHANI,这是为了加速少量数据HASH而设计的,之前说过SHA256的AVX512版本一次处理16个lane的数据,但是但用户一次提交的数据数目过少,或者SIMD计算后只剩下单个或两个过长的buffer没有计算完,SHANI就可以加速这种情况。当然除了SHANI之外,ISA-L同样也用了AESNI指令集对AES进行加速。
另外在ISA-L中,为了减少内存的throughput,我们尽量的避免了在算法过程中使用栈,为了代替栈的使用,我们尽量的使用寄存器作为暂存数据(当然这也带来了代码的可读性降低)。但是在一些情况下也是不可避免的使用了栈进行缓存,比如当你的寄存器已经占满,不够用的时候,或者算法要求的预运算值会占用比较大的空间。这也是另外一点ISA-L计算快的原因。
isa-l_pub目前版本(v2.30.0)包含了以下算法:
isa-l_crypto目前版本(v2.23.0)包含了以下算法:
要进行编译以及安装库,通常只需运行如下即可:
./autogen.sh
./configure
make
sudo make install
对于isa-l_pub来说,如果需要编译target:
对于isa-l_crypto来说,由于isa-l_crypto并没有额外的工具集提供,所以并没有make other选项提供。其他的编译target的选项和isa-l_pub一致。
当你构建并安装好ISA-L后,默认情况下头文件安装在/usr/include,库文件安装在/usr/lib64/下。你可以将相应的库和头文件引入项目即可使用。但是在接口方面,ISA-L的和openssl的并不完全一致。
对于一些算法来说,ISA-L提供了example和工具来展示接口如何使用,这并不是全部算法都包含的。
拿sha256_mb/sha256_mb_rand_ssl_test.c为例,这里ISA-L用了自己的sha256接口和openssl的接口分别运算同一串字符串,得到结果进行对比测试。调用openssl的接口用到了SHA256()函数,但我们ISA-L的接口却用到了三个函数:
我们接口能接收的数据是多个buffer,而非单串字符串。接收多个buffer后,使用SIMD,性能自然是openssl的数倍,当然我们也能够提供提个类似于openssl SHA256的接口,但是这并不符合ISA-L设计的初衷。
在DPDK中,ISA-L帮助DPDK构建了Compression dev和crypto dev,具体使用情况如下:
在Compression dev中
在crypto dev中
而在SPDK中,ISA-L作为一个git submodule被包含了进去,在很多地方也有使用ISA-L,具体如下:
学习地址:http://ke.qq.com/course/5066203?flowToken=1043717
更多DPDK学习资料有需要的可以自行添加进入学习交流君 羊 793599096 免费获取,或自行报名学习,免费订阅,永久学习,关注我持续更新哦!!!
原文链接:https://blog.csdn.net/weixin_37097605/article/details/111306442