由于此前的大部分實現(xiàn)都是基于高級語言的(如Java、Python、Lua等),而即使是執(zhí)行最簡單的操作,高級語言也會比低級語言消耗更多的CPU周期,更何況是結(jié)構(gòu)復(fù)雜的深度神經(jīng)網(wǎng)絡(luò),因此運算緩慢就成了高級語言的一個天然的缺陷。
目前針對這一問題有兩種解決方案。
第一種方法是模擬傳統(tǒng)的編譯器。就好像傳統(tǒng)編譯器會把高級語言編譯成特定平臺的匯編語言實現(xiàn)高效運行一樣,這種方法將高級語言轉(zhuǎn)換為C語言,然后在C語言基礎(chǔ)上編譯、執(zhí)行。為了實現(xiàn)這種轉(zhuǎn)換,每一種張量操作的實現(xiàn)代碼都會預(yù)先加入C語言的轉(zhuǎn)換部分,然后由編譯器在編譯階段將這些由C語言實現(xiàn)的張量操作綜合在一起。目前pyCUDA和Cython等編譯器都已經(jīng)實現(xiàn)了這一功能。
第二種方法就是前文提到的,利用腳本語言實現(xiàn)前端建模,用低級語言如C++實現(xiàn)后端運行,這意味著高級語言和低級語言之間的交互都發(fā)生在框架內(nèi)部,因此每次的后端變動都不需要修改前端,也不需要完整編譯(只需要通過修改編譯參數(shù)進(jìn)行部分編譯),因此整體速度也就更快。
除此之外,由于低級語言的最優(yōu)化編程難度很高,而且大部分的基礎(chǔ)操作其實也都有公開的最優(yōu)解決方案,因此另一個顯著的加速手段就是利用現(xiàn)成的擴(kuò)展包。例如最初用Fortran實現(xiàn)的BLAS(基礎(chǔ)線性代數(shù)子程序),就是一個非常優(yōu)秀的基本矩陣(張量)運算庫,此外還有英特爾的MKL(Math Kernel Library)等,開發(fā)者可以根據(jù)個人喜好靈活選擇。
值得一提的是,一般的BLAS庫只是針對普通的CPU場景進(jìn)行了優(yōu)化,但目前大部分的深度學(xué)習(xí)模型都已經(jīng)開始采用并行GPU的運算模式,因此利用諸如NVIDIA推出的針對GPU優(yōu)化的cuBLAS和cuDNN等更據(jù)針對性的庫可能是更好的選擇。
運算速度對于深度學(xué)習(xí)框架來說至關(guān)重要,例如同樣訓(xùn)練一個神經(jīng)網(wǎng)絡(luò),不加速需要4天的時間,加速的話可能只要4小時。在快速發(fā)展的人工智能領(lǐng)域,特別是對那些成立不久的人工智能初創(chuàng)公司而言,這種差別可能就會決定誰是先驅(qū)者,而誰是追隨者。
總結(jié)
原文作者在文末指出:為了向開發(fā)者提供盡量簡單的接口,大部分深度學(xué)習(xí)框架通常都會將普通的概念抽象化,這可能是造成許多用戶感知不到上述五點核心組件的重要原因。
而這也正是作者寫本文的初衷:他希望開發(fā)者能夠通過了解不同框架之間的一些相似特性,更好地認(rèn)識和使用一個深度學(xué)習(xí)框架。另一方面,對于那些不僅對學(xué)會使用深度學(xué)習(xí)框架感興趣,還打算親手搭建一個深度框架的朋友,作者認(rèn)為了解各框架的內(nèi)部組成和一些共性的特征也是邁向成功的重要一步。他真誠地相信,一個優(yōu)秀的工程師不僅應(yīng)該“知其然”,更應(yīng)該“知其所以然”。