最近做了CNN的卷積層和LS-SVM在ZYNQ7020上的實現。除了輸入是由ARM透過AXI匯流排傳輸,演算法的主要部分都是由PL部分(FPGA)實現的。當然這只是入門的嘗試,對於一個深度學習演算法,如何在硬體上實現效率最高,還需要進一步的驗證(在SOC架構中對演算法進行劃分還是直接採用高階FPGA實現)。
最開始做的是卷積層的實現,透過學習的例程,使我對整個開發流程有了初步的認識。隨著自己在自己板子上的實現,對於其中存在的很多沒有明說的關鍵細節,有了更多的積累。最後,開發的流程和思想由這些細節串聯成一個整體。而後來的LS-SVM的實現,讓我對論文中的演算法復現體驗了一番。接下來,我將以上述兩個演算法為例,總結一下深度學習演算法在FPGA上的開發思想。
首先,在做實現之前,最重要的是演算法是在硬體上是做訓練,還是做檢測,這兩者之間差別較大。我認為FPGA對於訓練任務的適用性一定是體現在需要一邊檢測一邊學習的工程中,而不是為了減少訓練時間的單純訓練任務。訓練演算法一般有兩類情況,一類是需要不斷地迭代(BP演算法,SMO演算法等),一類是透過矩陣求逆等環節直接求解。這兩種在硬體上實現都對維數和層數提出了限制(多層迭代存在小數位數過大,難以定點化的問題;直接求解存在大型矩陣求逆的問題)。所以想在硬體上實現,需要對原先的演算法進一步的最佳化,用一些理論技巧去避免這些問題。對於檢測任務來說,把訓練好的演算法在FPGA上實現要更容易,但是同樣地,當浮點數實現演算法達不到要求(資源開銷,速度等),需要定點化時,檢測的準確率是會受影響的,這也是需要解決的問題。
當我們明確了能滿足上述要求的具體的演算法後,就要用硬體思想去理解演算法本身的結構,這是很必要的,即便我們是要用C或C++在HLS上實現(否則即便演算法在C/C++層面是通的,也很難綜合成RTL)。在LS-SVM中我們要實現的是:
轉換成硬體結構描述就是:
硬體思想的對於HLS也很重要,就是因為HLS中對C/ C++的一些限制就是硬體思想的體現:不支援動態分配記憶體,不支援長度不定的陣列(陣列都被綜合成ROM/RAM),不支援遞迴(記憶體分配問題)。所以當我們有了硬體思想,就能避免這些問題的出錯,不僅如此,硬體思想對於C/C++程式碼的進一步最佳化也有很大作用:使用FIFO,開闢快取,陣列的分割,陣列被綜合成ROM還是RAM(雙埠還是單埠)。有了這些認識使得我們對程式碼的結構最佳化變成可能。例如實現卷積時,視窗緩衝和行緩衝,減少了從DDR中取資料的等待時間,保證資料的流水取出並計算:
現狀和問題的總結
一、工程中如果需要邊訓練邊檢測,由於資料維度和演算法層數,對於需要不斷地迭代(BP演算法,SMO演算法等),存在小數位數過大,難以定點化的問題;對於透過矩陣求逆等環節直接求解的演算法(ELM,LS-SVM)存在大型矩陣求逆的問題。因而演算法的維度和層數有所限制。
二、浮點數計算的誤差及複雜度,和定點數精度的損失,對於演算法的效果也有所影響,這需要在具體的工程中評估,並提出解決方法。
三、已經實現的CNN和LS-SVM都只是單純的演算法實現,過於理想,沒有與實際的工程相關,可能在實際問題上的FPGA實現還有很多沒有考慮到的細節
四、ZYNQ的ARM+FPGA(對演算法不同部分劃分到ARM和FPGA中)架構與高階的FPGA-V-7相比對於深度學習的實現各自的效能還不可知,這也需要成熟具體的工程實現進行驗證對比。