《Data-Intensive Text Processing with MapReduce》第4章-壓縮

在用map-reduce進行倒排索引的建立的時候,進入文檔的編號已經有序了,按照升序排序,這時候可以對文檔編號進行壓縮。例如,最開始的時候文檔序列如下:

image

通過“相鄰差”的方式對文檔id進行壓縮,結果如下

image

,第二個文檔的文檔號7保存成第一個文檔與第二個文檔的差值,2=7-5,同理,第3個文檔12保存成與第二個文檔的差值,5=12-7。。。。,採取這種方式,差值的最差情況是:最大文檔號-最小文檔號。

     從數字的角度來看, 缺失降低了數字的大小,但是從佔用空間的角度來講,並沒有降低數字的大小。int類型假如佔4個字節的話,那麼可以存儲的最大的非負整數是2**32,所以, 數字7和數字12都是佔用同樣4字節的空間。問題的核心是採用了int類型的定長編碼方式,如果採取非定長編碼,則可以解決這個問題。

4.5.1字節對齊的和字對齊的編碼

      爲了降低編碼的長度,節約存儲空間,引入了可變長編碼varInt,varInt的最高位是1的話,表示當前bit是最後一個bit,否則爲0,表示不是最後一個bit,這樣的話每個字節有7位可以使用,1個字節表示的最大值是127。

image 用1個字節編碼,image 用兩個字節編碼,image 用三個字節。。。

127,128的編碼如下,

1 1111111, 0 0000001 1 0000000,這種編碼的壞處是解碼的時候,需要移位運算,還有frequent branch mispredict。

一種改進的辦法是Jeff Dean在WSDM上提出的辦法,將每四個字節一起編碼,然後用一個字節的prefix來表示後續四個字節的長度,例如00,00,01,10表示後續的4個字節的長度分別是1,1,2,3字節。這樣一組的的長度最短是5個字節,最長的長度是17個字節。將所有的前綴(prefix)表存起來,在進行解碼的時候直接查表,就能將後續4個字節一起解析出來。通過這種方式比上面的varInt方式速度能提高2倍。

   對於大多數機器體系,常常一下子讀入一個字的長度,因此基於字對齊的壓縮編碼更常用,其中最常用的是simple-9,基於32bit,4字節的編碼。32bit中4bit保留作爲selector,剩餘的28bit用來對數據進行編碼。例如28bit可以存儲28個1bit的數據,或者14個2bit的數據。。直到3個9bit的數據(有一位未使用),公有9種方式,所有交simple-9。

4.5.2bit對齊的編碼

首先需要介紹下前綴編碼。如果在對字符的2進制編碼中不存在某一個字符的編碼是另一個字符編碼的前綴,那麼就稱這種編碼方式爲非前綴編碼,Huffman編碼就是一種非前綴編碼。

image

其中,unary是最簡單的前綴編碼。一個數字x表示成x-1個1,然後在結尾加一個0完成編碼。例如上圖中的9的編碼是8個1,然後在結尾加一個0。這種方式編碼的缺點很明顯,對1000進行編碼時,需要999個1,對大數據肯定是不行的。

image 在實際的使用中最多。對於一個數字x,對於image 部分,採用了上面提到的unary編碼,而對剩餘的部分image 則將其轉換成二進制,並用n-1bit進行編碼。例如,當x=10的時候,image 4,對應的unary編碼是1110,對於剩餘的部分image 最終的編碼爲1110:010。

解碼的時候也很方便,只需要先讀入unary編碼,假設unary解碼的結果是4,然後讀入4-1=3bit的數據111,轉換成數字,則最終的數字x是2**3+7=15。對於小於16的數,佔用的bit小於8個字節

   前面提到的都是無參數編碼,下面介紹一種有參數的編碼。叫着Golomb code。對於一個數x,參數b,首先計算image 部分,並且將q+1用unary編碼,剩餘image 用截斷二進制編碼(truncated binary)。例如假如x=2,b=5,則q=0,r=1.0的unary編碼是0。對於10,q=1,對應q+1爲10,r=4。

如果b是2的指數倍,則結果就是原數字的二進制編碼。

否則,對於r,image 值編碼到image ,對於b=5, 則3被編成11,而將剩餘的image 值編碼到image ,r=4剩餘的部分是4-3=1編碼到1。

 

truncated binary,wikipedia的介紹如下http://en.wikipedia.org/wiki/Truncated_binary_encoding

<Free Website Hosting
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章