【TVM系列四】模型編譯與運(yùn)行過程

一红选、前言

針對(duì)神經(jīng)網(wǎng)絡(luò)模型的編譯,TVM封裝了非常簡潔的python接口,如下:

# keras前端導(dǎo)入弦讽,使用llvm作為target編譯
mod, params = relay.frontend.from_keras(keras_resnet50, shape_dict)
# compile the model
target = "llvm"
dev = tvm.cpu(0)
with tvm.transform.PassContext(opt_level=0):
    model = relay.build_module.create_executor("graph", mod, dev, target, params).evaluate()
print(model)
tvm_out = model(tvm.nd.array(data.astype(dtype)))

在上一篇文章中介紹了模型的算子轉(zhuǎn)換與Relay IR Module的流程,當(dāng)TVM將Relay IR Module模型編譯為runtime module時(shí)膀哲,可以通過下面的函數(shù)完成:

model = relay.build_module.create_executor("graph", mod, dev, target, params).evaluate()

它返回的是一個(gè)函數(shù)入口往产,從打印的輸出可以看到它所指向的函數(shù):

<function graphexecutor._make_executor.._graph_wrapper at 0x7fb634b3ed30>

下面這一句相當(dāng)于將輸入傳入這個(gè)函數(shù)去運(yùn)行:

tvm_out = model(tvm.nd.array(data.astype(dtype)))

這兩個(gè)步驟在TVM中的運(yùn)行過程是怎么樣的呢被碗?這篇文章將圍繞這個(gè)問題進(jìn)行相關(guān)的介紹。

二仿村、模型編譯

image.png

首先來看一下TVM是如何調(diào)用到編譯函數(shù)的:

  • create_executor(...)函數(shù)會(huì)根據(jù)executor的類型返回相應(yīng)的執(zhí)行器對(duì)象蛮放,這里使用的是"graph",所以返回的是GraphExecutor(...)對(duì)象奠宜,類class GraphExecutor()是_interpreter.Executor的子類包颁。

  • 類class Executor(object)是一個(gè)接口類,它的成員函數(shù)_make_executor()是一個(gè)接口函數(shù)压真,繼承它的子類需要實(shí)現(xiàn)娩嚼,它的另一個(gè)成員函數(shù)evaluate()會(huì)調(diào)用_make_executor(),也即調(diào)用子類class GraphExecutor實(shí)現(xiàn)的_make_executor()成員函數(shù)滴肿。

  • _make_executor()主要的工作是調(diào)用build(...)函數(shù)對(duì)Relay IR Module進(jìn)行編譯岳悟,并且提供graph執(zhí)行器的運(yùn)行函數(shù),也就是前言小節(jié)中提到的:

    <function graphexecutor._make_executor.._graph_wrapper at 0x7fb634b3ed30>
    

下面介紹一下build(...)函數(shù)的過程:

  • 首先實(shí)例化一個(gè)build_module對(duì)象bld_mod泼差,對(duì)象的實(shí)例化流程是通過tvm._ffi._init_api("relay.build_module", name)調(diào)用C++端的接口RelayBuildCreate()贵少,它會(huì)創(chuàng)建RelayBuildModule對(duì)象。

  • 然后通過bld_mod["build"]查找到編譯函數(shù)的PackedFunc堆缘,這個(gè)主要是通過類class RelayBuildModule中的GetFunction(...)實(shí)現(xiàn)滔灶。它會(huì)調(diào)用類class RelayBuildModule的成員函數(shù)Build(...),在對(duì)一些成員變量進(jìn)行賦值后吼肥,調(diào)用最終的BuilRelay(...)將Relay IR Module編譯為runtime module录平。

  • 最后會(huì)返回一個(gè)GraphExecutorFactoryModule(...)對(duì)象,這個(gè)對(duì)象在初始化的時(shí)候會(huì)調(diào)用C++端的接口創(chuàng)建類class GraphExecutorFactory的對(duì)象缀皱。

其中BuildRelay的調(diào)用過程如下圖所示斗这,它主要有兩個(gè)步驟,一個(gè)是對(duì)relay_module做了OptimizeImpl(...)的優(yōu)化啤斗,對(duì)模型進(jìn)行算子的融合表箭、fold constants以及其它的一些優(yōu)化;第二個(gè)是創(chuàng)建codegen對(duì)象并生成lowered_funcs并調(diào)用tvm::build(...)進(jìn)行編譯钮莲。

image.png

整個(gè)模型編譯的過程可以總結(jié)為:將Relay IR Module編譯為runtime module并為其構(gòu)造好執(zhí)行器的對(duì)象免钻。

三、模型運(yùn)行

模型運(yùn)行時(shí)會(huì)調(diào)用_make_executor(...)里定義的_graph_wrapper(...)函數(shù):

def _graph_wrapper(*args, **kwargs):
    args = self._convert_args(self.mod["main"], args, kwargs)
# Create map of inputs.
for i, arg in enumerate(args):
        gmodule.set_input(i, arg)
# Run the module, and fetch the output.
    gmodule.run()
    flattened = []
for i in range(gmodule.get_num_outputs()):
        flattened.append(gmodule.get_output(i).copyto(_nd.cpu(0)))
    unflattened = _unflatten(iter(flattened), ret_type)
return unflattened
  • 該函數(shù)首先會(huì)遍歷輸入的數(shù)據(jù)臂痕,并調(diào)用set_input(...)為module設(shè)置輸入?yún)?shù)伯襟,然后調(diào)用run()進(jìn)行模型推理,最后獲取輸出的結(jié)果握童。

  • 在類class GraphExecutorFactory的成員函數(shù)GetFunction(...)中股淡,如果輸入的name是模型名稱痢畜,則通過ExecutorCreate(...)創(chuàng)建GraphExecutor對(duì)象匪煌。

  • 在GraphExecutor對(duì)象中的GetFunction(...)會(huì)根據(jù)名稱"set_input"與"run"返回相應(yīng)的PackedFunc對(duì)象。

四俺附、總結(jié)

本文主要介紹了TVM模型編譯與運(yùn)行過程中的代碼流程。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末溪掀,一起剝皮案震驚了整個(gè)濱河市事镣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌揪胃,老刑警劉巖璃哟,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異喊递,居然都是意外死亡随闪,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門骚勘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铐伴,“玉大人,你說我怎么就攤上這事俏讹〉毖纾” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵泽疆,是天一觀的道長户矢。 經(jīng)常有香客問我,道長于微,這世上最難降的妖魔是什么逗嫡? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮株依,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘延窜。我一直安慰自己恋腕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布逆瑞。 她就那樣靜靜地躺著荠藤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪获高。 梳的紋絲不亂的頭發(fā)上哈肖,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音念秧,去河邊找鬼淤井。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的币狠。 我是一名探鬼主播游两,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼漩绵!你這毒婦竟也來了贱案?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤止吐,失蹤者是張志新(化名)和其女友劉穎宝踪,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體碍扔,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瘩燥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蕴忆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片颤芬。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖套鹅,靈堂內(nèi)的尸體忽然破棺而出站蝠,到底是詐尸還是另有隱情,我是刑警寧澤卓鹿,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布菱魔,位于F島的核電站,受9級(jí)特大地震影響吟孙,放射性物質(zhì)發(fā)生泄漏澜倦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一杰妓、第九天 我趴在偏房一處隱蔽的房頂上張望藻治。 院中可真熱鬧,春花似錦巷挥、人聲如沸桩卵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雏节。三九已至,卻和暖如春高职,著一層夾襖步出監(jiān)牢的瞬間钩乍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工怔锌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留寥粹,地道東北人变过。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像排作,于是被迫代替她去往敵國和親牵啦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容