初探GF-Complete(伽羅瓦運算庫)

GF-Complete 是一個開源、綜合性的伽羅瓦運算庫,相應的文章發表在FAST13 中(見參考文獻【1】)。作者是大名鼎鼎的Jim Plank 教授,作爲開源糾錯碼庫Jerasure 的開發者,在這個伽羅瓦運算庫中創新地採用了SSE 指令集來加速糾錯碼運算的瓶頸---伽羅瓦運算中的乘法運算,並採用了其他運算方法,綜合得到GF-Complete。該庫可在Plank 主頁中下載得到,下面就GF-Complete 庫做簡要分析,詳細可參考文檔【2】。




 
一、文件的組成


GF-Complete 有以下文件:


1. gf_complete.h 是應用程序使用的的頭文件,所有的其他源程序將生成各自的 .o 文件,所有的 .o 文件將被打包爲gf_complete.a ,供應用程序使用。gf_complete.h 包含了通用的數據類型gf_t (GF(2w) 中所有值得類型)和其他運算接口;


2. gf_general.h 中包含了不同大小w 的伽羅瓦域基礎運算,盡力消除不同w 大小帶來不同數據類型運算的痛苦。文件gf_wgen.c / gf_w4.c / gf_w16.c / gf_w32.c / gf_w64.c / gf_w128.c 分別對應着w<32 / w=4,8,16,32,64,128 的基礎運算(加法,乘法,除法,乘2等);


3. gf_rand.h 和gf_rand.c 是一個隨機數生成器;


4. gf_int.h 定義了gf_w** 需要使用的一些初始化函數和其他類型;


 


下面幾個文件並不是該庫所必須的,主要用於測試和例子:


6. gf_mult.c / gf_div.c  / gf_add.c 分別是域上的單個乘法/除法/加法工具;


7. whats_my_sse.c 是用於查看該機器支持哪些指令集,直接通過gcc 可編譯;


2. gf_method.h 和 gf_method.c 是用來幫助用戶知道自己可以使用的方法(不同處理器支持的指令集不同);


8. gf_time.c / gf_uint.c / gf_ploy.c 分別用於測試速度,單元測試和域中尋找本原多項式;


9. gf_example_1/2/3/4 分別對應着伽羅瓦域上的單個乘法和除法、一塊區域乘以一個常量、w=64 的常用運算,w=128 的常用運算測試;


 
二、gf_time


gf_time 是其中一個最重要的測試速度的工具,命令格式如下:


UNIX>gf_time w tests seed buffer-size iterations method


其中w 是位長,大於零小於等於32,或者爲64 和128;seed 是用於隨機數的種子;buffer-size 爲每次運算的區域的大小,iterations 爲循環次數(用於測速);最重要的兩個參數是tests 和 method,tests 指測試的選項,有以下幾種:
‘M’ 單個乘法計算
‘D’ 單個除法計算
 ‘I’    單個元素轉置
‘G’  一個隨機常量乘以一塊區域
‘0’ 零乘以一塊區域(等同於bzero())
‘1’ 一乘以一塊區域(等同於memcpy() 和 XOR)
‘2’ 二乘以一塊區域,這比一般的乘二運算要快(通過移位實現)
‘S’ 所有三種單個測試‘M’,‘D’,‘I’
‘R’ 所有四個區域測試‘G’,‘0’,‘1’,‘2’
‘A’ 所有七個測試


method 是伽羅瓦域上計算採用的技術(取決於機器支持的指令集,現有的伽羅瓦域運算方法和位長w ),通過gf_method 可以查詢到對應機器支持的方法,gf_method 有三部分組成:乘法方法,區域乘法方法和除法方法。


乘法對應有以下方法:
 ‘TABLE’          乘法表
 ‘LOG’              對數表
‘LOG_ZERO’ 類似於對數表
 ‘SHIFT’           通過不可約多項式進行移位乘法,速度很慢,參考【3】
 ‘BYTWO_p’    通過循環乘二並選擇性異或被乘數得到乘法結果,可以利用到Anvin 乘二的優化
 ‘BYTWO_b’    同上
 ‘SPLIT’            乘法裂表(比如LR表,或者利用SIMD 的表,詳見【1】)分別有wa 和wb 兩個參數
 ‘GROUP’         使用左右組合表的方法(參考文獻【4】)
 ‘COMPOSITE’在一個組合域上進行運算,GF((2l)k) 在參考文獻【3】、【4】有介紹


區域乘法有以下方法:
 ‘-’              使用默認方法
 ‘LAZY’      區域乘法前生成查詢表
 ‘SSE’        如果有SSE4 指令集,則使用
‘NOSSE’ 不使用SSE4 指令集
‘SINGLE’ 每次查詢一個元素運算的表
‘DOUBLE’每次查詢兩個元素運算的表
 ‘QUAD’     每次查詢四個元素運算的表,‘SINGLE’是一般的查詢表,之所以有另外兩個表,是爲了加速較小w 的運算,達到內存使用和計算的均衡
‘STDMAP’使用標準字位對其,內存塊分割爲連續的字
‘ALTMAP’非標準字位對其,每個字分割在不同的內存塊中
‘CAUCHY’將內存分爲w 塊且僅進行Cauchy Reed-Solomon 中的異或運算【5】


除法有以下方法選擇:
 ‘-’               使用默認方法
‘EUCLID’ 使用歐幾里得算法,方法慢,但允許使用乘法進行除法計算
‘MATRIX’  將每個元素轉化爲w×w 大小的bit-matrix(像在Cauchy Reed-Solomon 中),然後轉置該矩陣得到逆元素
三、字長和選項


w = 4:


“BYTWO_b SSE -”是默認的區域運算的一半速度,幾乎和乘二一樣快,但單個運算慢;


“BYTWO_b NOSSE -”是不使用SSE4 指令最快的區域運算方法;


“TABLE QUAD -”是不使用SSE 指令,基於查詢表最快的方法;


w = 8:


默認下速度最快


w = 16:


“SPLIT 16 4 SSE,ALTMAP -”這是w = 16時最快的區域乘法,關於這部分算法可以參考【2】


“BYTWO_b SSE -” 這對於區域乘二是最快的選項,但其他乘法就慢了


w = 32:


“SPLIT 32 4 SSE,ALTMAP -” 和w = 16一樣,這個比默認方法要快


“SPLIT 8 8 - -” 單個乘法最好的選擇,但要預分配1.75MB 內存


“BYTWO_b SSE -” 乘二非常快


“SPLIT 32 8 - -” 不使用SSE4 指令集最快的區域乘法,不使用1.75MB 內存


“COMPOSITE 2 1 SPLIT 16 4 SSE,ALTMAP - ALTMAP -” 對於較大的w,組合(composite)操作是最好的方法,但對於單個乘法計算不友好


w = 64:


“SPLIT 64 4 SSE,ALTMAP -” 這是最快的區域運算,採用128個不同的查找表,單個運算慢,建議使用默認方法


“COMPOSITE 2 1 SPLIT 32 4 SSE,ALTMAP - ALTMAP -”  區域運算也很快


“BYTWO_b SSE -” 這一直是區域乘二的最快方法


w = 128:


“SPLIT 128 4 - -” 方法尚不完善,這是暫時最快的方法


“BYTWO_b - - ”最快的區域乘二


 
三、源碼分析


先看幾個 .h頭文件(gf_complete.h 包含於gf_general.h 和gf_int.h 中)定義了一些數據結構:


gf_general_t  (gf_general.h)代表伽羅瓦域中元素類型,減少w 不同帶來不同數據類型運算的痛苦;
 1: typedef union { 


 2: uint32_t w32; 


 3: uint64_t w64; 


 4: uint64_t w128[2]; 


 5: } gf_general_t; 




 


gf_internal_t  (gf_int.h)代表伽羅瓦運算,包含了運算指定的類型和參數;
 1: typedef struct { 


 2: int mult_type; 


 3: int region_type; 


 4: int divide_type; 


 5: int w; 


 6: uint64_t prim_poly; 


 7: int free_me; 


 8: int arg1; 


 9: int arg2; 


 10: gf_t *base_gf; 


 11: void *private; 


 12: } gf_internal_t; 




 


gf_region_data  (gf_int.h)代表一塊要進行區域乘法計算的內存塊;
 1: typedef struct { 


 2: gf_t *gf; 


 3: void *src; 


 4: void *dest; 


 5: int bytes; 


 6: uint64_t val; 


 7: int xor; 


 8: int align; 


 9: void *s_start; 


 10: void *d_start; 


 11: void *s_top; 


 12: void *d_top; 


 13: } gf_region_data; 




 


gf_val_32_t , gf_val_64_t , gf_val_128_t 分別作爲w = 32、64、128時伽羅瓦域中的元素類型,是uint32_t,uint64_t 和uint64_t * 的別名。


gf_func_a_b 是兩個元素乘法或除法的函數指針,對於不同w 有三種函數指針;


gf_func_a     是一個元素求逆的函數指針


gf_func_region 是一個元素乘以一個區域的函數指針


gf_t  是一個伽羅瓦域運算的結構體,某個gf_t的實例(且允許我這麼說)代表了一個伽羅瓦域的運算方法
 1: typedef struct gf { 


 2: gf_func_a_b multiply; 


 3: gf_func_a_b divide; 


 4: gf_func_a inverse; 


 5: gf_region multiply_region; 


 6: gf_extract extract_word; 


 7: void *scratch; 


 8: } gf_t; 




這些結構通過gf_free 釋放空間


 但一個應用程序調用這些方法時,需要指定參數進行初始化,比如生成查找表等,這些可以通過gf_init_easy() 和gf_init_hard(),前者是後者的一個默認參數的選擇,如果手動選擇參數調用後者即可。也可以通過提供的create_gf_from_argv(&gf, w, argc, argv, 6) 通過手動輸入參數進行初始化。
發佈了76 篇原創文章 · 獲贊 188 · 訪問量 184萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章