PYNQ中實現SoftMax函數加速器

2021-01-11 電子產品世界

  孫齊偉

本文引用地址:http://www.eepw.com.cn/article/201905/401026.htm

  (西南交通大學 信息科學與技術學院,四川 成都 611756)

  摘要:SoftMax函數通常在深度學習中作為激活函數使用,但其計算涉及自然指數和除法運算,傳統PC機上計算較慢,拖累了一個神經網絡的訓練。本文針對自然指數運算的特點,提出了一種名為基底拆分法的新方法。該方法將SoftMax函數中自然指數計算拆分為多個由查找表實現的特定基底上,通過這種方法,一個複雜的自然指數計算過程即可由查找表過程和乘法過程實現。這種方法有效的降低了硬體複雜度以及邏輯傳播延時。由於該方法中使用了自定義的數據結構,因此本文採用了CPU + FPGA的架構,通過合理分工,加速SoftMax函數計算。同時,本文將基於這種方法設計的IP核在PYNQ-Z2開發板上進行了板級調試。

  關鍵詞:PYNQ,ZYNQ,SoftMax,AXI總線,異構計算

  * 本作品獲得第二屆「全國大學生集成電路創新創業大賽」全國一等獎

  0 引言

  Xilinx推出的ZYNQ系列FPGA中嵌入了一顆雙核ARM,既能發揮FPGA的定製特性,也能發揮處理器的通用特性,而且兩個部分之間接口豐富、官方文檔齊全,可玩性極高。同時相應的開發板也很多。傳統的ZYNQ開發板(Zedboard等)需要結合vivado和SDK兩大工具分別對PL、PS端進行硬體和軟體開發。本次我介紹的平臺為PYNQ開發板可使用Python將軟體操作和硬體控制進行無縫銜接,目前已經出到Z2版本,由依元素進行代理銷售,999塊極具性價比。

  PYNQ是Xilinx一項旨在使用Python和一些lib讓SoC開發更加簡單的開源項目,以我的理解其本質是Python的一些第三方庫,是對PS端操作的封裝。傳統的ZYNQ開發板也能使其變為PYNQ開發板,當引入Python後就可以使用一些Python中強大的第三方庫了例如Numpy、Matplotlib等。

  1 SoftMax函數介紹及計算方案介紹

  SoftMax 函數是神經網絡中的一種輸出層函數,計算輸出層的值,主要用於神經網絡最後一層。其表達式如下所示:

  設計中的關鍵問題是 自然指數的計算 ,傳統的方案有:

  (1)查表法:同等規格定點數下精度極高,但若要在較大範圍上計算需要消耗大量資源。

  (2)CORDIC:利用迭代特性,資源復用,佔用資源極小,常用於計算器中,但在大規模計算中需要進行流水線化改造,且需要想辦法克服最大旋轉角度限制的問題。

  (3)泰勒級數展開:也即多項式擬合,該法較為靈活,多項式次數越高精度越高,劃分區間越細精度越高,是較為常用的方法。

  本文針對指數計算的特性,設計了一種原理簡單的計算方案,並且通過了板級測試。根據其計算特性稱其為基底查表法。

  在十進位中,若要計算3.68的自然指數我們可以通過公式(1)分別計算e3,e0.6,e0.08,所以可以事先將需要的自然指數值存在ROM表中,計算時將待計算數字通過基底拆分分別得到個位、十分位、百分位,並作為ROM的尋址地址,最後將查表得到的值進行乘法操作即可得到最終結果。但數字電路中實現十進位取整取餘操作時較為複雜的,因此實際使用時對二進位情況進行了優化。

  圖2為基於二進位移位操作的基底拆分示意圖,待計算的16bit數據,高三位表示的是小數點的位置信息,低十三位為數據位。經過左移並按照人為設計的格式輸出即可還原數據。這種方法僅採用移位操作進行基底劃分,因此硬體結構簡單、傳播延時小。

  工程中設計的IP核內部結構,見圖3。

  其中的關鍵流水線如圖4。

  大致原理就是如此,可以看出這種方法也是很靈活的,可以通過簡單地增加ROM和乘法器數量即可擴大計算範圍,而且精度可以通過增減ROM表存儲的定點數位寬進行改變,乘法器可以使用ZYNQ中的DSP資源來提高性能。本次設計的範圍針對[-10,10]。

  2 誤差結果

  測試時分別使用[-10,10],[-5,5]兩個區間中4096個點進行誤差分析,大致過程如圖5。

  最後得到的絕對誤差圖,見圖6。

  誤差在10^-7數量級上,可以說是很小了。

  3 IP核接口介紹

  深度學習又被稱為煉丹,究其原因就是其訓練速度較慢,因此考慮深度學習中的加速問題十分有意義。FPGA由於其定製特性,可以通過邏輯門電路十分高效的完成計算過程。

  本次我使用FPGA實現了一款AXI接口的激活函數softmax的加速器,並且通過PYNQ開發板對其進行驗證同時完成了精度測試。輸入輸出均為AXI總線形式,內部採用了一個AXI_S和一個AXI_M,其中,輸入AXI_S用於ARM端向ip核傳遞寫地址、讀地址、數據個數、輸出數據16/8bit切換,AXI_M完成對PS端DDR的讀寫操作,這樣設計的目的是為了最大化減小ARM端的工作量,使整個系統更加高效,因為AXI_M可以主動的讀寫AXI_S並且AXI_S只能被動的被AXI_M進行讀寫,這個過程設計好後無需ARM端幹預。其結構圖如圖7所示。

  因此涉及的操作為 GPIO口操作,AXI寫操作,DDR操作。這裡原本設計採用ZYNQ上的AXI-HP埠,但是調試時發現該埠在數據格式配置為32 bit時仍採用的64bit數據位,估計是個bug,因此不得不換成AXI-GP埠了。

  (1)從ARM引出的兩個GPIO一個作為復位信號,另一個作為觸發信號

  (2)AXI_M接口,用於配置ip核的一些信息。

  4 任務劃分

  為了充分發揮ARM對通用任務的處理特性以及PL的定製特性,本次設計的系統中PS完成了讀取數據、數據的定點化和數據移動任務,PL端利用其定製化特性完成計算的加速。整體結構框圖如圖8。

  圖中的CPU即為ARM,工作時將模擬輸入的數據寫入DDR,並且完成定點化工作。圖中硬體即為PL端設計的加速器,其工作分為兩個階段,一是計算元素的自然指數值並對其進行求和,二是利用第一個階段的自然指數值和和做除法求得每個元素的softmax值。

  5 PYNQ平臺的優勢

  我的設計在曾在傳統的ZYNQ開發板上進行過調試。設計好硬體後需要結合SDK工具對ARM核進行C語言開發,結果最後需要通過串口返回PC機進行處理。

  在SDK中返回的數據,返回的數據經過上位機的處理才能得到想要的誤差數據,較為繁瑣。

  但PYNQ不一樣,PYNQ上使用了Jupyter可以使用瀏覽器進行在線Pyhthon編程,而且Python中numpy科學計算庫可以只使用3句話就實現softmax的高精度計算,結合pynq的相應庫可以實現軟體處理和硬體控制的無縫銜接,PL端加載bit文件、PL端控制、軟體計算、matplotlib繪製均使用Python完成,最後的結果都可以在網頁中顯示出來,極其方便。

  圖中我使用了matplotlib庫將軟體計算結果與硬體計算結果進行了絕對誤差計算,可直接在網頁中顯示出圖像,更加形象化。本次我的設計中,使用PYNQ完成了 從SD卡中讀入數據,數據定點化,數據寫入DDR,控制PL端進行加速計算,讀DDR,將軟體結果與硬體結果對比通過誤差散點圖來測試設計的IP核的精度。

  ZYNQ與PYNQ平臺的差異可通過對比兩個平臺的系統框圖得到

  可以看出,傳統ZYNQ通常為裸機開發,而且PYNQ一般為在自身運行的Ubuntu上進行Python開發,因此PYNQ相對而言上手簡單加上一些強大的第三方庫的支持使用起來也十分方便、有趣。

  6 PYNQ使用方法

  一些基礎操作可以參考官方Get Start我總結有如下步驟:

  (1)vivado中設計PL端的硬體結構--PC操作,如圖13。

  (2)vivado導出設計tcl文件和bit文件--PC操作

  write_bd_tcl -force C:/Users/Administrator/Desktop/test.tcl

  (3)將tcl文件和bit文件放入PYNQ中--PC操作,如圖14。

  windows上運行 \\pynq 即可通過sdb功能連接PYNQ開發板,進行文件移動

  (4)使用Overlay將bit文件進行加載--PYNQPython操作

  overlay = Overlay('/home/xilinx/pynq/overlays/softmax/design_1.bit')

  至此設計就初始化在PL端,使用Python控制相應外設即可。

  7 Python中相關lib的基本使用

  1.Overlay

  from pynq import Overlayov

  overlay = Overlay('/home/xilinx/pynq/overlays/softmax/design_1.bit')

  用於加載比特流文件至PL端

  2.GPIO

  from pynq import GPIO

  rst = GPIO(GPIO.get_gpio_pin(0), 'out')

  triggle = GPIO(GPIO.get_gpio_pin(1), 'out')

  triggle.write(1)

  rst.write(1)

  rst.write(0)

  rst.write(1)

  操作PS端的GPIO口,操作的是64bit的PS-PL端的EMIO

  3.Xlnk

  from pynq import Xlnk

  xlnk = Xlnk()

  buf = xlnk.cma_array(shape=(num,), dtype=np.uint32, cacheable=0)

  addr = buf.physical_address

  結合numpy在DDR中分配空間,用於PL端AXI_M使用其中physical_address可以得到DDR中的物理地址在分配空間時,有個cacheable屬性,由於PS和PL端都要對DDR進行操作,所以為了防止PS的cache導致讀到的數據未被更新,所以通常需要關閉緩存功能。

  4.AXI從端操作

  myip = overlay.axi_s_control_0

  myip.write(0x00,addr)

  myip.write(0x04,addr)

  myip.write(0x08,num)

  myip.write(0x0c,bool_16)

  myip.read(0x08)

  其中axi_s_control_0是我AXI_S的模塊名稱,這個是python從導出的原理圖tcl文件讀出的,因此需要保證tcl和bit文件的一致性,而且需要兩者同名

  註:這些信息都在上文提到的Get Start連接中可以找到,具體請參考官方的說明。

  8 結論

  此次藉助「全國大學生集成電路創新創業大賽」契機,我們分別在傳統ZYNQ和PYNQ平臺上完成了SoftMax函數的異構計算加速,獲得了比較好的效果。

  在傳統的ZYNQ平臺上開發SoC需要具備數字電路和ARM嵌入式開發知識,比較偏向於底層。反觀PYNQ平臺,利用Python這一優美的語言對ZYNQ操作的封裝極大的降低了開發難度,同時結合Python強大的第三方庫,可玩性極高。

  當今數字電路工程師僅僅掌握數字集成電路的知識是遠遠不夠的,項目開發更加需要複合型人才。我在項目中採用Verilog作為硬體開發語言,使用HLS做雛形開發,同時使用Python及Matlab進行建模及數據分析,使用的軟體工具有Xilinx的VIVADO、ISE,以及Synopsys的DC,ICC,Synplify。可以看出僅僅掌握一門技能是遠遠不夠支撐一個項目的。時代在進步,科技在發展,因此數字IC工程師應該保持住學習的狀態,就比如說近幾年大火的深度學習,十幾年前這個領域還是沒有人願意去碰的,但現在該領域已經讓很多停滯不前的方向又迎來新春。

  世界上還是存在很多機會的,但機會都是留給有準備的人。

  附件:本文設計的softmax ip核在PYNQ運行所需的所有文件https://pan.baidu.com/s/1OuaoS34nIp4Ci96gMCEmug 密碼:ifme

  本文來源於科技期刊《電子產品世界》2019年第6期第69頁,歡迎您寫論文時引用,並註明出處


相關焦點

  • softmax 損失函數 & 參數更新詳解
    要點回歸softmax進階多分類 - 基礎理解softmax多分類實現圖解softmax 損失函數產生及理解對參數求偏導推導及更新要點回歸:邏輯回歸二分類用sigmoid變換成預測單個「概率」,損失函數為交叉熵,用梯度下降求解參數wbsoftmax多分類用softmax
  • 從最優化的角度看待 Softmax 損失函數
    Softmax交叉熵損失函數應該是目前最常用的分類損失函數了,在大部分文章中,Softmax交叉熵損失函數都是從概率角度來解釋的,本周二極市就推送了一篇Softmax相關文章:一文道盡softmax loss及其變種。本文將嘗試從最優化的角度來推導出Softmax交叉熵損失函數,希望能夠啟發出更多的研究思路。
  • 周末AI課堂 理解softmax函數 | 機器學習你會遇到的「坑」
    函數都有著更為本質的意義,我們將會在這一節對softmax進行詳細討論。同時,用於多分類的softmax函數是這怎樣得出的?很多人會把softmax當作sigmoid函數的推廣,但這樣的理解並不是自然的,比如面對多分類問題,softmax函數會輸出每個結果的概率,和為1;但sigmoid函數會對每一個數據輸出屬於該結果和不屬於該結果的概率,這個概率之和為1,但對於每個結果而言,概率之和並不為1,事實上,sigmoid函數的背後有著更為本質的原因,我們可以分別從廣義線性模型的角度來理解softmax
  • 深度學習中常見的損失函數
    在深度學習分類任務中,我們經常會使用到損失函數,今天我們就來總結一下深度學習中常見的損失函數。該式其實是式(1)的推廣,正如softmax是sigmoid的多類別推廣一樣,在TensorFlow裡面根據最後分類函數softmax和sigmoid就分為softmax交叉熵以及sigmoid的交叉熵,並對這兩個功能進行統一封裝。
  • 神經網絡中的各種損失函數介紹
    不同的損失函數可用於不同的目標。在這篇文章中,我將帶你通過一些示例介紹一些非常常用的損失函數。這篇文章提到的一些參數細節都屬於tensorflow或者keras的實現細節。損失函數的簡要介紹損失函數有助於優化神經網絡的參數。
  • 機器學習中的激活函數綜合指南
    激活函數對神經網絡的效率和穩定性起著至關重要的作用。在這篇文章中,將儘可能簡要地概述激活函數的最新發展,並關注為什麼需要它們以及何時應用它們。為什麼需要激活函數?簡而言之,激活函數解決了神經網絡中的兩個關鍵問題:確保激活映射是非線性的,因此彼此獨立;確保某些輸出具有基本的數值特性,例如,在[- 1,1]範圍內或為有效的概率分布。
  • 楊植麟等人瞄準softmax瓶頸,新方法顧表達性和高效性
    但是,正如楊植麟等人在之前研究 [19]中所指出的,softmax 限制了神經語言模型的表達能力,因為它將輸出表示限制在低秩,這不足以建模自然語言的複雜性。該局限叫做「softmax 瓶頸」。它不像 MoS 在概率空間中部署標量混合(scalar mixture),而是在 logit 空間中應用向量門控機制,以避免使用多個成本高昂的 softmax。此外,Mixtape 還使用了另外兩項新技術來進一步降低計算成本。首先,向量門控機製成本高昂,因為該機制需要我們對詞彙表中的每一個詞計算 softmax 門控。
  • CMU楊植麟等人再次瞄準softmax瓶頸,Mixtape兼顧表達性和高效性
    但是,正如楊植麟等人在之前研究 [19]中所指出的,softmax 限制了神經語言模型的表達能力,因為它將輸出表示限制在低秩,這不足以建模自然語言的複雜性。該局限叫做「softmax 瓶頸」。MoS →Mixtape為了降低 MoS 的計算成本,最近楊植麟等人提出了一種高效解決 softmax 瓶頸的新型輸出層 Mixtape。Mixtape 可作為額外層嵌入到任意現有網絡的交叉熵損失函數之前。它不像 MoS 在概率空間中部署標量混合(scalar mixture),而是在 logit 空間中應用向量門控機制,以避免使用多個成本高昂的 softmax。
  • 「技術綜述」一文道盡softmax loss及其變種
    本文首發於知乎專欄《有三AI學院》,https://zhuanlan.zhihu.com/c_151876233今天來說說softmax loss以及它的變種1 softmax losssoftmax loss是我們最熟悉的loss之一了,分類任務中使用它,分割任務中依然使用它。
  • RBF-Softmax:讓模型學到更具表達能力的類別表示
    在很多現有的方法中,得到的logits會進行softmax的歸一化,得到每個類別的概率。歐式距離是一種很常用的相似性度量方法,而且具有很清晰的幾何意義。但是,現有的基於softmax的方法並不是直接去優化歐式距離,而是優化類內和類間的相對差別。
  • 深入理解深度學習中的激活函數
    導讀數字邏輯電路中的門電路可以讓滿足不同條件的輸入信號輸出開(1)或關(0)輸出。這體現在機器學習中感知機的性質。但我們也知道感知機有個局限性,即無法單層表示非線性變化,而神經網絡往往通過激活函數用來表示非線性變化。即激活函數的作用就是引入非線性。
  • TensorFlow四種Cross Entropy算法實現和應用
    ➤TensorFlow的交叉熵函數TensorFlow針對分類問題,實現了四個交叉熵函數,分別是tf.nn.sigmoid_cross_entropy_with_logits、tf.nn.softmax_cross_entropy_with_logits、tf.nn.sparse_softmax_cross_entropy_with_logits
  • TensorFlow四種Cross Entropy算法的實現和應用
    這裡多次強調sigmoid激活函數,是因為在多目標或者多分類的問題下有些函數是不可用的,而TensorFlow本身也提供了多種交叉熵算法的實現。注釋中還提到這10個分類之間是獨立的、不要求是互斥,這種問題我們成為多目標,例如判斷圖片中是否包含10種動物,label值可以包含多個1或0個1,還有一種問題是多分類問題,例如我們對年齡特徵分為5段,只允許5個值有且只有1個值為1,這種問題可以直接用這個函數嗎?答案是不可以,我們先來看看sigmoid_cross_entropy_with_logits的代碼實現吧。
  • 神經網絡中的激活函數
    什麼是神經網絡激活函數?激活函數有助於決定我們是否需要激活神經元。如果我們需要發射一個神經元那麼信號的強度是多少。激活函數是神經元通過神經網絡處理和傳遞信息的機制為什麼在神經網絡中需要一個激活函數?在神經網絡中,z是輸入節點與節點權值加上偏差的乘積。
  • 通過對抗損失函數來降低對抗損失函數的效用
    該文將進一步通過對抗損失函數來降低對抗損失函數的效用,並且使用優化ranknet-2模型實現對抗損失函數。同時將softmax函數映射到了循環網絡中,即將損失函數映射到了dnn整體和用戶的得分之間的差值之間的回歸梯度,增強網絡網絡的泛化能力。
  • 【強化學習實戰】基於gym和tensorflow的強化學習算法實現
    現在我們回顧一下:圖2.1 qlearning 算法偽代碼  從圖2.1中我們看到,qlearning算法的實現可以分為以下關鍵點:  行為值函數的表示,探索環境的策略,epsilon貪婪策略,值函數更新時選擇動作的貪婪策略,值函數更新。下面,我就逐個講解一下。
  • 用Python實現多層感知器神經網絡
    激活函數是一種確保感知器「發射」或僅在達到一定輸入水平後才激活的數學方法。常見的非線性激活函數為S型,softmax,整流線性單位(ReLU)或簡單的tanH。激活函數有很多選項,但是在本文中我們僅涉及Sigmoid和softmax。
  • 機器學習算法中的7個損失函數的詳細指南
    當然是有的,簡而言之,機器學習中損失函數可以解決以上問題。損失函數是我們喜歡使用的機器學習算法的核心。但大多數初學者和愛好者不清楚如何以及在何處使用它們。它們並不難理解,反而可以增強你對機器學習算法的理解。那麼,什麼是損失函數,你如何理解它們的意義?
  • Python機器學習算法中的7個損失函數的詳細指南
    當然是有的,簡而言之,機器學習中損失函數可以解決以上問題。損失函數是我們喜歡使用的機器學習算法的核心。但大多數初學者和愛好者不清楚如何以及在何處使用它們。它們並不難理解,反而可以增強你對機器學習算法的理解。那麼,什麼是損失函數,你如何理解它們的意義?在本文中,我將討論機器學習中使用的7種常見損失函數,並解釋每種函數的使用方法。
  • Pytorch 0.3.0 發布,實現多方面提速,增加對ONNX支持
    根據官方文檔的介紹,此次增加了多個函數和功能,多方面的性能均實現提升。重大變更0.3 版本中刪掉了 Variable.reinforce() 等隨機函數,因為它們的功能有限,並且會影響到性能。設置隨機函數的初衷是為了避免採樣值的 book-keeping,在實際中,由於各種各樣的原因,用戶的代碼中仍然會包括 book-keeping。