當(dāng)我們談?wù)?MegEngine 時(shí),我們?cè)谡務(wù)撌裁?/h2>
眾所周知,開源深度學(xué)習(xí)框架曠視天元(MegEngine)是曠視自主研發(fā)的國產(chǎn)工業(yè)級(jí)深度學(xué)習(xí)框架 ,是曠視新一代 AI 生產(chǎn)力平臺(tái) Brain++ 的最核心組件,在2020年3月正式向全球開發(fā)者開源。MegEngine 憑借其訓(xùn)練推理一體、超低硬件門檻和全平臺(tái)高效推理 3 大核心優(yōu)勢(shì),幫助企業(yè)與開發(fā)者大幅節(jié)省產(chǎn)品從實(shí)驗(yàn)室原型到工業(yè)部署的流程,真正實(shí)現(xiàn)小時(shí)級(jí)的轉(zhuǎn)化能力。
MegEngine 自上向下包含三個(gè)層次:Imperative、MegBrain 和 MegDNN。它們的角色定位分別是:
-
Imperative:MegEngine為動(dòng)態(tài)訓(xùn)練設(shè)計(jì)的一套新接口,負(fù)責(zé)處理動(dòng)態(tài)圖運(yùn)行時(shí)(Imperative Runtime)。 -
MegBrain:負(fù)責(zé)處理靜態(tài)圖運(yùn)行時(shí)(Graph Runtime)。 -
MegDNN:MegEngine的底層計(jì)算引擎。
下面再從下到上介紹一下這三個(gè)模塊在 MegEngine 中的作用。
MegEngine 的底層計(jì)算引擎 —— MegDNN
MegDNN 在 MegEngine 中扮演的角色是底層計(jì)算引擎。MegDNN 是一個(gè)跨平臺(tái)的底層算子庫,訓(xùn)練和推理過程中的所有計(jì)算操作最終都需要落到一個(gè) MegDNN 的算子上進(jìn)行,一個(gè) MegDNN 算子可能會(huì)根據(jù)場(chǎng)景(如張量尺寸等)有一個(gè)或多個(gè)不同的實(shí)現(xiàn)(也叫 kernel)。
作為一個(gè)跨平臺(tái)的計(jì)算庫,MegDNN 為我們提供豐富的與 Tensor 相關(guān)的計(jì)算原語,比如 Convolution、Pooling、MatrixMul、Transpose 等。目前 MegDNN 支持的平臺(tái)有:x86、arm、CUDA、RoCM、OpenCL、Hexagon 等。

感興趣的同學(xué)可以在這里看到 MegDNN 在各個(gè)平臺(tái)下的 kernel 具體實(shí)現(xiàn)。
靜態(tài)圖運(yùn)行時(shí)管家 —— MegBrain
為了確保訓(xùn)練推理一致性, Imperative 中復(fù)用了 MegBrain 的計(jì)算代碼,因此我們需要了解 MegBrain 做了什么。
MegBrain 負(fù)責(zé)處理靜態(tài)圖的運(yùn)行時(shí),主要提供 C++ 的訓(xùn)練和推理接口。
從下面的 MegEngine 整體架構(gòu)圖可以看出,Imperative 通過 Tensor Interpreter (張量解釋器)復(fù)用了許多 MegBrain 的代碼。比如 shape 推導(dǎo)、計(jì)算、求導(dǎo)、Trace 等。

在 MegBrain 中,一個(gè) Computing Graph 由 SymbolVar 以及許多 op (算子,operator)組成。SymbolVar 是在 MegBrain 層面 Tensor 的表示,可以理解為傳遞給 op 進(jìn)行計(jì)算的數(shù)據(jù)。作個(gè)類比,op 是類似加減乘除這樣的計(jì)算操作(在深度學(xué)習(xí)中常用的有 convolution、pooling 等),SymbolVar 就是我們用來進(jìn)行加減乘除的“數(shù)”(在深度學(xué)習(xí)中就是 Tensor)。
MegEngine 動(dòng)態(tài)圖接口 —— Imperative 登場(chǎng)
因?yàn)?MegEngine 是動(dòng)靜合一的深度學(xué)習(xí)框架,MegBrain 解決了靜態(tài)圖的訓(xùn)練和推理問題,還需要有一個(gè)“組件”負(fù)責(zé)處理動(dòng)態(tài)圖的訓(xùn)練和推理、以及 Python 側(cè)的訓(xùn)練接口,于是便有了 Imperative,也就是說,Imperative Runtime 是為了動(dòng)態(tài)訓(xùn)練而單獨(dú)設(shè)計(jì)的一套新接口。
實(shí)際上,在 MegBrain 的 Computing Graph 中已經(jīng)有了非常多的算子實(shí)現(xiàn),因此 MegEngine 的 Imperative 借助張量解釋器 Tensor Interpreter 較多地復(fù)用了 MegBrain 中的 op。這樣做的原因是:
- 重寫算子代價(jià)高,且容易寫錯(cuò)。
- 若
Imperative的實(shí)現(xiàn)和MegBrain的實(shí)現(xiàn)不一致的話,容易導(dǎo)致訓(xùn)練推理不一致。
除了復(fù)用 MegBrain 的部分功能,Imperative 自身包含的模塊主要有:Module(定義深度學(xué)習(xí)網(wǎng)絡(luò)的基礎(chǔ)類的實(shí)現(xiàn))、Optimizer(一些優(yōu)化器的實(shí)現(xiàn))、Functional(提供 python 層的訓(xùn)練接口)、Interpreter(計(jì)算入口,底層會(huì)調(diào)用 kernel 或者 MegBrain 的算子實(shí)現(xiàn))、DTR(動(dòng)態(tài)重計(jì)算模塊)、Tracer(記錄計(jì)算圖的計(jì)算過程)等。
這些模塊會(huì)在之后的文章中有更詳細(xì)的介紹,感興趣的同學(xué)可以查閱 MegEngine 官方文檔。
總結(jié):Imperative 與 MegDNN / MegBrain 的關(guān)系
簡單來說,MegDNN 負(fù)責(zé) MegEngine 中所有的計(jì)算操作在各個(gè)平臺(tái)(CUDA 等)的最終實(shí)現(xiàn),無論是 MegBrain 還是 Imperative 的 op,最終都需要通過調(diào)用 MegDNN kernel 來完成計(jì)算。
既然 MegDNN 包攬了計(jì)算的活兒,那么在訓(xùn)練推理過程中那些與計(jì)算無關(guān)的工作,自然就落到了 MegBrain 和 Imperative 的頭上。這些工作包括:求導(dǎo)、內(nèi)存分配、對(duì) Tensor 的 shape 進(jìn)行推導(dǎo)、圖優(yōu)化、編譯等。
MegEngine 整體上是有兩部分 Runtime 以及底層的一些公共組件組成的。這兩部分的 Runtime 分別叫做 Graph Runtime(對(duì)應(yīng) MegBrain) 和 Imperative Runtime(對(duì)應(yīng) Imperative)。
Graph Runtime 負(fù)責(zé)靜態(tài)圖部分,主要提供 C++ 訓(xùn)練推理接口。實(shí)際計(jì)算時(shí)需要調(diào)用 MegDNN 的實(shí)現(xiàn)。
Imperative Runtime 負(fù)責(zé)動(dòng)態(tài)圖部分,主要為動(dòng)態(tài)訓(xùn)練提供 Python 接口。實(shí)際計(jì)算時(shí)需要調(diào)用 MegBrain 的已有實(shí)現(xiàn)或者直接調(diào)用 MegDNN 的 kernel。