TensorFlow架構與設計:圖模塊

計算圖是TensorFlow領域模型的核心。本文通過對計算圖領域模型的梳理,講述計算圖構造的基本原理。

Edge持有前驅節點與后驅節點,從而實現了計算圖的連接,也是計算圖前向遍歷,后向遍歷的銜接點。

邊上的數據以Tensor的形式傳遞,Tensor的標識由源節點的名稱,及其所在邊的src_output唯一確定。也就是說,tensor_id = op_name:src_output

src_output與dst_input

Edge持有兩個重要的屬性:

  • src_output:表示該邊為前驅節點的第src_output條輸出邊;
  • dst_input:表示該邊為后驅節點的第dst_input條輸入邊。

例如,存在兩個前驅節點s1, s2,都存在兩條輸出邊;存在兩個后驅節點d1, d2,都存在兩條輸入邊。

邊索引

控制依賴

計算圖中存在兩類邊,

  • 普通邊:用于承載Tensor,常用實線表示;
  • 控制依賴:控制節點的執行順序,常用虛線表示。

特殊地,控制依賴邊,其src_output, dst_input都為-1(Graph::kControlSlot),暗喻控制依賴邊不承載任何數據,僅僅表示計算的依賴關系。

bool Edge::IsControlEdge() const {
   return src_output_ == Graph::kControlSlot;
}

節點

Node(節點)持有零條或多條輸入/輸出的邊,分別使用in_edges, out_edges表示。另外,Node持有NodeDef, OpDef。其中,NodeDef持有設備分配信息,及其OP的屬性值集合;OpDef持有OP的元數據。

節點

輸入邊

在輸入邊的集合中按照索引線性查找,當節點輸入的邊比較多時,可能會成為性能的瓶頸。依次類推,按照索引查找輸出邊,算法相同。

Status Node::input_edge(int idx, const Edge** e) const {
  for (auto edge : in_edges()) {
    if (edge->dst_input() == idx) {
      *e = edge;
      return Status::OK();
    }
  }
  return errors::NotFound("not found input edge ", idx);
}

前驅節點

首先通過idx索引找到輸入邊,然后通過輸入邊找到前驅節點。依次類推,按照索引查找后驅節點,算法相同。

Status Node::input_node(int idx, const Node** n) const {
  const Edge* e;
  TF_RETURN_IF_ERROR(input_edge(idx, &e));
  if (e == nullptr) {
    *n = nullptr;
  } else {
    *n = e->src();
  }
  return Status::OK();
}

Graph(計算圖)就是節點與邊的集合,領域模型何其簡單。計算圖是一個DAG圖,計算圖的執行過程將按照DAG的拓撲排序,依次啟動OP的運算。其中,如果存在多個入度為0的節點,TensorFlow運行時可以實現并發,同時執行多個OP的運算,提高執行效率。

空圖

計算圖的初始狀態,并非是一個空圖。實現添加了兩個特殊的節點:Source與Sink節點,分別表示DAG圖的起始節點與終止節點。其中,Source的id為0,Sink的id為1;依次論斷,普通OP節點的id將大于1。

另外,Source與Sink之間,通過連接「控制依賴」的邊,保證計算圖的執行始于Source節點,終于Sink節點。它們之前連接的控制依賴邊,其src_output, dst_input值都為-1。

習慣上,僅包含Source與Sink節點的計算圖也常常稱為空圖。

空圖
Node* Graph::AddEndpoint(const char* name, int id) {
  NodeDef def;
  def.set_name(name);
  def.set_op("NoOp");

  Status status;
  Node* node = AddNode(def, &status);
  TF_CHECK_OK(status);
  CHECK_EQ(node->id(), node_id);
  return node;
}

Graph::Graph(const OpRegistryInterface* ops)
    : ops_(ops), arena_(8 << 10 /* 8kB */) {
  auto src  = AddEndpoint("_SOURCE", kSourceId);
  auto sink = AddEndpoint("_SINK",   kSinkId);
  AddControlEdge(src, sink);
}

非空圖

在前端,用戶使用OP構造器,將構造任意復雜度的計算圖。對于運行時,無非就是將用戶構造的計算圖通過控制依賴的邊與Source/Sink節點連接,保證計算圖執行始于Source節點,終于Sink節點。

非空圖

添加邊

計算圖的構造過程非常簡單,首先通過Graph::AddNode在圖中放置節點,然后再通過Graph::AddEdge在圖中放置邊,實現節點之間的連接。

const Edge* Graph::AllocEdge() const {
  Edge* e = nullptr;
  if (free_edges_.empty()) {
    e = new (arena_.Alloc(sizeof(Edge))) Edge;
  } else {
    e = free_edges_.back();
    free_edges_.pop_back();
  }
  e->id_ = edges_.size();
  return e;
}

const Edge* Graph::AddEdge(Node* source, int x, Node* dest, int y) {
  auto e = AllocEdge();
  e->src_ = source;
  e->dst_ = dest;
  e->src_output_ = x;
  e->dst_input_ = y;

  CHECK(source->out_edges_.insert(e).second);
  CHECK(dest->in_edges_.insert(e).second);

  edges_.push_back(e);
  edge_set_.insert(e);
  return e;
}

添加控制依賴邊,則可以轉發調用Graph::AddEdge實現。

const Edge* Graph::AddControlEdge(Node* src, Node* dst) {
  return AddEdge(src, kControlSlot, dst, kControlSlot);
}

開源技術書

https://github.com/horance-liu/tensorflow-internals
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內容