MxNet源碼解析(2) symbol

1. 前言

我們在訓練之前矩距,先建立好一個圖,然后我們可以在這個圖上做我們想做的優(yōu)化怖竭,這種形式稱為Symbolic Programs锥债。相對應的是Imperative Programs,也就是每一句代碼都對應著程序的執(zhí)行,在這種情況下哮肚,我們可以寫類似于下面的代碼:

a = 2
b= a + 1
d = np.zeros(10)
for i in range(d):
    d += np.zeros(10)

這在symbolic的方式下是做不到的登夫,因為在for循環(huán)開始時,程序并不知道d的值允趟,也就無法判斷循環(huán)的次數(shù)恼策。
因此我們可以說,symbolic更高效潮剪,imperative更靈活涣楷。

MxNet是一個異步式的訓練框架,它支持上面的兩種形式抗碰。我們可以使用NDArray來進行imperative形式的程序編寫狮斗,也可以使用symbol來建立圖。

2. op

先來了解operator弧蝇,不了解operator可能就很難理解源碼中占據(jù)了很大一部分的operator的定義碳褒。就是通過這些operator來將symbol連接成為了一個圖。

  • OpManager:單例結構體捍壤,通過OpManager::Global()總會返回同一個結構體骤视。Op的構造函數(shù)會將OpManagerop_counter加一,并且將自己的index_注冊為當前的op_counter鹃觉。
  • add_alias:將別名注冊到`dmlc::Registry<Op>中
  • Get:根據(jù)name返回Op
  • GetAttrMap

2.1 op

  • name:名字
  • description:該op的描述
  • num_inputs:輸入的個數(shù)
  • num_outputs:輸出的個數(shù)
  • get_num_outputs, get_num_inputs:函數(shù)专酗,返回輸出,輸入的個數(shù)
  • attr_parser:函數(shù)盗扇,用于方便返回該op的參數(shù)
  • Op& Op::describe(const std::string& descr):方法用于將輸入注冊到description變量中祷肯,并返回這個op,方便接著調(diào)用其他方法疗隶。

2.2 幾個宏

  • #define NNVM_REGISTER_VAR_DEF(OpName):定義OpName
  • #define NNVM_REGISTER_VAR_DEF(TagName):定義TagName
#define NNVM_REGISTER_OP(OpName) \
  DMLC_STR_CONCAT(NNVM_REGISTER_VAR_DEF(OpName, __COUNTER__) = \
    ::dmlc::Register<::nnvm::op>::Get()->__REGISTER_OR_GET(#OpName)

注冊op佑笋,并返回該op

3. Node

Node是組成symbol的基本組件。
結構體NodeEntry包含了:

  • node:指向node的指針
  • index:輸出的索引值
  • version:輸入的version

結構體NodeAttrs包含了:

  • op: 指向operator的指針
  • name: node的名字
  • dict:attributes的字典

Node包含:

  • attrs:結構體NodeAttrs成員斑鼻,存儲了op, name, attributes等信息蒋纬。
  • inputs:輸入,是一個元素為NodeEntry的向量
  • control_deps:保存了應該在該node執(zhí)行之前執(zhí)行的node坚弱。
  • op():返回該Node的operator蜀备,就是返回attrs中保存的op
  • Create():類方法,靜態(tài)方法荒叶,用于新建一個Node碾阁,返回指向它的指針
  • num_outputs:如果是變量,輸出為1些楣,否則返回op的輸出

幾個函數(shù)

定義在文件op_attr_types.h

  • FListinputNames:返回輸入的名字脂凶,默認return {'data'}
  • FNumVisibleOutputs:用于隱藏一些輸出
  • FListOutputNames:返回輸出的名字
  • FMutateInputs:返回該node會改變的node的索引值
  • FInferNodeEntryAttr:推理出AttrType
  • FInferShape:推理shape宪睹,也就是上面的AttrTypeTshape
  • FInferType:推理類型
  • TIsBackward是否是反向傳播
  • FInplaceOption
  • FGradient:返回node的梯度節(jié)點
  • FSetInputVarAttrOnCompose:為輸入設置attribute
  • FCorrectLayout:推理layout
  • FInputGraph:返回輸入,解釋為圖而不是數(shù)據(jù)

這些函數(shù)是在定義具體的op時蚕钦,可以選擇注冊對應的函數(shù)亭病。

4. Symbol

Symbol是為了使用Node建立Graph。Symbol是我們能夠直接接觸的類嘶居,它定義了一系列方法用于更方便地構建圖命贴。在symbol的成員outputs中,定義了一組由NodeEntry組成的向量食听。

  • outputs:該symbol包含的輸出,是一個元素是NodeEntry的向量
  • Copy:返回一個深拷貝污茵,方式是通過遍歷Node樱报,每次訪問到的Node保存起來,再建立起node之間的連接泞当,最后將head加入到outputs中迹蛤。
  • Symbol operator[] (size_t index) const:返回第n個輸出。
  • ListInputs:返回輸入
  • ListInputNames:返回輸入的名字
  • Compose:組合symbol
  • operator ():調(diào)用compose襟士,來組合symbol
  • AddControlDeps:加入控制盗飒,用于有向圖的構建
  • GetInternals:返回一個symbol,它的輸出是原來symbol的輸出加上所有中間輸出和輸入
  • GetChildren
  • SetAttrs:設置attribution
  • GetAttrs
  • CreateFunctor:給定op和attrs陋桂,返回一個symbol
    我認為symbol中比較重要的函數(shù)是compose逆趣,在調(diào)用的時候我們是通過調(diào)用symbol的操作符()函數(shù),也就是operator ()嗜历,該函數(shù)將參數(shù)傳遞給Compose宣渗。

5. Graph

Graph就是計算的時候使用的圖

  • outputs:和symboloutputs一樣,類型為std::vector<NodeEntry>
  • attrs:定義了圖的一些屬性
  • PostOrderDFSVisit:后序遍歷圖梨州,給定參數(shù)head痕囱,進行拓撲排序。算法暴匠,貌似鞍恢,就是拓撲排序算法。
  • DFSVisit:調(diào)用PostOrderDFSVisit每窖,對圖的head進行拓撲排序帮掉。參數(shù)為:const std::vector<NodeEntry>& heads, FVisit fvisit,其中head是反向傳播時的頭節(jié)點岛请,fvisit是訪問時調(diào)用的函數(shù)旭寿,該方法將fvisit(*n)作為訪問節(jié)點時的函數(shù),[](GNode n)->Node*{return->get();}作為hash函數(shù)崇败,這個函數(shù)看簽名返回的是一個指向節(jié)點的指針盅称。圖的節(jié)點入度計算如下:
[](GNode n)->uint32_t {
  if (!(*n)) return 0;
  return (*n)->input.size() + (*n)->control_deps.size();
}

節(jié)點輸入計算如下:

[](GNode n, uint32_t index)->GNode {
  if (index < (*n)->input.size()) {
    return &(*n)->input.at(index).node;
  } else {
  return &(*n)->contorl_deps.at(index - (*n)->inputs.size());
}

6. IndexedGraph

IndexedGraphGraph返回肩祥,

  • nodes_:成員變量,一個指向Node結構體的向量缩膝,Node定義如下:
struct Node {
  const nnvm::Node* source;
  array_view<NodeEntry> inputs;
  array_view<uint32_t> control_deps;
  std::weak_ptr<nnvm::Node> weak_ref;
};

其中NodeEntry如下:

struct NoodeEntry {
  uint32_t node_id;
  uint32_t index;
  uint32_t version;
};

成員變量:

  • input_nodes_:輸入node的索引
  • mutable_input_nodes_
  • outputs:輸出節(jié)點
  • node2index:node到索引的映射
  • entry_rptr_:
  • input_entries_
  • control_deps_
    方法:
  • DFSVisit
  • PostOrderDFSVisti

7. pass

7.1 gradient.cc

  • Gradientgradient會根據(jù)屬于的graph混狠,返回一個帶反向傳播圖的新圖。它主要由executor建立圖的時候調(diào)用疾层,調(diào)用方式如下:
nnvm::Graph g_grad = nnvm::pass::Gradient(g, 
            symbol.outputs, xs, head_grad_entry_, ArggregateGradient,
            need_mirror, nullptr, zero_ops, "_copy");

調(diào)用該方法會調(diào)用文件pass_function.h下的Gradient函數(shù)将饺。該函數(shù)將傳入的參數(shù)保存在graph下的attrs中。再通過applypass調(diào)用Gradient方法痛黎。也就是在該文件下定義的方法予弧,簽名:Graph Gradient(Graph src)

  1. 根據(jù)DFSVisit進行拓撲排序湖饱,將序列存儲到topo_order
  2. 將輸出的梯度保存在output_grads
  3. 根據(jù)mirror_fun在適當?shù)牡胤讲迦胄碌墓?jié)點掖蛤,來實現(xiàn)內(nèi)存的復用
  • DefaultAggregateGradient

7.2 plan_memory.cc

7.3 place_device.cc

7.4 correct_layout.cc

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市井厌,隨后出現(xiàn)的幾起案子蚓庭,更是在濱河造成了極大的恐慌,老刑警劉巖仅仆,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件器赞,死亡現(xiàn)場離奇詭異,居然都是意外死亡墓拜,警方通過查閱死者的電腦和手機港柜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來撮弧,“玉大人潘懊,你說我怎么就攤上這事』哐埽” “怎么了授舟?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長贸辈。 經(jīng)常有香客問我释树,道長,這世上最難降的妖魔是什么擎淤? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任奢啥,我火速辦了婚禮,結果婚禮上嘴拢,老公的妹妹穿的比我還像新娘桩盲。我一直安慰自己,他們只是感情好席吴,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布赌结。 她就那樣靜靜地躺著捞蛋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪柬姚。 梳的紋絲不亂的頭發(fā)上拟杉,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機與錄音量承,去河邊找鬼搬设。 笑死,一個胖子當著我的面吹牛撕捍,可吹牛的內(nèi)容都是我干的拿穴。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼忧风,長吁一口氣:“原來是場噩夢啊……” “哼贞言!你這毒婦竟也來了?” 一聲冷哼從身側響起阀蒂,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎弟蚀,沒想到半個月后蚤霞,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡义钉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年昧绣,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捶闸。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡夜畴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出删壮,到底是詐尸還是另有隱情贪绘,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布央碟,位于F島的核電站税灌,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏亿虽。R本人自食惡果不足惜菱涤,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望洛勉。 院中可真熱鬧粘秆,春花似錦、人聲如沸收毫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至陋气,卻和暖如春劳吠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背巩趁。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工痒玩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人议慰。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓蠢古,卻偏偏與公主長得像,于是被迫代替她去往敵國和親别凹。 傳聞我的和親對象是個殘疾皇子草讶,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

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