ISA-L加速库介绍以及在SPDK中的集成

作者简介:周嘉祺,Intel 软件工程师,主要从事SPDK、ISA-L开发和存储软件性能优化的工作

前言

关注SPDK/DPDK的朋友,可能对ISA-L并不陌生,作为SPDK的submodule,其为SPDK/DPDK提供了一些计算领域的算法支持,比如CRC,GZIP等。除此之外,ISA-L作为一个独立的库,也可以满足大部分大多数上层应用对压缩、哈希、EC、CRC的需求。

ISA-L分为了isa-l_pub版本和isa-l_crypto版本, 如图1所示。前者主要包含了在存储领域的一些算法,后者主要包含的是密码学的一些算法,包括在最新版本中增加了高性能SM3算法的支持。

11111111111111111111111
图 1 ISA-L 库概况

这次将更为详细地介绍isa-l_pub以及isa-l_crypto,本文分为以下几块:

  1. ISA-L 原理讲解
  2. ISA-L支持的算法
  3. ISA-L的使用
  4. SPDK/DPDK中,ISA-L的支持情况

ISA-L原理讲解

ISA-L的运算快的主要原因是用了SIMD。那么SIMD是什么呢?

SIMD(Single Instruction Multiple Data)的中文释义是单指令流多数据流。顾名思义,就是单条指令,可以处理多条数据流。

举个具体例子,如图2所示,我们存在两个数组,分别存了4个int,如果需要下标相同的元素相加的话,正常代码需要写一个循环,分别加4次再存到数组中。而在SIMD中,只需要做一次add操作就可以完成。并且SIMD中的寄存器每一个小块的空间也是相对独立的(当然不同指令集的操作长度也不同),和数组一样,下标为1的数值相加溢出后,不会影响到下标0的数值。

22222222222222
图 2 SIMD add指令示例

从最早的MMX,到后来的SSE(包括SSE、SSE2、SSE3、SSE4)、AVX,AVX2,再到如今的AVX512指令集,都是SIMD的指令集。而ISA-L的核心就是对于SIMD的使用,将指令集运算细节封装,再暴露出上层C的接口,以达到加速的目的。

对于不同的SIMD指令集,运算寄存器组有如下区别:

  • SSE :XMM0 ~ XMM7 , 提供了8个128位寄存器
  • SSE(x86-64) : XMM0 ~ XMM15,提供了16个128位寄存器
  • AVX(AVX-128): XMM0 ~ XMM15,寄存器同于SSE(x86-64),不同于SSE的是,提供了更为多且方便的运算指令,比如使用vshufps代替shufps。
  • AVX2(AVX-256): YMM0 ~ YMM15,提供了16个256位寄存器。提供了更多的运算指令。
  • AVX512:ZMM0 ~ ZMM31,提供了32个512位寄存器。提供了更多的运算指令。

值得一提的是,AVX512的ZMM寄存器和AVX2的YMM寄存器有着重叠的关系,AVX2的YMM寄存器组和SSE的XMM寄存器组同样存在着重叠的关系。

举个例子,当你机器同时拥有AVX512和AVX2指令集时,当你操作YMM0的时候,会改变ZMM0低位256位的寄存器组。它们的关系如图3所示:

33333333333
图 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已经计算完成了,那么会填充到内存中,不再经过下一轮计算。

444444444444444
图 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支持的算法

isa-l_pub目前版本(v2.30.0)包含了以下算法:

  • EC(erasure codes) : 类型为Reed-Solomon编码的纠错码,使用了GF(2^8),并且提供了一些有限域内运算的接口。
  • CRC(Cyclic Redundancy Check) : 支持iscsi32, ieee32, t10dif, ecma64, iso64, jones64多项式的循环冗余校验,不同的标准返回的crc长度也是不同的。
  • Raid(Redundant Array of Independent Disks) : 并不是支持磁盘阵列的标准,而是支持raid标准中经常需要用到的XOR和P + Q运算。
  • Igzip(ISA-L GNU ZIP) : 主要支持deflate和inflate算法,同时也支持了GNU ZIP的头部信息的写入和解析。

isa-l_crypto目前版本(v2.23.0)包含了以下算法:

  • Multi-buffer hashes : 包含了标准SHA1、SHA256、SHA512、MD5、SM3的hash算法集。
  • MH (Multi hashes) : 自研hash算法,包含了mh-sha1和mh-sha256。它的设计为了串行的hash过程 ,设计核心是将单个的buffer分组为多个块进行SIMD过程, 有兴趣的读者可以看看multi-hash-paper(在文末点击“阅读原文”即可)。(注意:mh1-sha256得出的结果和标准sha256得出的结果并不一致。)
  • AES(Advanced Encryption Standard) : 标准的AES算法,支持GCM、CBC、XTS三种模式,并且支持128位、192位、256位密钥长度。
  • Rolling hash : 标准的划窗hash

ISA-L的使用

要进行编译以及安装库,通常只需运行如下即可:
./autogen.sh
./configure
make
sudo make install

对于isa-l_pub来说,如果需要编译target:

  • make check : 编译并运行基本的运行测试,测试包含了一些内置的测试集
  • make tests : 编译并运行基本的单元测试
  • make perfs : 编译并运行isa-l_pub的性能测试软件,将会和openssl对比性能
  • make ex : 编译内置的example,并非所有算法都有example
  • make other : 编译工具集,目前isa-l_pub只提供了igzip的一个工具集。
  • make doc : 编译创建api文档

对于isa-l_crypto来说,由于isa-l_crypto并没有额外的工具集提供,所以并没有make other选项提供。其他的编译target的选项和isa-l_pub一致。

当你构建并安装好ISA-L后,默认情况下头文件安装在/usr/include,库文件安装在/usr/lib64/下。你可以将相应的库和头文件引入项目即可使用。但是在接口方面,ISA-L的和openssl的并不完全一致。

对于一些算法来说,ISA-L提供了example和工具来展示接口如何使用,这并不是全部算法都包含的。这个时候,你可以参考算法的API文档或者相应的tests来编写自己的应用程序。再或者,如果你目前的项目使用的是openssl,想切换到isa-l,那么你可以参考一下ISA-L中带有rand test的测试案例,这种测试案例都是和openssl进行对比测试。

拿sha256_mb/sha256_mb_rand_ssl_test.c为例,这里ISA-L用了自己的sha256接口和openssl的接口分别运算同一串字符串,得到结果进行对比测试。调用openssl的接口用到了SHA256()函数,但我们ISA-L的接口却用到了三个函数:

  • sha256_ctx_mgr_init : 初始化sha256的ctx
  • sha256_ctx_mgr_submit : 将ctx里面的数据提交
  • sha256_ctx_mgr_flush : 将ctx未计算完的数据全计算完成

我们接口能接收的数据是多个buffer,而非单串字符串。接收多个buffer后,使用SIMD,性能自然是openssl的数倍,当然我们也能够提供提个类似于openssl SHA256的接口,但是这并不符合ISA-L设计的初衷。

SPDK/DPDK中 ISA-L的支持情况

在DPDK中,ISA-L帮助DPDK构建了 Compression dev和 crypto dev,具体使用情况如下:

在Compression dev中

  • 使用DEFLATE接口(包含在igzip中),来帮助PMD进行压缩/解压操作
  • CRC32,来帮助PMD进行数据完整性校验
    在crypto dev中
  • AES,帮助PMD进行AES的加密/解密操作
  • HASH,帮助PMD对数据进行hash操作

而在SPDK中,ISA-L作为一个git submodule被包含了进去,在很多地方也有使用ISA-L,具体如下:

  • SPDK中提供了vbdev_crypto和vbdev_compress,这是借助于DPDK中Compression dev和crypto dev实现的,底层同样运行了ISA-L
  • ISA-L的CRC被SPDK封装成了一个util,在blobstore,tcp,iscsi,ftl,ocf等模块中都有用到。


  • 本站原创文章仅代表作者观点,不代表SDNLAB立场。所有原创内容版权均属SDNLAB,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用,转载须注明来自 SDNLAB并附上本文链接。 本站中所有编译类文章仅用于学习和交流目的,编译工作遵照 CC 协议,如果有侵犯到您权益的地方,请及时联系我们。
  • 本文链接https://www.sdnlab.com/24655.html
分享到:
相关文章
条评论

登录后才可以评论

环球塔莎 发表于20-12-28
0