簡介
在軟體工程領域,許多科學計算軟體的開發延用著傳統的開發技術。傳統的軟體開發方法具有編寫容易、目的明確等優點,運算速度基本能滿足需要,但其主要不足是:(1)開發的軟體規模較小,功能單一,重複利用率低;(2)較難進行多語言聯合開發及二次開發;(3)由於FOrtran自身及其所使用的套用框架的局限性,使之可視化界面粗糙,且不能充分發揮現有作業系統及各種套用伺服器的先進功能來進行網路化的分散式管理。當不僅僅把計算程式作為一種公式計算器時,我們需要一種新的開發方法來進行軟體開發,而運用這種方法開發需要達到以下要求:(1)軟體的通用性較強,具有高度的集成性和複雜度,二次開發較為方便,在WindOws下具有友好的人機界面,能充分利用網路進行分散式管理;(2)能有效地區分科學計算核心和其他管理功能的開發任務,使負責編寫科學計算程式的工程師與負責其它設計任務的程式設計師的工作能夠清楚地分開,讓計算功能儘可能地從具體問題中抽象出來,計算工程師可用與原來相似的方法編寫計算核心程式,甚至原有的程式被稍加改動既可變為計算框架的新核心,從而大大提高了原有計算程式的利用率,而對外圍程式可利用與計算核心無關的最先進的開發手段進行開發。
進行科學計算軟體開發的主要問題是如何使應用程式框架高效、合理、安全地操作計算程式核心,使之能正常工作並能返回正確的運行結果。主要的實現方法有6種:(1)利用檔案作為接口傳遞參數;(2)編寫共享記憶體接口庫使核心與主框架通訊;(3)利用資料庫作為參數控制管理核心的方式;(4)將計算核心改寫為FOrtran動態程式庫的形式由主框架直接調用;(5)將計算核心部署為COM/DCOM/ActiVeX組件;(6)部署為Web形式的B/S結構。
設計與實現
方法一
該方法利用檔案作為接口傳遞參數與計算核心進行通信。主程式框架將核心所需的參數以檔案的形式寫入指定路徑,然後啟動核心進程,將參數從檔案中讀取出來進行運算。這種方法簡單快捷,容易開發,持久保持在硬碟中的參數記錄下計算過程,使計算核心進程在重新啟動後能繼續執行計算工作,無需從頭再來,這符合大多數計算程式讀取參數的方式,計算程式做很小改動,甚至不做改動就可無縫地融合到整個框架之中。該方法最符合開發科學計算軟體的程式設計師的習慣。
方法二
該方法編寫共享記憶體接口庫使核心與主框架通訊。在Win32環境下,每一個進程都有獨立的進程空間,其它進程不能訪問,要想利用記憶體進行公共數據交換,可選擇建立記憶體映像檔案的方法來實現。利用記憶體映像檔案與計算核心進程通訊具有I/O開銷小,數據傳輸效率高"操作靈活的優點,其速度優勢在處理較大量數據傳輸的問題時非常明顯,十分適合傳遞格線、圖像之類的大型數組數據,不必生成中間檔案"在一定程度上避免了中間狀態數據的泄漏。由於程式語言的限制和程式分工的不同,讓Fortan程式設計師直接調用Win32的API函式實現上述功能既不方便編寫,又不利於Fortran程式作為計算核心的抽象性,所以建議把要使用的API函式封裝到一個用其它語言編寫的動態程式庫中,供Fortran程式調用,使其源程式相對簡化。
方法三
該方法利用資料庫作為參數控制管理核心。這種方式使數據的保存、更新、刪除等工作更加方便,對參數的檢索方式更為靈活,在一些實際的工程中已經出現了這種帶資料庫接口的工程計算程式:利用資料庫接口,將計算過程中的信息以及計算結果進行存取,再在計算結果資料庫之上建立管理信息系統,從而對計算數據進行查詢和分析。雖然此模式有一些成功案例,但它的問題是:在計算程式中使用資料庫接口進行大量繁雜的數據操作,破壞了計算程式作為核心的單純性,使其編寫的複雜性大大增加。同時由於Fortan語言和VisualFortanFramework的限制,它的資料庫性能無法與VC++/Delphi相比,用這種方法編寫的程式的資料庫性能和穩定性相對較差。同時將資料庫的接口封裝在不同計算核心中既可能占用更多的資源,又會產生數據同步性差的隱患,還不利於整個框架的部署,建議將資料庫的工作交給框架平台,而用於計算的核心進程應專注於計算本身,將必要的計算過程和計算結果數據的存取修改以訊息的方式通知框架平台,由它進行處理。
方法四
該方法將計算核心改寫為Fortran動態程式庫(DLL)的形式由主框架直接調。當應用程式調用動態程式庫函式時,會將這個DLL映射到自身進程的記憶體空間內(BFFFFFFF-80000000)。DLL將利用調用它的進程來堆疊,故調用DLL中的函式就像調用本身的函式一樣方便不存在多進程通訊的複雜處理過程。由於DLL在記憶體中只存在一份,調用程式僅是將它的記憶體地址映射到自己的記憶體地址空間,所以當有多個進程調用同一個DLL時,作業系統只會將這個DLL的副本複製到進程,而不會像開闢獨立進程那樣再開闢記憶體,使用DLL的效率比使用進程要高。
將計算核心改寫為Fortran動態程式庫以供主框架調用是一種高效快捷的方法,但它的優勢有時也會轉換為劣勢。由於它需要注入別的進程,所以DLL不能單獨運行,例如為了快捷方便,用戶可能直接啟動一些計算模組,但DLL卻做不到這一點(運行rundll32.exe可以執行某個DLL但是不夠靈活而且在顯示表達上也不夠豐富),另外當它所注入的進程因為錯誤(也有可能是該進程引用的其他DLL的錯誤)導致本進程無法繼續運行時,這個進程相關聯的所有DLL也都會在進程空間裡失效,這種失效有可能會使一個計算了幾天的工作結果付之東流,相對前面所提到的基於多進程的結構,這種基於DLL的多執行緒結構的穩定性比較差(ORACLE資料庫就是基於多進程的而微軟的SOLSERVER是基於多執行緒的),所以在涉及到長時間、大強度、關鍵性運算時使用動態程式庫框架要慎重。
方法五
該方法將計算核心部署為COM/DCOM/ActiveX組件的形式。COM(ComponentObjectModel)即組建對象模型時Windows系統的核心,也可以說Windows就是建立在COM模型之上的。編寫COM對象不但可以實現二進制級別上的代碼復用,還可以深入到系統的核心。任何支持接口(Interface)的程式語言都可以調用COM對象的接口方法,而COM對象接口如果繼承自Idispatch那該接口的方法可以被腳本語言調用,這將大大豐富COM對象的使用面。在網路上部署的COM組件被稱為DCOM,DCOM需要部署為進程外伺服器或部署在MTS之類的套用伺服器之上,供使用者在網路上進行分散式調用。這樣做的好處是可以充分發揮網路資源的優勢,根據每台機器的特點部署不同計算強度的組件,使計算力量合理分配。而這一切對使用者來說又幾乎是透明的,操作起來就像操作本地電腦一樣方便。當然,這樣的做法較複雜,不太適合負責計算模組的程式設計師編寫。可先用C++/ObjectPascal之類的語言編寫COM對象,再用前文的方法1~4將對象與底層核心組合起來,由COM負責與核心的通信,訪問程式只和COM對象打交道。
方法六
該方法將開發框架部署為Web形式的B/S結構。將計算程式和管理它的WebApplication安裝在伺服器上的優勢是:客戶端無需再安裝任何軟體和進行複雜的系統配置,就可在任何地方使用任何系統進行計算。不僅可以在區域網路內使用這種B/S結構的計算框架,在Internet上同樣可以讓瀏覽器操作防火牆後的計算程式,當然這種操作可以是集成了安全認證的。用這種方式構建的遠程計算框架可以為我們帶來一種較為流行的軟體提供形式,即ApplicationSerVice交付給客戶的不再是光碟中的軟體和複雜的使用說明書,而可能僅僅是一張寫有伺服器網址和用戶名密碼的卡片,甚至是限制計算次數的充值卡。這種框架不太適合用ASPActiVeXSerVerPage實現,因為這裡涉及到本地代碼的調用問題,可以考慮使用Jsp+JaVaBean/EJB或VC++/Delphi編寫的ISAPI來實現。ISAPI即InternetSerVerApplicationProgramInterface是微軟提供的一套面向Internet服務的API接口。SAPI的工作原理是通過互動式主頁取得用戶輸入信息,然後交伺服器後台處理。在ISAPI下建立的應用程式是以動態程式庫的形式存在的,ISAPI套用的DLL不僅可以象CGI(即通用網關接口CommonGatewayInterface)程式一樣被用戶請求激活,還可以被系統預先激活來監視用戶輸入。被用戶激活的DLL在處理完一個用戶請求後將繼續駐留在記憶體中等待處理別的用戶輸入,直到過了一段無用戶輸入時間後才消失。一個ISAPI的DLL可在被用戶請求激活後長駐記憶體,等待用戶的另一個請求,還可在一個DLL里設定多個用戶請求處理函式,此外ISAPI的DLL應用程式和WWW伺服器處於同一個進程中,效率要顯著高於CGI。
常用的深度學習科學計算框架
Tensorflow
TensorFlow是一款開源的數學計算軟體,使用數據流圖(DataFlowGraph)的形式進行計算。圖中的節點代表數學運算,而圖中的線條表示多維數據數組(tensor)之間的互動。TensorFlow靈活的架構可以部署在一個或多個CPU、GPU的台式以及伺服器中,或者使用單一的API套用在移動設備中。TensorFlow最初是由研究人員和GoogleBrain團隊針對機器學習和深度神經網路進行研究所開發的,開源之後可以在幾乎各種領域適用。
TensorFlow的特點:
機動性:TensorFlow並不只是一個規則的neuralnetwork庫,事實上如果你可以將你的計算表示成dataflowgraph的形式,就可以使用TensorFlow。用戶構建graph,寫內層循環代碼驅動計算,TensorFlow可以幫助裝配子圖。定義新的操作只需要寫一個Python函式,如果缺少底層的數據操作,需要寫一些C++代碼定義操作。
可適性強:可以套用在不同設備上,cpus,gpu,移動設備,雲平台等
自動差分:TensorFlow的自動差分能力對很多基於Graph的機器學習算法有益
多種程式語言可選:TensorFlow很容易使用,有python接口和C++接口。其他語言可以使用SWIG工具使用接口。(SWIG—SimplifiedWrapperandInterfaceGenerator,是一個非常優秀的開源工具,支持將C/C++代碼與任何主流腳本語言相集成。)
最最佳化表現:充分利用硬體資源,TensorFlow可以將graph的不同計算單元分配到不同設備執行,使用TensorFlow處理副本。
Torch
Torch是一個有大量機器學習算法支持的科學計算框架,其誕生已經有十年之久,但是真正起勢得益於Facebook開源了大量Torch的深度學習模組和擴展。Torch另外一個特殊之處是採用了程式語言Lua(該語言曾被用來開發視頻遊戲)。
Torch的優勢:
•構建模型簡單
•高度模組化
•快速高效的GPU支持
•通過LuaJIT接入C
•數值最佳化程式等
•可嵌入到iOS、Android和FPGA後端的接口
Caffe
Caffe由加州大學伯克利的PHD賈揚清開發,全稱ConvolutionalArchitectureforFastFeatureEmbedding,是一個清晰而高效的開源深度學習框架,由伯克利視覺學中心(BerkeleyVisionandLearningCenter,BVLC)進行維護。(賈揚清曾就職於MSRA、NEC、GoogleBrain,他也是TensorFlow的作者之一,任職於FacebookFAIR實驗室。)
Caffe基本流程:Caffe遵循了神經網路的一個簡單假設——所有的計算都是以layer的形式表示的,layer做的事情就是獲得一些數據,然後輸出一些計算以後的結果。比如說卷積——就是輸入一個圖像,然後和這一層的參數(filter)做卷積,然後輸出卷積的結果。每一個層級(layer)需要做兩個計算:前向forward是從輸入計算輸出,然後反向backward是從上面給的gradient來計算相對於輸入的gradient,只要這兩個函式實現了以後,我們就可以把很多層連線成一個網路,這個網路做的事情就是輸入我們的數據(圖像或者語音等),然後來計算我們需要的輸出(比如說識別的標籤),在訓練的時候,我們可以根據已有的標籤來計算損失和gradient,然後用gradient來更新網路的參數。
Caffe的優勢:
上手快:模型與相應最佳化都是以文本形式而非代碼形式給出
速度快:能夠運行最棒的模型與大量的數據
模組化:方便擴展到新的任務和設定上
開放性:公開的代碼和參考模型用於再現
社區好:可以通過BSD-2參與開發與討論
Theano
2008年誕生於蒙特婁理工學院,Theano派生出了大量深度學習Python軟體包,最著名的包括Blocks和Keras。Theano的核心是一個數學表達式的編譯器,它知道如何獲取你的結構。並使之成為一個使用numpy、高效本地庫的高效代碼,如BLAS和本地代碼(C++)在CPU或GPU上儘可能快地運行。它是為深度學習中處理大型神經網路算法所需的計算而專門設計的,是這類庫的發明之一(發展始於2007年),被認為是深度學習研究和開發的行業標準。
Theano的優勢:
•集成NumPy-使用numpy.ndarray
•使用GPU加速計算-比CPU快140倍(只針對32位float類型)
•有效的符號微分-計算一元或多元函式的導數
•速度和穩定性最佳化
•動態地生成C代碼-更快地進行計算
•廣泛地單元測試和自我驗證-檢測和診斷多種錯誤
•靈活性好