技術解碼 | RSFEC原理分析

今天向大家介紹下RSFEC的原理,它通過生成冗餘數據來恢復丟失的信息,首先介紹下背景,之後重點介紹RSFEC如何計算冗餘和恢復數據的,分爲異或方式和矩陣方式,異或方式可以認爲是矩陣方式的特殊形式,最後做下總結。

- 背景介紹 -

RSFEC廣泛應用於存儲、通信、二維碼等領域,比如RAID利用它生成冗餘盤提升容錯性,視頻通話中利用它生成冗餘數據對抗網絡丟包,太空中遠距離傳輸數據時也用到它,第三張圖片是旅行者一號應用RSFEC將太空中拍攝的照片傳回地球,二維碼中也有使用,下面的二維碼缺了一個角,還是可以掃出來。

下面以視頻通話場景爲例,大家用過微信的視頻通話吧,有時網絡不佳會感覺卡頓。畫幅圖說明,發送端發了3個數據包,不加任何處理,經過網絡傳輸丟失其中一個數據包,接收端只收到兩個,就可能引起卡頓。一種簡單的做法是將它們重複發一遍使接收端儘量得到3個包,但這樣比較費流量,有沒有辦法儘量少發包並達到相同的效果?

可以在發送前根據3個數據包的特點,計算出一個FEC包,當3個包任意一個丟失,可以通過FEC包和剩餘的兩個計算出丟失的包。下面將介紹怎麼計算冗餘包,並講解如何恢復數據。

- 異或方式編碼與恢復 -

假設發送端要發的數據是a, b, c,用異或方式編碼生成一個冗餘包r,將4個包發送出去,網絡傳輸過程中b丟失了,a, c, r成功到達,接受端將收到的3個包異或,計算回b,這樣就恢復了數據。

同樣的計算,用矩陣方式表達,其中加法是異或,這裏爲什麼要將這個簡單的例子用矩陣這種看似複雜的方式重新算一遍呢?因爲這個例子是RSFEC的簡化版,用矩陣方式計算的過程基本涵蓋了RSFEC的過程,這裏用簡單例子說明方便理解。

下面等式右邊是接收端應該收到的數據,現在b丟失了,將b這一行刪掉,相應地刪掉等式左邊的矩陣的第二行,形式化的表達就是左乘下方左邊的矩陣,得到右下角的等式。

下面用高斯消元法解方程組,先將待解方程組的係數矩陣和未知數寫成增廣矩陣(augmented matrix)形式,用行初等變換進行前向替換(forward substitution),目的是將矩陣化爲上三角矩陣,先交換第二行和第三行,再將第一行加到第二行上,注意加法是異或,1+1=0。第二步是後向替換(back substitution),將第三行加到第二行,將右上角全化爲0,最終得到解。

這裏再強調下,對於這個簡單的例子,我們肉眼可以直接看出解,但計算機是用程序化的方式求解,如果方程變得複雜了之後我們肉眼是看不出解的,而計算機的程序化方式能應對複雜的計算,這裏演示了整個生成冗餘和恢復數據的過程。

- WebRTC中的實現 -

WebRTC是瀏覽器中進行RTC實時通信的一個框架,其中有兩種基於異或的編碼方式,ULP FEC和Flex FEC。下面先介紹ULP FEC,非均等級別的保護,顧名思義,它對不同的數據提供不同程度的保護。通常數據的前段部分比較重要,所以這裏用一個FEC包保護A、B的前邊部分,用另外一個FEC包保護C、D的前邊部分,每個FEC包保護兩個數據包,也就是加了50%的FEC。再看A、B、C、D的後邊部分,用了L1級別的包保護這四段數據,加了25%的FEC。前後段保護程度不同。

第二種是Flex FEC,分爲非交錯模式和交錯模式,把它們叫行模式和列模式更好理解。這裏的發包順序是S1, S2到SL,SL+1,SL+2一行一行地發送,對每一行進行異或運算生成冗餘包,第一行生成R1,第二行生成R2一直到RD。數據包有D行L列,生成D個冗餘包。這種生成方式可以抗隨機丟包,沒法抗連續丟包,比如第一行連續丟包,數量過多後將無法恢復,如果隨機丟也就是把丟失包分攤到各行上,每一行就容易恢復數據。

下面這種是交錯模式,或者稱列模式,每一列計算生成冗餘包,計算冗餘包的數據包是交錯的,假如發生連續丟包,它們分攤在各列上,每一列丟失地不多容易恢復,所以它能夠抗連續丟包,或者說burst突發丟包。

上面說的行列模式被保護的包位置是固定的,還有保護包位置不固定的模式,下面舉例說明,使用Flexible mask n=7個數據包,m=3個冗餘包展示隨機和連續兩種模式下的編碼和恢復情況。左邊是抗隨機丟包的mask,右邊是抗連續丟包的mask,源碼在下面。

先看抗隨機丟包的mask,7個數據包用a到g 7個字母表示,使用這個mask編碼就是把相應位置的數據包異或得到冗餘包,注意代碼中的宏定義每行是兩個字節16位,實際用到了7位,因爲有7個數據包。

假如a、b、c三個包丟失,即連續丟包,這個mask代表的編碼方式只是抗隨機丟包,我們看下爲什麼沒法抗連續丟包。發送端將a ~ g、r1、r2、r3發送出去,接受端收到d ~ g、r1、r2、r3,丟失了前三個包,相應地刪除編碼矩陣的前三行,得到方陣,由於這個矩陣是不可逆的,所以無法將a ~ g全部解出,爲什麼不可逆?我們可以對編碼矩陣進行高斯消元法,用上方的4個1往下加,剩餘紅框中的小方陣,將小方陣的第三行加到第二行,第二行變爲1 1 0,與第一行相同,兩者線性相關所以不可逆。用中學數學的觀點看,就是下方的方程組無解,每行都有a、b、c中的兩個未知數,無論怎麼消元都解不出,所以無法恢復。

再看busty抗突發丟包的編碼方式,和前面一樣先寫出編碼的式子。

將a、b、c和相應行刪掉,這個係數矩陣是可逆的,可以用高斯消元法驗證,所以可以恢復丟失的包。用中學數學的觀點看,解下方的方程組,觀察到最後一個方程只含a一個未知數,先解出,然後代到第一個方程,求出b,再求出第二個方程得到c。用高等數學的觀點看,就是用高斯消元法求解方程組,它是一種程序化的手段,也是計算機所使用的。

這兩種mask適用於各自特定的場景,有時不能恢復數據,因爲矩陣不可逆。是否有一種方法,丟失任意m個包都可恢復呢?

- RSFEC矩陣方式 -

前面說過,要想恢復數據,矩陣需要可逆,而範德蒙矩陣具有這樣良好的性質,刪除任意行列得到的方陣都是可逆的。下面紅框中的矩陣是範德蒙矩陣,它是一個m行n列的矩陣,n是媒體數據包數量,m是冗餘包數量,它的第一行全是1,第二行1、2、3到n,第三行是1、2^2 、3^2 到n^2 ,每一行在上一行的基礎上乘以一個數,最後一行是1、2^(m-1) 、3^(m-1) 到n^(m-1) 。m=1時就是PPT開頭舉的那個最簡單的例子。

前面介紹的矩陣運算要在計算機上落地實現,會碰到什麼問題?運算是在實數域上進行的,加減乘除可能會溢出,浮點數的計算可能損失精度。假設編程語言中有一種數據類型是uint3_t,即3比特位,它可以表示8種狀態(0~7) 。如果是普通意義上的四則運算,比如3*7=21會溢出,1/3也無法用uint3_t表示,而有限域上的“加減乘除”沒這些問題,運算結果仍然在該域(0~7)上。

這裏爲什麼要造一種奇怪的數據類型uint3_t呢?是爲了方便講解,因爲後面會將它的所有8種狀態列出來,如果用常見的uint8_t舉例,要列出256種狀態不方便。uint3_t和uint8_t的原理是類似的。

有限域是一門通用的技術,這部分內容相對獨立,不僅解決RSFEC的運算問題,還運用於密碼學等領域,有興趣的同學可以參考《密碼編碼學與網絡安全》的有限域一章。

uint3_t上共8個元素,這裏要抽象看待,看成8種狀態或者8個符號,我們定義一種運算規則,運算對象是多項式。看下多項式怎麼得到的,將8個數字寫成二進制形式,比如3的二進制是011,某位上是1,相應地有一個x的次方,最低位是x^0 即1,011就是x+1,或者說g+1,取什麼符號沒有關係。再比如101對應x^2+1。先關注表格中紅框的三列,其他兩列後面介紹。得到8個多項式後,我們定義一種多項式運算。

使用代數基本規則的普通多項式運算。比如x+x=2x,x*x=x^2。

係數運算是模2運算的多項式運算,即係數在GF(2)={0, 1}中。比如x+x=2x,係數再模2,最終結果是0。

係數在GF(2)中,且多項式被定義爲模一個3次多項式prime polynomial x^3+x+1 的多項式運算。prime polynomial不能被uint3_t上8個多項式中的兩個相乘得到,也就是不可約(irreducible),可以理解爲多項式的“素數”。

舉個例子,計算3乘以7,先將它們寫成相應的多項式,x+1和x^2+x+1,運用第一條規則展開,同類項合併,比如 x^2 + x^2=2 x^2,運用第二條規則,系統模2後爲0,同理x+x=0,得到 x^3+1 ,此時它“溢出”了,因爲那八個多項式最高次數就是2,再運用第三條規則,將次數降下來,目的是使它落到8個多項式中。模一個多項式怎麼計算呢?我們知道整數中比如a模b就是a減去整倍數個b,使最終結果小於b就行,同理,這裏可以將x^3+1減去prime polynomial x^3+x+1,得到-x,係數模2得到x,對應的二進制是010,十進制是2。這樣原本普通意義上的3乘以7=21溢出了,用我們定義的規則得到2,稱作運算是封閉的。

用同樣的方法對uint3_t上的所有元素進行四則運算,得到下表。其中減法用加法逆元表示,比如a-b等於a+(-b),除法用乘法逆元表示,a/b等於a*b^(-1)。

前面的乘除法計算過程還是比較複雜的,有限域有一個良好的性質是所有元素可以用generator的指數次方表示,generator爲primitive polynomial的根,比如g^3+g+1=0 ,不用求出具體值,只是一種表示,要抽象看待。由於異或性質,g^3=-(g+1)=g+1 ,看錶格中的元素3,它的二進制是011,即g+1,也等於g^3,其他元素都可以化成指數形式,可以看下右邊的推導過程。

每個元素都表示爲g的指數次方後,可以將它們用表格形式列出來,比如g^3=3, g^6=5 。同時將對數列出來,比如g^6=5,也就是log5=6。接下來重新計算3*7,查表找到對數和指數結果,進行加法和模運算就可以得到結果,這樣就將乘除法轉化成加減法,提升了運算效率。

現在我們知道怎麼對uint3_t上的元素進行運算了,計算機上實現矩陣運算時每個元素用一個字節uint8_t表示,計算原理與uint3_t是類似的,只是在GF(2^8)上進行,四則運算的結果仍可以用一個字節表示。

- 總結 -

總結下RSFEC用到的兩個核心技術,第一個是利用範德蒙矩陣任意子方陣可逆的性質,允許丟失任意m個包。第二個是解決計算機上落地時碰到的溢出、浮點數精度問題,離散數學中的有限域恰好搭建了連續數學與計算機間的橋樑,利用有限域上的運算封閉性質落地。

關於RSFEC還有很多值得探討的點,柯西矩陣是與範德蒙矩陣性質類似的一種矩陣,也是任意子方陣可逆,它和範德蒙矩陣比有哪些優勢,感興趣的同學可以看下參考資料,這裏就不展開了;前面提到恢復數據時需要求逆或者說高斯消元法,它的普通算法的時間複雜度是O(n^3) ,可以利用範德蒙矩陣、柯西矩陣的結構特點優化求逆,將時間複雜度降爲O(n^2);另外矩陣運算時可以利用SIMD單指令多數據加速計算,具體可以看看參考資料。

以上就是今天的分享內容,歡迎大家線下交流探討。

參考資料

ULP FEC 標準:

https://datatracker.ietf.org/doc/html/rfc5109

Flex FEC 標準:

https://datatracker.ietf.org/doc/html/rfc8627

談談有限域那些事兒:

https://blog.csdn.net/qmickecs/article/details/77281602

離散對數和橢圓曲線加密原理,講了有限域在加密中的應用:

https://blog.csdn.net/qmickecs/article/details/76585303

William Stallings 《密碼編碼學與網絡安全:原理與實踐》

Cryptography and Network Security: Principles and Practice 

音視頻通信中FEC的數學原理:

http://justme0.com/archive/fec.html

WebRTC FEC 解讀:

https://xjsxjtu.github.io/2017-07-16/LearningWebRTC-fec/

FEC各種編碼:

https://zhuanlan.zhihu.com/p/93684856

FEC解碼優化:

https://patents.google.com/patent/CN103780352B/zh

柯西矩陣之於範德蒙矩陣的優勢:

http://abcdxyzk.github.io/blog/2018/04/16/isal-erase-2/

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