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 協議,如果有侵犯到您權益的地方,請及時聯系我們。
  • 本文鏈接http://www.taian720.com/24655.html
分享到:
相關文章
條評論

登錄后才可以評論

環球塔莎 發表于20-12-28
0