TVM:

Hello TVM

TVM 是什麼?A compiler stack,graph level / operator level optimization,目的是(不一樣框架的)深度學習模型在不一樣硬件平臺上提升 performance (我要更快!)html

TVM, a compiler that takes a high-level specification of a deep learning program from existing frameworks and generates low-level optimized code for a diverse set of hardware back-ends.前端

compiler比較好理解。C編譯器將C代碼轉換爲彙編,再進一步處理成CPU能夠理解的機器碼。TVM的compiler是指將不一樣前端深度學習框架訓練的模型,轉換爲統一的中間語言表示。stack個人理解是,TVM還提供了後續處理方法,對IR進行優化(graph / operator level),並轉換爲目標硬件上的代碼邏輯(可能會進行benchmark,反覆進行上述優化),從而實現了端到端的深度學習模型部署。java

我剛剛接觸TVM,這篇主要介紹瞭如何編譯TVM,以及如何使用TVM加載mxnet模型,進行前向計算。Hello TVM!node

TVM概念圖

背景介紹

隨着深度學習逐漸從研究所的「伊甸園」迅速在工業界的鋪開,擺在你們面前的問題是如何將深度學習模型部署到目標硬件平臺上,可以多快好省地完成前向計算,從而提供更好的用戶體驗,同時爲老闆省錢,還能減小碳排放來造福子孫python

和單純作研究相比,在工業界咱們主要遇到了兩個問題:ios

  • 深度學習框架實在是太TMTM多了。caffe / mxnet / tensorflow / pytorch訓練出來的模型都彼此有不一樣的分發格式。若是你和我同樣,作過不一樣框架的TensorRT的部署,我想你會懂的。。。
  • GPU實在是太TMTM貴了。深度學習春風吹滿地,老黃股票真爭氣。另外一方面,一些嵌入式平臺沒有使用GPU的條件。同時一些人也開始在作FPGA/ASIC的深度學習加速卡。如何將深度學習模型部署適配到多樣的硬件平臺上?

爲了解決第一個問題,TVM內部實現了本身的IR,能夠將上面這些主流深度學習框架的模型轉換爲統一的內部表示,以便後續處理。若想要詳細瞭解,能夠看下NNVM這篇博客:NNVM Compiler: Open Compiler for AI Frameworks。這張圖應該可以說明NNVM在TVM中起到的做用。c++

NNVM在TVM中的做用

爲了解決第二個問題,TVM內部有多重機制來作優化。其中一個特色是,使用機器學習(結合專家知識)的方法,經過在目標硬件上跑大量trial,來得到該硬件上相關運算(例如卷積)的最優實現。這使得TVM可以作到快速爲新型硬件或新的op作優化。咱們知道,在GPU上咱們站在Nvidia內部專家的肩膀上,使用CUDA / CUDNN / CUBLAS編程。但相比於Conv / Pooling等Nvidia已經優化的很好了的op,咱們本身寫的op極可能效率不高。或者在新的硬件上,沒有相似CUDA的生態,如何對網絡進行調優?TVM這種基於機器學習的方法給出了一個可行的方案。咱們只需給定參數的搜索空間(少許的人類專家知識),就能夠將剩下的工做交給TVM。若是對此感興趣,能夠閱讀TVM中關於AutoTuner的介紹和tutorial:Auto-tuning a convolutional network for ARM CPUgit

編譯

個人環境爲Debian 8,CUDA 9。github

準備代碼

   

config文件

   

編輯config文件,打開CUDA / BLAS / cuBLAS / CUDNN的開關。注意下LLVM的開關。LLVM能夠從這個頁面LLVM Download下載,我以前就已經下載好,版本爲7.0。若是你像我同樣是Debian8,能夠使用for Ubuntu14.04的那個版本。因爲是已經編譯好的二進制包,下載以後解壓便可。算法

找到這一行,改爲

   

 

編譯

這裏有個坑,由於咱們使用了LLVM,最好使用LLVM中的clang。不然可能致使tvm生成的代碼沒法二次導入。見這個討論帖:_cc.create_shared error while run tune_simple_template

   

python包安裝

   

demo

使用tvm爲mxnet symbol計算圖生成CUDA代碼,並進行前向計算。

   

最後的話

我我的的觀點,TVM是一個頗有意思的項目。在深度學習模型的優化和部署上作了不少探索,在官方放出的benchmark上表現仍是不錯的。若是使用非GPU進行模型的部署,TVM值得一試。不過在GPU上,得益於Nvidia的CUDA生態,目前TensorRT仍然用起來更方便,綜合性能更好。若是你和我同樣,主要仍然在GPU上搞事情,能夠密切關注TVM的發展,並嘗試使用在本身的項目中,不過我以爲仍是優先考慮TensorRT。另外一方面,TVM的代碼實在是看不太懂啊。。。

想要更多

後續TVM的介紹,不知道啥時候有時間再寫。。。隨緣吧。。。

 

 


 

 

 

被瀏覽
101,159
 
 

12 個回答

等 

從去年nnvm推出以後,很是感謝在zhihu和 

 上有一些討論 如何評價陳天奇的模塊化深度學習系統NNVM? ,關於nnvm剩下的瓶頸。這個討論自己加上早期的nnvm編譯嘗試,讓我意識到了能夠支持快速調優底層op的重要性。在接下來的八個多月裏面咱們不斷迭代完成了TVM。

 

TVM嘗試從更高的抽象層次上總結深度學習op的手工優化經驗,用來使得用戶能夠快速地以自動或者半自動的方法探索高效的op實現空間。

TVM和已有的解決方案不一樣,以XLA做爲例子,TVM走了和目前的XLA比更加激進的技術路線,tvm能夠用來使得實現XLA須要的功能更加容易 :已有的解決方案自己基於高級圖表示的規則變換,能夠產生一些圖級別的組合op優化,如conv-bn fusion,可是依然要依賴於手寫規則來達到從圖的表示到代碼這一步。圖的op表示到代碼自己能夠選擇的東西太多,如何作線程,如何利用shared memory,而大部分沒有在圖語言裏面獲得刻畫,致使難以自動化。 這樣下去深度學習系統的瓶頸必然從op實現的複雜度變成了實現graph compiler中模式生成規則的複雜度。走這個方向須要很是大的工程團隊的支持,而咱們但願採用更少的人力達到一樣甚至更好的效果。

咱們採起了風險更大可是回報也更大的長遠技術路線。簡單地說,TVM經過把圖到op生成規則這一步進一步抽象化,把生成規則自己分紅各個操做原語,在須要的時候加以組合。基於tvm咱們能夠快速地組合出不一樣的schedule方案。

這個想法並不新穎,正如其它回答中提到的Halide,或者polyhedra method都是嘗試去作這件事情。想法雖然美好,可是自動代碼生成這條路線必需要生成代碼效率到達手寫的80%-90%效率以上,纔會有實際使用的價值。一旦到達了80%到90%的效率以上,經過fusion,layout的一些高級聯合優化就能夠彌補這一個gap來獲得比直接組合手寫代碼更好的效果。

可是這也正是這個問題最困難的地方,咱們須要能使得自動或者半自動生成的代碼達到手寫代碼的效果。在TVM以前,已有的解決方案都尚未解決這個問題。我知道的最好的GPU自動生成代碼大概能夠到Cublas的50%的運行效率,而大部分的已有方案只是針對單線程cpu有比較好的效果。

固然已有的解決方案有很多值得參考的地方。好比polyhedra method自己很是精闢地把程序優化的大部分問題總結爲針對整數集的分析Halide裏面的schedule和declaration分離的思想等。這些思想都很是強地影響了TVM的設計

這自己是一個頗有趣的科研問題,dmlc的的初衷就是去解決這樣新的問題,發佈新的解決方案。TVM在很大程度上解決了這個問題。要解決它,須要作到兩點:設計足夠大的schedule空間,使得它能夠囊括包括cpu和gpu在內能夠作到的手寫優化,設計足夠強大的搜索算法。以前的方法之因此沒有圖片,難點在於須要足夠大的空間。

全部的抽象老是有缺陷的,因此死抱一個固定的抽象確定不能解決全部的問題。可是能夠被寫出來的手工優化基本上也是能夠被抽象的。過去的幾個月咱們就是沿着這樣的思路,不斷地去總結手工優化的經驗加以抽象到TVM中。雖然咱們不敢保證TVM包含全部可能的手工優化,可是我基本上cover了我知識範圍裏面能夠涉及到的東西(使得TVM至少比我知道的多)。隨着TVM的演化,會有更多的這樣的手工優化經驗能夠被加入進來。這也真是須要HPC機器學習和編譯等各方面人才一塊兒協力的結果。

到目前爲止,咱們基本能夠肯定TVM目前提供的schedule空間在cpu上能夠作到90%,類似或者超過一些手寫優化庫效果的方案,在gpu上幾本能夠作到達到或者超過手寫cuda的方案,可是和手寫assembly在一些狀況還有80%的差距(主要來源於gpu的寄存器分配比較困難)。TVM自己也意識到的手寫優化的重要性,會在容許在各個級別混用手寫優化的代碼, 來彌補剩下這一平衡。

這是一個很是激動的前沿課題,基於這個項目自己還會有很多有趣的研究方向,咱們在不少地方已經能夠看到很是好的效果。因此咱們很是但願對於機器學習,hpc,編譯原理,硬件加速 有興趣的同窗一塊兒加入進來,一塊兒來推進這個項目。而由於咱們目前到達的效果自己,TVM已經能夠被使用於實際的應用場景中了。

最後有一些細節上面的東西,TVM自己的設計中是很是注重開發效率和可擴展性。TVM直接提供了很是好用的python和真機調試框架,能夠不依賴於上層框架直接基於python開發調試。這一點使得tvm在調試開發和效率迭代上面比起已有的方案有比較大的優點。將來咱們也會放出一些樣例教程,讓你們均可以開發高效的代碼

 

 

將來會有自動圖編譯以及直接在python端定義customop

 

最近一直在研究TVM,感受跟 xla,ngraph,DLVM比,tvm在張量計算的實現和優化這一塊作的更好,以前看論文感受TVM重點是支持多後端,可是今天你的回答感受又像是TVM重點在自動代碼生成這一塊,並且並無提出中間表示IR這一說,別的編譯器xla/dlvm都有IR的設計理念,那tvm有一套 graph或者底層張量計算的IR的設計麼?
 
等 

目前 TVM 放出的資料還較少,週日學習了下代碼,和你們交流分享,有疏漏煩請回復指出。

TVM 的應用場景,是跟 TensorFlow XLA 對標,提供將模型輸出到不一樣設備 native code 的能力。這裏面有幾個能夠對標的組件:

  • TOPI (TVM Operator Inventory) 大約對應 XLA HLO, 描述在 DL 領域會用到的高層次 Operator 如 matmul, conv2d 等。這一層次能夠作 CSE、Fusion 等優化。
  • Schedule + HalideIR + TVM IR 無對應
  • 代碼輸出 TVM 使用 LLVM IR 和 Source Code, 對應 XLA 使用 LLVM IR.

這裏面,TVM 的切入點是在 High Level 到 Low Level 中間,插入了 Schedule 層,大概流程是 NNVM -> TVM/TOPI -> TVM/Schedule -> TVM/HalideIR -> TVM IR -> LLVM IR 或 Source Code。中間 TVM Schedule 的主要思想來自於 Halide. 這裏要簡單介紹一下 Halide 這個爲圖像處理設計的語言。Halide 其特色是計算描述(algorithm)和計算過程(schedule)分離()。這麼作是由於計算機體系結構的設計(緩存,SIMD 等),直接裸寫算法不能得到最高性能(一個例子是三重循環裸寫矩陣乘會很慢)。所以不一樣的體系結構,對一個算法的計算過程也就不一樣。分離算法定義和計算過程,則方便爲不一樣的體系結構制定不一樣的 schedule, 進一步能夠探索 schedule 的自動生成(Automatically Scheduling Halide Image Processing Pipelines)。更詳細的介紹建議去 Halide 官網 Halide 學習。

 

當初看到 Halide 的時候,就在想這個想法在 DL 領域必定會有用,現在終於被 DMLC 推進進入了人們的視線。我對這個事情的見解是:

  1. Halide 能夠比較快的實現一個性能還不錯的 kernel,開發效率很高,換不一樣 schedule 測試方便。對比傳統 kernel 實現通常是手寫 C/C++ 或者彙編代碼,開發效率較低。但任何抽象都不是完美的,有足夠人力的狀況下,傳統寫法必定能夠得到不低於 Halide 的效率。
  2. Halide 提供了 auto-tune 的可能,但目前也只是在學術界研究,離工業級生產還遠。所以可預見的將來,咱們仍是要爲不一樣的 target 手寫 schedule 的。

根據 

 介紹,TVM 相對 Halide 作的比較多的工做,主要的是去解決 schedule 空間包含手寫優化的問題。具體內容移步 crowowrk 的回答

 

 

TVM 的另外一個目的是,但願經過 TOPI 這個 Operator 庫,爲全部兼容 dlpack 的深度學習框架提供 kernel 庫,這個目標是十分歡迎的,具體效果還有待觀察。

反過來看 TensorFlow 的 XLA,目前 XLA 還在快速開發中,有幾點能夠注意:

  1. XLA 並不反對獨立出來給其餘框架用 XLA standalone
  2. XLA 歡迎嘗試各類 idea,目前有人在 Incorporate Polyhedral Compilation
  3. XLA 目前不少 kernel 實現是基於 Eigen 的。某種程度上,Eigen 這種數學庫也是 TOPI 的對標。

 

總的來講,TVM 目標是很好的,很是支持。Soumith (PyTorch 主要做者)也在積極參與 TVM 項目並表示在接下來的幾個月內會有更多關於 TVM/PyTorch 的消息 Twitter 。

edit: 跟做者交流更新了若干技術細節。

 等 

最近陣容有點強大。

 

這週四咱們請了天奇來將門作線上直播,給你們親自講講TVM。

 

天奇的直播首秀,就在本週四(16號)下午1點,將門創投鬥魚直播間!

 

歡迎你們呼朋引伴來給天奇打call!!

 

詳情>>線上 | TVM發明人陳天奇: TVM-深度學習全棧自動優化和軟硬件協同設計

最近在考慮將深度學習移植到移動端, 面對不少問題: 

  • ios 11有coreml, ios10用metal, 更低版本須要手寫低版本metal代碼
  • neon指令集優化
  • 安卓gpu
  • caffe,tensorflow,darknet等一堆框架,移植不便,並且沒法一一優化.

瞌睡送枕頭, 感受tvm就是答案. 

github上關注了tianqi, 一直納悶最近半年爲啥沒有提交代碼, 難道上課太忙?

直到昨天...

忽然都亮起來了.

吐槽一句, mxnet號稱是輕量級框架, 各類宏,lambda看的懷疑人生,nnvm竟然還能把torch弄過來用Orz. 後來看了caffe, 不少功能都用第三方庫, 主體代碼很清晰簡單啊, 這纔是輕量啊...

利益相關: dmlc腦殘粉, tianqi腦殘粉

估計Google最近應該也會發一個東西,MXNet和TensorFlow競爭好激烈。。。

你們還記得找不到工做的bhuztez麼

他在去年在一位七歲小朋友的指導下預言,2017年出現的下一代深度學習框架後端會利用Polyhedral model作fusion,減小GPU內存帶寬壓力,提高運行速度。被某人下結論說「真心不會.. 合併帶來的內存節省只是一次elementwise op的代價,比起卷積開銷真是一個毛毛」

而如今的廣告

「如今咱們看到了 TVM 構建了由循環轉換工具好比 loopy、多面體分析啓發的圖優化」

「咱們經過自動融合運算符並使 TVM 生成融合的內核,在圖形節點之間和之中應用優化」

bhuztez不如趕忙改行,事實證實他那點破爛水平,連名校博士頭銜都沒有,真心不適合寫程序 ,我建議他仍是去賣煎餅果子吧 :)

 

 

 


 

 

 

如何評價陳天奇的模塊化深度學習系統NNVM?

介紹文章:MXNet專欄 | 陳天奇:NNVM打造模塊化深度學習系統
項目地址:GitHub - dmlc/nnvm: Intermediate Computational Graph Representation for Deep Learning Systems

NNVM是否會成爲深度學習時代的彙編語言,成爲溝通底層計算設備(GPU、FPGA)與高層的計算圖描述語言(Tensorflow、MXNet)的通用橋樑?
被瀏覽
51,424
 
 

7 個回答

等 

北京時間 10 月 13 日 12:00 更新:
加個 Disclaimer: 本文僅表明我的觀點,與僱主無關。

北京時間 10 月 4 日 1:40 更新:
看到做者 

 的 回答,而且在評論中進行了簡單交流。個人見解和做者的想法,都是認同 graph 定義和優化這一層的,區別是我認爲這一層放在框架內部更方便開發,而 NNVM 想把這一層拿出來你們一塊兒作大作強避免重複勞動。這個想法我是很是支持的,但最終是否好用仍是要看工程的發展和理論總結,尤爲是在當前 NNVM 的實現還很是單薄的狀況下。
我以前的回答,主要是在把 NNVM 跟 TF 內部的 graph 這層比對,並非爲了分出高下,而只是在作技術上的比對,並表達個人一些想法。但願你們不要有門派之爭,理性討論,共同促使技術進步。 

 

=== 10 月 3 日答案原文以下 ===
tl;dr NNVM 的出現不在於技術上有多大突破(該有的 TF 都有),而在於意欲打造一個公共接口(雖然我並不認同)。當下推出的 TinyFlow, 也有一點集合社區力量對抗 Google 的 TensorFlow 的意思。無論怎麼說,DL Framework 社區活躍,終歸是一件好事,做爲從業者很是感謝!

首先建議想作技術分析的同窗,都先看看 TensorFlow 的代碼,雖然量很大,但核心都在core/framework 和 common_runtimecore/distributed_runtime 幾個目錄下面,從 Session 一路分析進去,並不難懂。

nnvm 從 github 上看,是爲了做爲模塊化 DL 系統中的計算圖的一環。
NNVM offers one such part, it provides a generic way to do computation graph optimization such as memory reduction, device allocation and more while being agnostic to the operator interface definition and how operators are executed. NNVM is inspired by LLVM, aiming to be a high level intermediate representation library for neural nets and computation graphs generation and optimizations.

這些部分,在 TensorFlow 裏面都有相對成熟的實現。
先說圖表示,在 TensorFlow 裏面有兩種圖,一種是用於接口的,基於 protobuf 表示的圖 tensorflow/graph.proto,稱之爲 GraphDef。另外一種是 C++ 內部運行時用的圖表示 tensorflow/graph.h,稱之爲 Graph. 而 Operator 的定義,TF 是經過一個在 C++ 裏面實現的 DSL 作的 tensorflow/op.h 使用方法例如 tensorflow/math_ops.cc,這個在 NNVM 裏面也採用了相似的形式。

以後作圖的優化,在 C++ 層面有 tensorflow/graph_optimizer.h. 基於這個接口,目前也作了若干實現 tensorflow/graph_optimizer.cc 如常數摺疊,公共表達式消除等。除此以外,在 Python 層面也有  graph_editor 用來作圖的編輯。好比 Sublinear Memory 理論上用 GraphEditor 是能夠作到的。

TF 的 Operator 和 Kernel 也是分開的,相同的 Operator 能夠有 CPU/CUDA 等多種實現,OpenCL 也在進行中。往 TF 裏面加 Operator 並不複雜 .

因此先潑一瓢冷水:我粗略的掃了一下 NNVM 的代碼,能夠說目前 NNVM 的目標,在 TF 內部都有實現而且都有比較好的抽象隔離。從新造輪子,政治意義大於技術意義。
轉載做者 陳天奇 的微博 關於今天深度學習系統爭論。目前的壁壘並不是... 來自陳天奇怪:
關於今天深度學習系統爭論。目前的壁壘並不是使用哪個,而是系統內部高度耦合,使得改進或者從頭fork打造系統的代價變高。經過模塊化,去中心化來解決這些問題,防止壟斷。 當你們均可以經過組裝組件幾天從頭打造MX, TF或者相似系統的時候。這些爭論就不復存在了。

最近推出的 TinyFlow 號稱是 2k 行的 TensorFlow,但其實看代碼會發現,作到當面這個層面,即便徹底重寫,代碼成本也不算高。TinyFlow 目前(2016.10.3)的本質是一個 Python DSL 到 Lua 代碼的轉換器。而 TensorFlow 自己的結構並不複雜,難點在於無窮多 Operator 的實現,和當初分佈式架構的設計。這兩個實現出來,本質上都是工做量問題,這也是 TF 的 codebase 如此龐大的緣由。

NNVM 目前(2016.10.3)自身也不包括 Operator 的定義,這會致使使用 NNVM 的不一樣框架本質上是沒法互換的。而定義 Operator 這個工做量比較大,甚至不必定能完成(好比不一樣 Framework 對 padding 的定義就不太同樣),不知道 NNVM 是否有意願往這個方向發展。

目前 DL 的領域還在高速發展,新的網絡結構(好比 ResNet, GAN)、計算節點(各類神奇的 Operator)、計算方法(好比 lowbit, sublinear memory)、計算設備(好比 TPU,寒武紀)都在不斷涌現。分佈式架構也在不斷演進。在這個時間點,我認爲 monolithic 的框架重構相對方便,會有更加旺盛的生命力。而 NNVM 的理想,恐怕跟現實仍是有必定差距的。目前更有價值的,我以爲並不在圖表示層,而是各類 Operator 的 kernels. 每一個設備的 kernel 都須要專業人員定製,工做量大,難度高。cudnn 解決了 CUDA 設備上的大部分問題,但仍然有不少 Operator 須要本身實現。lowbit 目前也並無特別可用的實現。若是能有一個統一的庫,定義每一個 Operator 在各類設備上的最優運行代碼,應該對社區更有幫助。而上層的網絡定義,和具體每一個圖的運行調度方式(好比 MXNet 的 Dependency Engine,TensorFlow 的分佈式框架和 rendezvous 設計),這些代碼量不大,但更容易體現出差別化的部分,我想仍是留待每一個框架本身解決吧。

我的愚見,請各位參考。雖然我並不認同 NNVM 的目標,但依然對陳天奇先生對社區的貢獻很是欽佩。各位如想評論,請至少大略瞭解 NNVM,TensorFlow 和 MXNet 的內部實現架構,以節省你們時間。
 

15 條評論

  • KaiJ
    KaiJ2 年前
    贊成。另外不知道「從頭fork打造系統」的需求是哪兒來的,並且有了nnvm也並不容易從頭打造系統,由於最麻煩的仍是opr。。並且跟llvm的情形不一樣,PL的前端很是豐富並且差別巨大,而中間表示用上三地址碼能夠用不少現成的優化理論。 但deep learning的前端基本就是graph的描述,並無太多接口之外的差別。而在不考慮opr具體特性狀況下的中間表示能帶來的優化有限,可能最有用的就是內存分配;像const folding目前看來在nnvm的框架裏並很差作,由於須要知道opr的具體操做,須要定義好tensor結構,管理一些內存分配,這樣nnvm就要膨脹成大半個dl框架了。如答主所述,真正加速還得看後面的kernel和硬件,這塊門檻最高,價值最大,但如今社區裏能看到的成果也是最少的。
  • 王佳明
    王佳明回覆KaiJ2 年前
    贊成,dnn的優化須要各類kernal代碼,如你所說,門檻最高,價值最大,目前都是cudnn包辦,社區就一個nervana,成立兩年就賣了幾億刀。在圖結構上跳舞是捨本逐末。
  • 劉知遠
    劉知遠2 年前
    文筆很好呀!
  • 渡河
    渡河2 年前
    膜拜大大!
  • 某一個吃貨
    某一個吃貨2 年前
    其實看最新mxnet的issue,整個mxnet將會在nnvm上進行重構。我以爲良好的系統結構抽象和徹底的性能不可兼得。但並非說選擇優秀的抽象就不如優秀的性能。整個mxnet在幾位大牛(感受就五我的左右)的貢獻下(和TF幾十我的的團隊相比),開發效率很是高,這也和優秀的抽象和思考是分不開的。
  • 某一個吃貨
    某一個吃貨2 年前
    其實我以爲作這個的你們都明白框架之間的差別其實都並不大,核心就是分佈式和Operator的支持程度。Google有着最優秀的研究和工程人才天然有優點。但我以爲nnvm志不在此,並非爲了和TF一較高下,而是一個開源社區下降入門contribution門檻的階梯。其實當有一天nnvm(dmlc)社區成長的和keras同樣以後,優秀架構的潛力就會慢慢顯現,以前的那些問題也都不會是問題。
  • 王健飛
    王健飛 (做者) 回覆某一個吃貨2 年前
    在 TF 已經開源近一年的時間點上,正如我回答所說,NNVM 在架構上目前並無優點,更多的是政治意義。若是您對這方面技術有興趣,歡迎您去閱讀 TF,Caffe,MXNet 的代碼,再作評論。
  • 某一個吃貨
    某一個吃貨2 年前
    我以爲就像當年推出Java的時候,只是爲了解決一個問題(跨平臺)而不是爲了解決全部的問題(性能啊語言特性啊),確定不會想到如今的用途。畢竟有一個重要的人生經驗【一我的的命運啊,固然要靠自我奮鬥,可是也要考慮到歷史的行程】
  • 謝流遠
    謝流遠2 年前
    tf分佈式效率那麼差,架構設計並不能算優勢吧
  • 謝流遠
    謝流遠2 年前
    kernel其實經常使用的性能瓶頸10個都不到,剩下的長尾優化意義不大並且永遠不可能寫完。若是你作的是novel research,那你用的op必然不可能有別人給你寫好。
  • dzhwinter
    dzhwinter2 年前
    反對一下,TF的抽象作的太多了,分佈式設計易用性並很差,小operator組合致使效率差如今尚未解決。認同NNVM講的三個story。
  • 劉弈
    劉弈2 年前
    飛機好厲害~雖然我看不懂 0.0
  • 王雷
    王雷2 年前
    贊同樓上的反對,TF的抽象過多,設計質量和代碼質量並不理想
  • 時間的朋友
    時間的朋友1 年前

    一個在科研界混的人以爲NNVM更像一個科研項目,設計追求各類靈活,這在很大程度上確實可以促進社區的發展。但重口難調啊,設計無比靈活的東西針對特定需求,性能卻不必定牛逼,在工程應用上各家有各家的獨特需求和硬件條件,我的以爲更須要針對需求的定製。

  • zhuao
    zhuao8 個月前

    我是作系統多媒體框架的,對DL的東西不瞭解,看了陳天奇的回答,以爲蠻有感觸的。

    Android上的多媒體框架就是一個渣。stagefright的player連google本身的應用都不使用;java層從新封裝的exoplayer也並無爲廣大第三方應用所接受。由於他的思路就是面向特定的應用來構建實現,沒有留給第三方開發者真正的定製化開發空間。好比你想在視頻播放過程當中加一個額外的後處理實現圖像加強,這不可以經過添加一個新的組件來簡單的解決。從陳天奇的回覆來看,TF也是相似的解決方案 -- 你想添加一個額外的處理環節,很難。而這是在作框架設計的時候須要慎重考慮的東西。

     

    而參考其餘的多媒體框架,像Linux的GStreamer,Windows的DShow;都是能夠方便地作到上面的事情。也就是他們是真的面向pipeline的graph設計:每一個模塊(算子,plugin)具備統一的直觀的接口(而不是具象的每一個特定屬性);不一樣的模塊(算子)能夠自動地完成鏈接和交互數據。內存的管理和數據的流動在框架的約束下交由模塊自動完成。這樣在搭建的新的場景的時候,就是壘積木,足夠簡單;在pipeline中添加和去除處理環節也能夠經過幾行代碼來完成。

    至於「相對乾淨的Op應該去推進成爲一個獨立的模塊」,這個能夠參考多媒體領域的ffmpeg。他就是focuse在具體的視頻編解碼和處理功能,而獨立於不一樣的多媒體框架(能夠充分被Gstreamer,VLC,甚至stagefright所使用)

     

    這種框架設計的思路,隨着場景和工程的演進,能夠表現出更多的優點。

 等 

以前討論事後更加意識到了@王健飛 所說的更好地支持更多平臺的op調優的重要性。昨天咱們發佈了dmlc/tvm 來解決這部分問題。 

-------

在幾個月以後給了幾個關於NNVM的報告,也思考了它和已有系統的差異。追加一下這一頁slide,是我對於在抽象成面上面各個系統差異的理解。

 

原回答

-------
我是NNVM的做者。

 

總結一下,技術上自己的NNVM和現有的東西的差異是最小模塊化和去中心化,下降深度學習系統優化門檻。除了爲了解決現有問題,更可能是爲了將來考慮。

 

關因而否重複造輪子的問題,圖表示和優化自己在MXNet就已經存在,樓上也提到TF也有對應的抽象,爲何咱們須要從新寫一遍呢,基本上也就是以上兩點緣由。

 

基本上現有的深度學習系統分紅兩塊,1) 基本的operator的實現, 2)支撐其中的系統調度,優化,解釋或者編譯架構。

 

在工程難點上,operator須要堆代碼,可是對於工程架構的難度上面而言相對較低(也就是說能夠寫的人比較多一些),可是須要堆比較大量的代碼。而剩下的系統優化部分,內存,執行調度和分佈式優化對於總體系統而言的難度相對高一些。Operator的集合問題雖然是一個問題,看已經有的成熟框架不管是Torch, Theano或者MXNet的operator完整程度基本上能夠知足於大部分應用,也就是說這部分暫時屬於已經解決或者能夠經過堆積工程力量容易解決的問題。樓上說的最小化通用的 Op接口很重要,和NNVM咱們考慮的方向垂直。我以爲相對乾淨的Op應該去推進成爲一個獨立的模塊,而Op實現自己其實沒有必要和框架耦合很深(雖然遺憾的是目前的設計暫時沒有作到這一點)。

 

NNVM但願解決的是垂直於operator實現的問題。有趣的是其實TF在這一暫時沒有花特別多的力氣,因此會讓人以爲operator是大頭。其實這裏有不少有趣的東西,在執行,調度和編譯優化上面。編程模型和一個圖自己的執行模式和硬件也會有更多的差別。

 

直接討論一下設計,目前TF採起了單一的動態執行模式,使得自己執行特別依賴於動態內存分配以及threading。而這並不是是大部分場景下的最優方案。大部分場景下基於對於有限的圖進行的靜態分配,能夠更大的緩解這個問題,實際狀況如MX自己的內存損耗能夠作的更好。爲何目前TF不會出現多種執行模式呢,是由於TF自己Op的接口仍是過於通常地針對的動態,而若是要更好的優化須要更細化的Op接口(分開內存分配和計算的部分),這就考慮到一個Op甚至可能有多種接口的可能性。

 

NNVM自己的圖的設計參考了TF,MX和caffe2的圖部分。樓上的評論基本上提到了幾個很是重要的概念,即系統優化和Op具體的性息相關。可是和PL不一樣,咱們不能直接簡單的抽象出有限個操做來表示整個程序。這個時候彷佛框架和Op會有比較強的關聯性,致使比較大的耦合。可是也並不是如此,由於每個優化自己其實只依賴於Op的部分屬性。好比有同窗提到的常數摺疊,其實須要知道的是一個Op是不是常數,以及如何去展開常數兩個函數。NNVM自己的作法是容許註冊這兩個額外屬性來容許常數摺疊優化。可是當不須要這個優化的時候,能夠直接去掉這一部分。使得深度學習的優化能夠插拔。如今看起來可能有些overkill,可是咱們相信將來深度學習系統在這方面會有很大的發展,容許不一樣的優化來自於不一樣羣體和研究人員是咱們更加喜歡的方式。

 

基於以上緣由,NNVM容許給每一個op註冊任意的信息。而且能夠使得屬性和註冊和op的實現分開。這相對於TF的op接口而言是一個進步的地方。TF內部的全部op屬性是須要提早數據結構指定的,也就是說,目前TF能夠註冊shape inference, op的輸入參數的個數,可是沒法註冊好比咱們須要的新的細化Op接口,或者有些人關心的代碼生成函數。若是須要加入這些特性,必需要修改Op的接口。這意味着全部的開發須要在一箇中心,而且只能保留你們關心的東西。若是forkA有feature1, forkB有feature2的狀況,forkB想要拿到 feature1就會比較不方便。由於NNVM容許不修改Op接口註冊任意信息,相對解決了這個問題。

 

固然模塊化和去中心化並不是對於全部人都重要,就是見仁見智把。

 

將來的深度學習系統會有更多系統的問題,使得優化和執行更加多樣化。咱們不可以期待全部的優化都來自於一個團隊,或者只應用於一個框架。更多的優化看起來會帶來更多的耦合,可是也並不是如此。

發佈TinyFlow緣由很簡單。大部分人並無意識到其實目前深度學習的「系統」部分能夠經過簡單抽象獲得。TinyFlow做爲一個教程性質的項目,能夠用比較短的代碼展現目前有的大部分優化概念,而且把Op的部分代理給Torch(由於Op自己雖然重要,可是並不做爲架構一部分)。若是能夠有更多的同窗來關注深度學習系統優化,基本這個項目的目的就達到了。

 

值得認可的是,NNVM目前只是走出了第一步,只是包含了MXNet原有的一些優化,暫時內容很少,咱們會繼續帶來更多好玩的東西。 咱們也會繼續堅持模塊化和去中心化的思想,使得咱們新的成果能夠更好的用在各個平臺裏面

12 條評論

  • 固然模塊化和去中心化並不是對於全部人都重要,就是見仁見智吧
  • 強黃
    強黃2 年前
    爲大家感到驕傲
  • 王健飛
    王健飛2 年前
    自定義 attributes 的部分不太理解。爲了使用 nnvm 的不一樣框架可以交互,必然仍是要規定一組 common attributes 的,這些 common attributes 可能跟其餘框架內置固定的 attributes 並沒有二致。
    若是要某個框架要增長新的 attributes, 在不求通用性的前提下,能夠不改 NNVM 只在本身先後端實現,但這跟在一個 monolithic 框架中增長一個新的 attributes, 彷佛代碼量不相上下?

    以及,支持自定義 attributes 只要支持一個 map 便可,我沒有確認目前各個框架的實現,但即便目前不是 map, 在 Operator 定義中增長一個 map 支持任意 attributes 也不是難事吧?
  • 陳天奇
    陳天奇 (做者) 回覆王健飛2 年前
    沒錯,任意attr實現代碼量很少。通用性,可拆除和去中心化,是咱們關心的東西。這裏的意義在於基於NNVM的attr優化能夠複用於各個先後端。若是全部的東西都是一個團隊在一個框架裏面實現,一樣代碼量沒有多大差異。

    只是在考慮通用性的時候會多一個心眼,有時候代碼會比hack的乾淨一些。這是在從MXNet轉化到NNVM的一個體會。

    雖然複製老是可能的,你們都會作,可是仍是但願能夠有共同的抽象。就好象op和模型,也是同樣的道理。

    最後,其實咱們就是但願用最小的代碼完成最多的事情,而不是overdesign一個東西。雖然不必定造成技術壁壘,可是有利於增長新的好玩的東西進行高效開發
  • 王健飛
    王健飛回覆陳天奇 (做者) 2 年前
    瞭解了。咱們並無本質的分歧,都認同 NNVM 這一層的意義。只是我以爲這一層目前放到框架內部作開發起來比較快,而 NNVM 以爲這一層拿出來複用會更有好處。本質上是作工程的口味問題,而不是技術的高下。另一點是,我我的以爲目前 DL 系統開發的難點並不在 Graph 層,不過這個見仁見智,就很少討論了。

    在不打算定義通用 Op 的狀況下,Attr 的設計應該是 NNVM 的關鍵,這個設計是對各類 Op 的本質的歸納,不知道我理解是否正確。這一點上,但願有更加理論的成果出現。加油!
  • 陳天奇
    陳天奇 (做者) 2 年前
    恩,個人理解是DL自己已經很難用枚舉instruction set的方式來統一中間表示了。因此經過通用的Attr來統一。

    如何根據各個優化的需求抽象出合適的Attr以及對應的優化的確是將來的關鍵。使用NNVM的設計基本上就是強迫咱們在將來系統演化中有更多這樣的思考。

    如今DL系統開發還有不少不肯定因素,相信不論你們角度如何,總會有更多好玩的東西出來的
  • lv-yafei
    lv-yafei2 年前
     在MxNet中,對於變長lstm和attention等網絡,圖的構建和銷燬開銷仍是比較大的,雖然nnvm優化了建圖的時間,可是仍是沒法作到能夠被忽略不計,nnvm之後是否會提供相似於tensorflow的動態流圖的構建。對於NLP等任務,動態流圖可能沒法作到顯存最優,可是卻能夠避免反覆構建圖的開銷。
  • 陳天奇
    陳天奇 (做者) 回覆lv-yafei2 年前
    將來考慮子圖結構組合吧。這樣子圖能夠避免反覆拷貝構建
  • 齊顯東
    齊顯東2 年前
    如今出來了 Weld,能夠對比一下嗎?是相似的框架嗎?
  • 餘風雲
    餘風雲1 年前

    還覺得是寒武紀

  • ForAnyThing
    ForAnyThing1 年前
    人和人差距真大,如今留言還這麼少,等你真的全民皆知的時候,至少我早點膜拜了大神。

NNVM Compiler: Open Compiler for AI Frameworks

盜一張文中圖:

給我一種感受,nnvm牽起了pytorch,cntk,caffe2,caffe,keras(?)的小手,開始幹xla。。(keras怎麼哪都有你。。)

7 條評論

    • charging
      charging1 年前
      keras蠻好用的
    • 羅若天
      羅若天 (做者) 回覆charging1 年前

      我相信的。

    • SLee
      SLee回覆羅若天 (做者) 1 年前
      我是你的忠實粉絲。關注你好久了!看你的博客論文代碼!life is shot us pytorch
  • bingo
    bingo1 年前
    不是中文圖嗎
  • 羅若天
    羅若天 (做者) 回覆bingo1 年前
    上文中的圖
  • sean zhuh
    sean zhuh1 年前
    感受tf好高傲,自成一家不和咱們玩😂
就就像xen理論性能等比kvm優秀,可是redhat準備全力推kvm的時候,趨勢開始轉移到kvm,因此,長期的運營支持,精確高質量的實現都是一個平臺的核心競爭力,並且DL平臺對交叉專業領域的需求,加速硬件,系統架構,通訊架構,互聯基礎網絡,分佈式並行架構,等等都也很是重要。
例如一個高速網絡架構下,一個關鍵內存未對齊的操做可能損失可觀的總體性能,一個忽視的鎖的設計也可能損失可觀的性能,一個tcp超時參數的不合理可能損失樂觀的性能,甚至一個硬件插槽的不合理也可能損失可觀總體的性能,一個不合理的通訊算法架構等等。
一般,系統領域fine-grained的優化實現相當重要,這須要對平臺的長期耕耘,也須要決策層面長期的支持,絕逼幾個單純的架構能解決的問題。
不多見到從distributed level將系統設計,大都仍是仍是based single node層面講靈活性,期待有更多關於總體system層面討論架構。

最近有點勤奮。

 

在沐哥醉心與寫書和帶娃的日子裏,爲了讓你們不忘了咱們。

 

這週四咱們請了天奇來將門作線上直播,給你們親自講講TVM。

 

天奇的直播首秀,就在本週四(16號)下午1點,將門創投鬥魚直播間!

 

歡迎你們呼朋引伴來給天奇打call!!

 

詳情>>線上 | TVM發明人陳天奇: TVM-深度學習全棧自動優化和軟硬件協同設計

NNVM Compiler是由mxnet的做者們提出的一個神經網絡的一箇中間表示。它包括兩部分:NNVM和TVM。NNVM主要作的是graph層面的表示,它經過表示節點和節點之間的鏈接關係,把Operator鏈接成一個computation graph,再經過TVM來優化每個節點,來生成最終可執行的代碼。

對於計算圖級別優化,其實NNVM作了一些,可是他並無作到極致,還有不少咱們認爲可優化的地方,它其實裏面並無提供。固然NNVM可能只是爲了創建一個這樣的平臺,讓你們去貢獻代碼,作這樣一個開源社區的概念。固然就是說若是要追求極致性能的話,有時候仍是須要關注這樣的一個優化的手段。

 

 

原文有一些有效的優化手段介紹:

Momenta:Paper Reading | 讓深度學習更高效運行的兩個視角​zhuanlan.zhihu.com圖標

 

NNVM的想法是,我來作DL框架的優化,別人來豐富具體的Operator
我不清楚做者們是否想考慮過相反的情形,即對DL來講,有沒有可能Operator是核心,框架是輔助?
從做者的回覆來看,是有些看不上Op開發的,都打算代理給Torch了

 

 

 


 

 

 

如何學習TVM的代碼?

對陳天奇團隊的開源深度學習編譯器TVM很感興趣,特別是看到18年發的論文中提到的在FPGA上的部署。對於基礎知識薄弱(如體系架構編譯等方面)的學生,應…
被瀏覽
18,089
 
 

你能夠邀請下面用戶,快速得到回答

 

委託劉看山邀請

開啓後爲你智能邀請潛在的回答者
[object Object]
回答過類似問題
[object Object]
最近回答過該領域問題
[object Object]
在「機器學習」話題下有 7 個回答
[object Object]
在「編譯器」話題下得到過 101 個贊

2 個回答

等 

或許和不少人不一樣,以個人經驗來看,以爲理解TVM,或者推理框架必定要從前端開始。即你從一個Tensorflow模型 / MXNet模型等,是如何轉爲NNVM的,而後再應該是後續的圖優化,以及後續的TVM Tensor,LLVM代碼生成等東西。

 

爲何我會這麼強調從前端開始呢?由於不理解前端模型,就很難理解後續TVM爲何是這樣,並且出了錯之後很難知道究竟是什麼緣由,好比不少時候找了半天,其實只是你忘記了模型輸入圖片的預處理,卻誤認爲是後續卷積的調度優化作的有問題,因此我強烈建議先從一個模型前端開始,在tvm/nnvm/frontend裏面選取一個前端。而選取前端開始不該該僅僅是看,Bug / 需求驅動永遠是最好學習源代碼的方式,建議從一個固化好的模型開始,而後補足NNVM算子,好比Mobilenet / Resnet50等,這裏也是讓你熟悉工具,熟悉NNVM的開始,可能會遇到不少問題,可是一個一個克服會收穫不少,這裏面推薦一個看模型的好工具:  我也是看蘋果公司一我的用了之後發現的,確實是好東西。

 

接下來你應該首先理解TOPI,這是架設在NNVM與TVM之間的東西(首先忽略圖優化,你後面再去看),由於你須要理解NNVM Symbol (其它模型在轉爲NNVM前端表示時會以Symbol形式的Api表示) 如何與TVM之間是如何鏈接起來的,在這裏面你會有點迷糊,由於TVM是C++和Python混合的工程,這裏面你須要在這二者跳來跳去,可是你這一步你最重要的是抓住兩個核心: FTVMCompute (@reg.register_compute) / @reg.register_schedule,這一個你須要分別在nnvm/top裏面的C++ / Python去找,top裏面會告訴你是如何從NNVM進入topi的。

 

這一步完成之後,你則須要進入topi裏面的任意一個後端Target去看,我暫時推薦x86後端,由於這一個後端尚未被AutoTVM改造。對於你來講,理解起來更容易。在這裏你會遇到topi/nn裏面的@tvm.target.generic_func到相似具體@generic.schedule_conv2d_nchw.register(["cpu"])的改變,這是TVM的核心所在,對於卷積這樣的數據負載處理,爲了優化而沿用Halide的思想: 計算與調度分離。爲了理解這個,你最好參考一下這個文檔: 

 

到這一步理解好之後,後續的TVM底層API大部分狀況下你都不須要去動,包括後續的LLVM自動生成,優化等你也大部分不須要去動,由於相似CNN這樣的網絡,大部分你要作的工做就是在調度上,如何減小Cache Miss ,如何更好的讓數據Locality是更關鍵的地方。

 

到這一步之後,你能夠再回過頭去理解圖優化的部分,如Operator Fusion / FoldScaleAxis等,以及包括TVM目前最核心最不同凡響的地方: AutoTVM(),這是TVM去擊敗NCNN等用手寫彙編的推理框架的關鍵一環,用機器學習去解決機器學習的問題,讓你從調度參數的設置中解放出來,而專心寫調度算法。這裏面目前ARM CPU的調度算法並不是是最優的,可是從測試來看,至少在測試中使用硬件和環境來看,已經超過能找到的推理框架。後續我將撰寫一篇文章到TVM社區,將我在ARM CPU的工做寫出來,這將改善目前ARM CPU的官方調度版本,這將在Mobilenet等模型中有很好的提高,敬請關注!

 

TVM是很好的一個項目,這種基於編譯優化思想的深度學習推理框架正是我贊同的,雖然還有不少工做須要作,可是我認爲它已經走在一個很好的方向上了。

19 條評論

  • Rand Xie
    Rand Xie10 個月前
    感謝藍色大大.
    • 喬楓惜
      喬楓惜10 個月前
      以前也看到了阿里發的使用TVM優化batch matmul的blog,請問後面您那邊是會有大規模的部署優化計劃嗎?
    • 藍色
      藍色 (做者) 回覆喬楓惜10 個月前
      他們是另一個團隊,咱們目前仍是更強調在嵌入式設備上作端上推理的性能
    • 喬楓惜
      喬楓惜回覆藍色 (做者) 10 個月前
      很是感謝,很期待您的文章,但願發佈的時候能在知乎上也宣傳一下讓咱們知曉。
    • WhySmalltalk
      WhySmalltalk10 個月前

      至少在測試中使用硬件和環境來看,已經超過能找到的推理框架。。謙虛點。。。

    • 藍色
      藍色 (做者) 回覆WhySmalltalk10 個月前
      很謙虛了,至少在咱們的測試環境是如此。
    • 藍色
      藍色 (做者) 回覆WhySmalltalk10 個月前
      看你公司是ARM吧,實話,ARM-NN很弱。
  • cyoung
    cyoung9 個月前
    藍大,這種混合工程用什麼工具看源代碼比較方便?好比用clion,除了c++代碼,其餘都是文本形式展現,很差看
  • 藍色
    藍色 (做者) 回覆cyoung9 個月前

    CLion能夠的,裝一個Python插件就能夠了。我用的是QtCreator + PyCharm

     

  • 輕舟
    輕舟6 個月前

    請教藍大,在看x86後端,遇到一個警告:
    WARNING:autotvm:Cannot find config for target=llvm, workload=('dense', (1, 512, 'float32'), (1000, 512, 'float32'), (1000, 'float32')). A fallback configuration is used, which may bring great performance regression.
    問題出在哪裏?應該怎麼去調優?謝謝指教!

  • 藍色
    藍色 (做者) 回覆輕舟6 個月前
    這是Auto Tuning的警告,你能夠本身Tuning, 你這裏是dense op,Tuning能夠參考卷積的作法 來Tuning dense.
  • Ahuier
    Ahuier3 個月前
    有一個問題今天沒看明白,像batchnorn算子,我在源碼看不到它的具體實現,卷積就能夠看到,這是爲何呢?是被優化掉了,仍是怎麼回事,我想添加本身的算子
  • 藍色
    藍色 (做者) 回覆Ahuier3 個月前
    SimplifyInference優化掉了,變爲了scale * data + shift
  • 3038
    30382 個月前

    您好! 有個問題請教一下。 我這邊打算使用TVM部署到手機,auto tuning之後發現計算速度反而變慢。 若是不通過auto Tuning的話,性能和ncnn此類相比,會差很大嗎? 

  • 藍色
    藍色 (做者) 回覆30382 個月前
    Auto Tuning不該該變慢,你能夠再確認一下是否是哪裏出了問題。不通過Auto Tuning,在arm cpu上會跑fallback,性能很差說
  • 3038
    3038回覆藍色 (做者) 2 個月前

    謝謝,我按照您的意見確認一下

 

 

 


 

 

 

 

一步一步解讀神經網絡編譯器TVM(一)——一個簡單的例子

《一步一步解讀神經網絡編譯器TVM(一)——一個簡單的例子》

前言

這是一個TVM教程系列,計劃從TVM的使用說明,再到TVM的內部源碼,爲你們大體解析一下TVM的基本工做原理。由於TVM的中文資料比較少,也但願貢獻一下本身的力量,若有描述方面的錯誤,請及時指出。

那啥是TVM?

《一步一步解讀神經網絡編譯器TVM(一)——一個簡單的例子》

簡單來講,TVM能夠稱爲許多工具集的集合,其中這些工具能夠組合起來使用,來實現咱們的一些神經網絡的加速和部署功能。這也是爲何叫作TVM Stack了。TVM的使用途徑很廣,幾乎能夠支持市面上大部分的神經網絡權重框架(ONNX、TF、Caffe2等),也幾乎能夠部署在任何的平臺,例如Windows、Linux、Mac、ARM等等。

如下面一張圖來形容一下,這張圖來源於(https://tvm.ai/about):

《一步一步解讀神經網絡編譯器TVM(一)——一個簡單的例子》

乍看這麼多感受很是地複雜,但咱們只須要知道TVM的核心功能就能夠:TVM能夠優化的訓練好的模型,並將你的模型打包好,而後你能夠將這個優化好的模型放在任何平臺去運行,能夠說是與落地應用息息相關。

TVM包含的東西和知識概念都有不少,不只有神經網絡優化量化op融合等一系列步驟,還有其餘更多細節技術的支持(Halide、LLVM),從而使TVM擁有很強大的功能…好了廢話不說了,再說就憋不出來了,若是想多瞭解TVM的能夠在知乎上直接搜索TVM關鍵字,那些大佬有不少關於TVM的介紹文章,你們能夠去看看。

其實作模型優化這一步驟的庫已經出現不少了,不管是Nvidia自家的TensorRT仍是Pytorch自家的torch.jit模塊,都在作一些模型優化的工做,這裏就很少說了,感興趣的能夠看看如下文章:

利用Pytorch的C++前端(libtorch)讀取預訓練權重並進行預測
利用TensorRT實現神經網絡提速(讀取ONNX模型並運行)
利用TensorRT對深度學習進行加速

開始使用

說到這裏了,感受有必要說下:咱們爲何要使用TVM?

若是你想將你的訓練模型移植到Window端、ARM端(樹莓派、其餘一系列使用該內核的板卡)或者其餘的一些平臺,利用其中的CPU或者GPU來運行,而且但願能夠經過優化模型來使模型在該平臺運算的速度更快(這裏與模型自己的算法設計無關),實現落地應用研究,那麼TVM就是你的不二之選。另外TVM源碼是由C++和Pythoh共同搭建,閱讀相關源碼也有利於咱們程序編寫方面的提高。

安裝

安裝其實沒什麼多說的,官方的例子說明的很詳細。你們移步到那裏按照官方的步驟一步一步來便可。

不過有兩點須要注意下:

  • 建議安裝LLVM,雖然LLVM對於TVM是可選項,可是若是咱們想要部署到CPU端,那麼llvm幾乎是必須的
  • 由於TVM是python和C++一塊兒的工程,python能夠說是C++的前端,安裝官方教程編譯好C++端後,這裏建議選擇官方中的Method 1來進行python端的設置,這樣咱們就能夠隨意修改源代碼,再從新編譯,而Python端就不須要進行任何修改就能夠直接使用了。

《一步一步解讀神經網絡編譯器TVM(一)——一個簡單的例子》
(官方建議使用Method 1)

利用Pytorch導出Onnx模型

說了這麼多,演示一個例子才能更好地理解TVM究竟是作什麼的,因此咱們這裏以一個簡單的例子來演示一下TVM是怎麼使用的。

首先咱們要作的是,獲得一個已經訓練好的模型,這裏我選擇這個github倉庫中的mobilenet-v2,model代碼和在ImageNet上訓練好的權重都已經提供。好,咱們將github中的模型代碼移植到本地,而後調用並加載已經訓練好的權重:

import torch
import time from models.MobileNetv2 import mobilenetv2 model = mobilenetv2(pretrained=True) example = torch.rand(1, 3, 224, 224) # 假想輸入 with torch.no_grad(): model.eval() since = time.time() for i in range(10000): model(example) time_elapsed = time.time() - since print('Time elapsed is {:.0f}m {:.0f}s'. format(time_elapsed // 60, time_elapsed % 60)) # 打印出來時間 

這裏咱們加載訓練好的模型權重,並設定了輸入,在python端連續運行了10000次,這裏咱們所花的時間爲:6m2s。

而後咱們將Pytorch模型導出爲ONNX模型:

import torch
from models.MobileNetv2 import mobilenetv2 model = mobilenetv2(pretrained=True) example = torch.rand(1, 3, 224, 224) # 假想輸入 torch_out = torch.onnx.export(model, example, "mobilenetv2.onnx", verbose=True, export_params=True # 帶參數輸出 ) 

這樣咱們就獲得了mobilenetv2.onnx這個onnx格式的模型權重。注意這裏咱們要帶參數輸出,由於咱們以後要直接讀取ONNX模型進行預測。

導出來以後,建議使用Netron來查看咱們模型的結構,能夠看到這個模型由Pytorch-1.0.1導出,共有152個op,以及輸入id和輸入格式等等信息,咱們能夠拖動鼠標查看到更詳細的信息:

《一步一步解讀神經網絡編譯器TVM(一)——一個簡單的例子》

好了,至此咱們的mobilenet-v2模型已經順利導出了。

利用TVM讀取並預測ONNX模型

在咱們成功編譯而且能夠在Python端正常引用TVM後,咱們首先導入咱們的onnx格式的模型。這裏咱們準備了一張飛機的圖像:

《一步一步解讀神經網絡編譯器TVM(一)——一個簡單的例子》

這個圖像在ImageNet分類中屬於404: 'airliner',也就是航空客機。

下面咱們將利用TVM部署onnx模型並對這張圖像進行預測。

import onnx
import time import tvm import numpy as np import tvm.relay as relay from PIL import Image onnx_model = onnx.load('mobilenetv2.onnx') # 導入模型 mean = [123., 117., 104.] # 在ImageNet上訓練數據集的mean和std std = [58.395, 57.12, 57.375] def transform_image(image): # 定義轉化函數,將PIL格式的圖像轉化爲格式維度的numpy格式數組 image = image - np.array(mean) image /= np.array(std) image = np.array(image).transpose((2, 0, 1)) image = image[np.newaxis, :].astype('float32') return image img = Image.open('../datasets/images/plane.jpg').resize((224, 224)) # 這裏咱們將圖像resize爲特定大小 x = transform_image(img) 

這樣咱們獲得的x[1,3,224,224]維度的ndarray。這個符合NCHW格式標準,也是咱們通用的張量格式。

接下來咱們設置目標端口llvm,也就是部署到CPU端,而這裏咱們使用的是TVM中的Relay IR,這個IR簡單來講就是能夠讀取咱們的模型並按照模型的順序搭建出一個能夠執行的計算圖出來,固然,咱們能夠對這個計算圖進行一系列優化。(如今TVM主推Relay而不是NNVM,Relay能夠稱爲二代NNVM)。

target = 'llvm' input_name = '0' # 注意這裏爲以前導出onnx模型中的模型的輸入id,這裏爲0 shape_dict = {input_name: x.shape} # 利用Relay中的onnx前端讀取咱們導出的onnx模型 sym, params = relay.frontend.from_onnx(onnx_model, shape_dict) 

上述代碼中導出的symparams是咱們接下來要使用的核心的東西,其中params就是導出模型中的權重信息,在python中用dic表示:

《一步一步解讀神經網絡編譯器TVM(一)——一個簡單的例子》

sym就是表示計算圖結構的功能函數,這個函數中包含了計算圖的流動過程,以及一些計算中須要的各類參數信息,Relay IR以後對網絡進行優化就是主要對這個sym進行優化的過程:

fn (%v0: Tensor[(1, 3, 224, 224), float32], %v1: Tensor[(32, 3, 3, 3), float32], %v2: Tensor[(32,), float32], %v3: Tensor[(32,), float32], %v4: Tensor[(32,), float32], %v5: Tensor[(32,), float32], ... %v307: Tensor[(1280, 320, 1, 1), float32], %v308: Tensor[(1280,), float32], %v309: Tensor[(1280,), float32], %v310: Tensor[(1280,), float32], %v311: Tensor[(1280,), float32], %v313: Tensor[(1000, 1280), float32], %v314: Tensor[(1000,), float32]) { %0 = nn.conv2d(%v0, %v1, strides=[2, 2], padding=[1, 1], kernel_size=[3, 3]) %1 = nn.batch_norm(%0, %v2, %v3, %v4, %v5, epsilon=1e-05) %2 = %1.0 %3 = clip(%2, a_min=0, a_max=6) %4 = nn.conv2d(%3, %v7, padding=[1, 1], groups=32, kernel_size=[3, 3]) ... %200 = clip(%199, a_min=0, a_max=6) %201 = mean(%200, axis=[3]) %202 = mean(%201, axis=[2]) %203 = nn.batch_flatten(%202) %204 = multiply(1f, %203) %205 = nn.dense(%204, %v313, units=1000) %206 = multiply(1f, %v314) %207 = nn.bias_add(%205, %206) %207 } 

好了,接下來咱們須要對這個計算圖模型進行優化,這裏咱們選擇優化的等級爲3:

with relay.build_config(opt_level=3): intrp = relay.build_module.create_executor('graph', sym, tvm.cpu(0), target) dtype = 'float32' func = intrp.evaluate(sym) 

最後咱們獲得能夠直接運行的func

其中優化的等級分這幾種:

OPT_PASS_LEVEL = { "SimplifyInference": 0, "OpFusion": 1, "FoldConstant": 2, "CombineParallelConv2D": 3, "FoldScaleAxis": 3, "AlterOpLayout": 3, "CanonicalizeOps": 3, } 

最後,咱們將以前已經轉化格式後的圖像x數組和模型的參數輸入到這個func中,而且返回這個輸出數組中的最大值

output = func(tvm.nd.array(x.astype(dtype)), **params).asnumpy() print(output.argmax()) 

這裏咱們獲得的輸出爲404,與前文描述圖像在ImageNet中的分類標記一致,說明咱們的TVM正確讀取onnx模型並將其應用於預測階段。

咱們另外單獨測試一下模型優化後運行的速度和以前直接利用pytorch運行速度之間比較一下,能夠發現最後的運行時間爲:3m20s,相較以前的6m2s快了將近一倍。

since = time.time() for i in range(10000): output = func(tvm.nd.array(x.astype(dtype)), **params).asnumpy() time_elapsed = time.time() - since print('Time elapsed is {:.0f}m {:.0f}s'. format(time_elapsed // 60, time_elapsed % 60)) # 打印出來時間 

固然,這個比較並非很規範,不過咱們能夠大概分析出TVM的一些可用之處了。

後記

這一篇僅僅是帶你們瞭解一下什麼是TVM以及一個簡單例子的使用,在接下來的文章中會涉及到部分TVM設計結構和源碼的解析。可能涉及到的知識點有:

  • 簡單編譯器原理
  • C++特殊語法以及模板元編程
  • 神經網絡模型優化過程
  • 代碼部署

等等,隨時可能會進行變化。

人工智能已經開始進入嵌入式時代,各式各樣的AI芯片即將初始,將複雜的網絡模型運行在廉價低功耗的板子上可能也再也不是高不可攀的幻想,不知道將來會是怎麼樣,但TVM這個框架已經開始走了一小步。

 

 


 

 

 

陳天奇等人提出TVM:深度學習自動優化代碼生成器

機器之心  · 2018-02-18
此處@各類工程師

編者按:本文來自公衆號機器之心(ID:AI_era),做者陳天奇等,機器之心編譯,參與者李澤南、路雪。

TVM 是由華盛頓大學在讀博士陳天奇等人提出的深度學習自動代碼生成方法,去年 8 月機器之心曾對其進行過簡要介紹。該技術能自動爲大多數計算硬件生成可部署優化代碼,其性能可與當前最優的供應商提供的優化計算庫相比,且能夠適應新型專用加速器後端。近日,這項研究的論文《TVM: End-to-End Optimization Stack for Deep Learning》終於完成,內容包含新方法的介紹與討論,以及 TVM 在英偉達、AMD 的 GPU、樹莓派及一些 FPGA 上的性能評估。

(項目連接:https://github.com/dmlc/tvm)

深度學習模型能夠識別圖像、處理天然語言,以及在部分具備挑戰性的策略遊戲中擊敗人類。在其技術發展的過程當中,現代硬件穩步推動的計算能力扮演了不可或缺的做用。不少目前最爲流行的深度學習框架,如 TensorFlow、MXNet、Caffe 和 PyTorch,支持在有限類型的服務器級 GPU 設備上得到加速,這種支持依賴於高度特化、供應商特定的 GPU 庫。然而,專用深度學習加速器的種類愈來愈多,這意味着現代編譯器與框架愈來愈難以覆蓋全部的硬件。

顯而易見,以現有的點到點方式實現不一樣深度學習框架對全部種類的硬件進行後端支持是不現實的。咱們的最終目標是讓深度學習負載能夠輕鬆部署到全部硬件種類中,其中不只包括 GPU、FPGA 和 ASIC(如谷歌 TPU),也包括嵌入式設備,這些硬件的內存組織與計算能力存在着顯著的差別(如圖 1 所示)。考慮到這種需求的複雜性,開發一種可以將深度學習高級程序下降爲適應任何硬件後端的低級優化代碼的優化框架是最好的方法。

目前的深度學習框架依賴於計算圖的中間表示來實現優化,如自動微分和動態內存管理 [3,7,4]。然而,圖級別的優化一般過於高級,沒法有效處理硬件後端算子級別的轉換。另外一方面,目前深度學習框架的算子級別庫一般過於僵化,難以輕鬆移植到不一樣硬件設備上。爲了解決這些問題,咱們須要一個可實現從計算圖到算子級別的優化,爲各類硬件後端帶來強大性能的編譯器框架。

陳天奇等人提出TVM:深度學習自動優化代碼生成器

圖 1:CPU、GPU 與類 TPU 加速器須要不一樣的片上存儲架構和計算基元。在生成優化代碼時咱們必須考慮這一問題。

陳天奇等人提出TVM:深度學習自動優化代碼生成器

圖 2:TVM 堆棧圖。目前的堆棧支持多種深度學習框架以及主流 CPU、GPU 以及專用深度學習加速器。

優化的四大基本挑戰

深度學習的優化編譯器須要同時展現高級別與低級別的優化,在論文中,研究人員總結了在計算圖級別與張量算子級別上的四大基本挑戰:

  • 高級數據流複寫:不一樣的硬件設備可能具備大相徑庭的內存層次結構,所以,融合算子與優化數據佈局的策略對於優化內存訪問相當重要。

  • 跨線程內存複用:現代 GPU 與專用加速器的內存可被多個計算核心共享,傳統的無共享嵌套並行模式已再也不是最優方法。爲優化內核,在共享內存負載上的線程合做頗有必要。

  • 張量計算內部函數:最新的硬件帶來了超越向量運算的新指令集,如 TPU 中的 GEMM 算子和英偉達 Volta 架構中的 Tensor Core。所以在調度過程當中,咱們必須將計算分解爲張量算術內部函數,而非標量或向量代碼。

  • 延遲隱藏(Latency Hiding):儘管在現代 CPU 與 GPU 上,同時擁有多線程和自動緩存管理的傳統架構隱藏了延遲問題,但專用的加速器設計一般使用精簡控制與分流,這爲編譯器堆棧的調度帶來了複雜性。因此,調度仍需仔細,以隱藏內存訪問延遲。

TVM:一個端到端優化堆棧(見圖 2),該端到端優化編譯器堆棧可下降和調整深度學習工做負載,以適應多種硬件後端。TVM 的設計目的是分離算法描述、調度和硬件接口。該原則受到 Halide [22] 的計算/調度分離思想的啓發,並且經過將調度與目標硬件內部函數分開而進行了擴展。這一額外分離使支持新型專用加速器及其對應新型內部函數成爲可能。TVM 具有兩個優化層:計算圖優化層,用於解決第一個調度挑戰;具有新型調度基元的張量優化層,以解決剩餘的三個挑戰。經過結合這兩種優化層,TVM 從大部分深度學習框架中獲取模型描述,執行高級和低級優化,生成特定硬件的後端優化代碼,如樹莓派、GPU 和基於 FPGA 的專用加速器。該論文作出瞭如下貢獻:

  • 咱們構建了一個端到端的編譯優化堆棧,容許將高級框架(如 Caffe、MXNet、PyTorch、Caffe二、CNTK)專用的深度學習工做負載部署到多種硬件後端上(包括 CPU、GPU 和基於 FPGA 的加速器)。

  • 咱們發現了提供深度學習工做負載在不一樣硬件後端中的性能可移植性的主要優化挑戰,並引入新型調度基元(schedule primitive)以利用跨線程內存重用、新型硬件內部函數和延遲隱藏。

  • 咱們在基於 FPGA 的通用加速器上對 TVM 進行評估,以提供關於如何最優適應專用加速器的具體案例。

咱們的編譯器可生成可部署代碼,其性能可與當前最優的特定供應商庫相比,且可適應新型專用加速器後端。

陳天奇等人提出TVM:深度學習自動優化代碼生成器

圖 3:兩層卷積神經網絡的計算圖示例。圖中每一個節點表示一次運算,它消耗一或多個張量,並生成一或多個張量。張量運算能夠經過屬性進行參數化,以配置其行爲(如 padding 或 stride)。

 

陳天奇等人提出TVM:深度學習自動優化代碼生成器

論文:TVM: End-to-End Optimization Stack for Deep Learning

論文連接:https://arxiv.org/abs/1802.04799

論文摘要:可擴展框架,如 TensorFlow、MXNet、Caffe 和 PyTorch 是目前深度學習領域中最流行和易用的框架。可是,這些框架只對窄範圍的服務器級 GPU 進行優化,要把工做負載部署到其餘平臺,如手機、嵌入式設備和專用加速器(如 FPGA、ASIC),則須要大量手動工做。咱們提出了 TVM,一個端到端的優化堆棧,具有圖形級和算子級的優化,覺得多種硬件後端提供深度學習工做負載的性能可移植性。咱們討論了 TVM 所解決的深度學習優化挑戰:高級算子融合(operator fusion)、多線程低級內存重用、任意硬件基元的映射,以及內存延遲隱藏。實驗結果證實 TVM 在多個硬件後端中的性能可與適應低功耗 CPU 和服務器級 GPU 的當前最優庫相比。咱們還經過針對基於 FPGA 的通用深度學習加速器的實驗,展現了 TVM 對新型硬件加速器的適應能力。該編譯器基礎架構已開源。

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

TensorRT是什麼,TensorRT是英偉達公司出品的高性能的推斷C++庫,專門應用於邊緣設備的推斷,TensorRT能夠將咱們訓練好的模型分解再進行融合,融合後的模型具備高度的集合度。例如卷積層和激活層進行融合後,計算速度能夠就進行提高。固然,TensorRT遠遠不止這個:

咱們平時所見到了深度學習落地技術:模型量化、動態內存優化以及其餘的一些優化技術TensorRT都已經有實現,更主要的,其推斷代碼是直接利用cuda語言在顯卡上運行的,全部的代碼庫僅僅包括C++和cuda,固然也有python的包裝,咱們在利用這個優化庫運行咱們訓練好的代碼後,運行速度和所佔內存的大小都會大大縮減。

 

 

其實相似TensorRT具體工做的有不少,例如TVM、TC(Tensor Comprehensions),都作了一些相似於TensorRT的工做,將訓練好的模型轉化爲運行在特定端(例如GPU)的進行模型優化等一系列操做後的代碼,從而達到快速預測的效果。

那麼爲何要選擇TensorRT呢?很簡單,由於咱們目前主要使用的仍是Nvidia的計算設備,在Nvidia端的話確定要用Nvidia親兒子了

 

 

在我這裏的實驗結論代表,在FP32的精度下,使用TensorRT和不使用TensorRT在GPU上運行的速度比大概爲3:1,也就是在我這個模型爲前提條件下,TensorRT在GPU端使個人模型速度提高了3倍(不一樣模型不一樣顯卡不一樣構架提高速度不一樣)。

TensorRT具有的功能

目前TensorRT的最新版本是5.0,TensorRT的發展其實已經有一段時間了,支持轉化的模型也有caffe、tensorflow和ONNX了,咱們要知道,TensorRT是有本身的模型框架的,咱們首先先其餘訓練好的框架經過轉化代碼轉化爲TensorRT的代碼才能夠使用。TensorRT對Caffe模型的支持度最高,同時也支持將Caffe模型轉化爲int8精度。

而ONNX模型的轉化則是近半年來的實現成果,目前支持了大部分的運算(通過測試,咱們日常使用的90%的模型均可以使用ONNX-TensorRT來進行轉化)。惟一遺憾的是ONNX模型目前還不支持int8類型的轉化。

相關文章
相關標籤/搜索