tensorflow源碼解析之distributed_runtime


本篇主要介紹TF的分布式運行時的基本概念。為了對TF的分布式運行機制有一個大致的了解,我們先結合/tensorflow/core/protobuf中的文件給出對TF分布式集群的初步理解,然后介紹/tensorflow/core/distributed_runtime路徑下的核心概念。


TF分布式集群

集群定義和理解

在研讀TF的分布式運行時代碼之前,我們需要先看下TF分布式運行的基本架構。TF的集群(cluster)由作業(job)構成,作業由任務(task)構成。舉個例子,一個由兩個作業構成的集群,作業1名為“worker”,包含了3個任務,作業2名為“ps”,包含了2個任務,如下:

Cluster:
    job { name:'worker'
            tasks {key:0 value:'worker1:2222'}
            tasks {key:1 value:'worker2:2222'}
            tasks {key:2 value:'worker3:2222'}
    }
    job { name:'ps'
            tasks {key:0 value:'ps0:2222'}
            tasks {key:1 value:'ps1:2222'}
    }

下面再看TF對於集群的定義,就一目了然了:

message JobDef {
    string name = 1;//作業的名稱
    
    //作業包含的任務id到hostname:port字符串的映射,也就是任務的編號到任務的數據傳輸接口
    map<int32, string> tasks = 2;
}

message ClusterDef {
    repeated JobDef job = 1;
}

以下我們會分別介紹Master服務和Worker服務,注意,Master服務是由Master提供,供客戶端使用的,而Worker服務是由Worker提供,供Master使用的。

master

先來講Master服務。Master服務是一種被客戶端用來與分布式的TF計算交互的服務。

一個Master服務通常會包含了多個master會話,每一個會話包含了一張計算圖以及與之相關的狀態,這些master會話通常會對應同一個client會話。

一個Master會話的職責包括:

  • 節點放置;
  • 插入恰當的節點以實現跨設備和跨進程的數據流和資源管理;
  • 發布命令給worker,使之運行分配給它的計算子圖;

通常,客戶端可以通過RPC的形式與一個Master之間保持一個交互式的計算。客戶端首先建立一個客戶端的會話,連接到一個特定的Master,這個Master接着創建一個對應的Master會話,並且在客戶端的調用之間維持狀態。

Master會話創建之后,Master會返回一個句柄給客戶端,這個句柄可以被用來進行客戶端和Master會話之間的交互。

客戶端可以在CreateSession調用中傳遞一個初始的圖給Master,並且使用ExtendSession向圖中添加節點。

對於一個Master來說,最常用的操作是RunStep,它實現了一個Session::Run()的API。它支持提供輸入,執行圖計算,返回輸出。

最后,當客戶端不再需要Master會話的時候,它需要通過CloseSession關閉這個會話,Master可以回收跟會話相關的資源。Master在關閉會話期間可以會因為垃圾回收而休眠一段時間。

我們來總結下MasterService包含的內容:

service MasterService {
    rpc CreateSession(CreateSessionRequest) returns (CreateSessionResponse);
    rpc ExtendSession(ExtendSessionRequest) returns (ExtendSessionResponse);
    rpc PartialRunStep(PartialRunStepRequest) returns (PartialRunSetupResponse);
    rpc RunStep(RunStepRequest) returns (RunStepResponse);
    rpc CloseSession(CloseSessionRequest) returns (CloseSessionResponse);
    rpc ListDevices(ListDevicesRequest) returns (ListDeviceResponse);
    rpc Reset(ResetRequest) returns ( ResetResponse);
}

代碼中提到的xxxRequest和xxxResponse,都有對應的結構,詳見/tensorflow/core/protobuf/master.proto。

woker

Worker服務定義了一種TF的服務,它可以代表MasterService,在一些局部的設備上執行數據流圖。

一個Worker服務保留了多個注冊圖,每一個注冊圖都是客戶端完整圖的一個子圖,包含了僅需要在當前worker上計算的節點。

service WorkerService {
    rpc GetStatus(GetStatusRequest) returns (GetStatusResponse);
    rpc CreateWorkerSession(CreateWorkerSessionRequest) returns (CreateWorkerSessionResponse);
    rpc RegisterGraph(RegisterGraphRequest) returns (RegisterGraphResponse);
    rpc DeregisterGraph(DeregisterGraphRequest) returns (DeregisterGraphResponse);
    rpc RunGraph(RunGraphRequest) returns (RunGraphResponse);
    rpc CleanupGraph(CleanupGraphRequest) returns (CleanupGraphResponse);
    rpc CleanupAll(CleanupAllRequest) returns (CleanupAllResponse);
    rpc RecvTensor(RecvTensorRequest) returns (RecvTensorResponse) {}
    rpc Logging(LoggingRequest) returns (LoggingResponse);
    rpc Tracing(TracingRequest) returns (TracingResponse);
}

以上內容來自/tensorflow/core/protobuf,主要為了講解TF中集群的基本概念和運行過程,以下內容來自/tensorflow/core/distributed_runtime,介紹TF中分布式運行時環境中的核心概念。

worker

Worker代表了執行計算的實體,與Client和Master相對應。以下是相關類的關系圖:

graph TB WorkerCacheInterface-->|用於產生|WorkerInterface WorkerCache-->|用於產生|Worker WorkerCacheInterface-->|派生|WorkerCache WorkerInterface-->|派生|Worker WorkerCacheLogger-->|提供日志記錄服務|WorkerCache Worker-->WorkerEnv Worker-->WorkerSession

tensor_coding

包含了TensorResponse類,這個類的作用是,當一個RPC返回了數據時,通過這個類可以把返回結果中的數據解析為張量,以及其它的元數據信息。

session_mgr

包含了SessionMgr類,它存在於Worker上,為Worker管理會話,包括了會話的產生和銷毀,同時還維護了一個當前Worker上的會話句柄到會話的映射。

class SessionMgr {
  public:
    Status CreateSession(...);
    Status DeleteSession(...);
  private:
    const WorkerEnv* const worker_env_;
    const WorkerCacheFactory worker_cache_factory_;
    std::map<string, std::unique_ptr<WorkerSession>> sessions_ GUARDED_BY(mu_);
};

server_lib

TF中的server,可以表現為兩種形式,一種是Worker,一種是Master,可以認為,兩者都是對外提供了“服務”,只不過是兩種不同的形式。ServerInterface為它們提供了統一的接口:

class ServerInterface {
  public:
    virtual Status Start() = 0;
    virtual Status Stop() = 0;
    virtual Status Join() = 0;
};

而所有的Server必須由其對應的工廠類產生,工廠類還提供了對其子類的注冊接口:

class ServerFactory {
  public:
    virtual Status NewServer(...);
    
    //任何一個工廠類的子類,都必須用這個方法將其一個對象注冊到這里
    static void Register(const string& server_type, ServerFactory* factory);
    
    //根據server_def,尋找一個能產生指定server的工廠
    static Status GetFactory(const ServerDef& server_def, ServerFactory** out_factory);
};

scheduler

根據Graph和CostModel的信息,計算不同調度策略下,每個節點的最早開始時間和最晚開始時間,三個類SlackAnalysis,GreedyScheduler,PriorityScheduler分別代表了松弛策略、貪心調度策略和優先級調度策略。

rendezvous_mgr_interface

類RendezvousMgr管理着一個局部rendezvous對象的集合。所有被當前的Worker發送的張量,在接收之前都在這個RendezvousMgr中保存着。每一個全局的step_id都對應着一個被RendezvousMgr管理的一個局部的rendezvous實例。

remote_device

包含了一個函數,NewRemoteDevices,它可以發現remote_worker上的可用設備。

partial_run_mgr

PartialRunMgr保存了未完成的局部運行的需求,它保證只有當對應的執行器完成運行時,它才會被標記為完成。

在TF的worker中,執行器會異步的執行,直到需求的輸出(能夠返回張量的操作)或者目標(不會返回張量的操作)完成。也就是說,計算圖中有兩類節點都可以作為worker執行的目標,一類是返回張量的操作對應的節點,一類是不返張量的操作對應的節點。一個局部運行包含兩步,第一,設置所有需要的輸出和目標,第二,獲得輸出。在第二步時,可能存在一種情況,即計算圖中需求的輸出已經計算完成,但需求的目標仍在計算。這時候,PartialRunMgr就發揮作用了,雖然這時理論上可以返回了,因為所有需求的輸出都計算完成了,剩余的需求目標並不影響返回的結果。但TF仍然要求必須等到所有的目標都完成計算才行,因為在目標完成計算之前,我們並不知道中間的輸出是否會發生變化。

message_wrappers

在Master和Worker之間相互通信的Request/Response的包裝類。

// Wrapper classes for the `MasterService.RunStep` request message.
class RunStepRequestWrapper {}
class MutableRunStepRequestWrapper : public RunStepRequestWrapper {}
class InMemoryRunStepRequest : public MutableRunStepRequestWrapper {}
class MutableProtoRunStepRequest : public MutableRunStepRequestWrapper {}
class ProtoRunStepRequest : public RunStepRequestWrapper {}

// Wrapper classes for the `WorkerService.RunGraph` request message.
class RunGraphRequestWrapper {}
class MutableRunGraphRequestWrapper : public RunGraphRequestWrapper {}
class InMemoryRunGraphRequest : public MutableRunGraphRequestWrapper {}
class MutableProtoRunGraphRequest : public MutableRunGraphRequestWrapper {}
class ProtoRunGraphRequest : public RunGraphRequestWrapper {}

// Wrapper classes for the `WorkerService.RunGraph` response message.
class MutableRunGraphResponseWrapper {}
class InMemoryRunGraphResponse : public MutableRunGraphResponseWrapper {}
class OwnedProtoRunGraphResponse : public MutableRunGraphResponseWrapper {}
class NonOwnedProtoRunGraphResponse : public MutableRunGraphResponseWrapper {}

// Wrapper classes for the `MasterService.RunStep` response message.
class MutableRunStepResponseWrapper {}
class InMemoryRunStepResponse : public MutableRunStepResponseWrapper {}
class OwnedProtoRunStepResponse : public MutableRunStepResponseWrapper {}
class NonOwnedProtoRunStepResponse : public MutableRunStepResponseWrapper {}

master_session

與單機情況下的DirectSession對應的,分布式情況下的Master會話,它包含了圖計算的基本步驟,比如資源分配、節點放置、圖執行等。

master_interface

用於與TF的Master服務通信的虛擬接口。這個接口既支持基於RPC的master實現,也支持進程內部的master實現。

master

TF中Master服務的實現。與Worker服務對應。

master_env

Master的環境類,包含了一個Master所必須的環境資源指針。注意Master並不擁有這些指針。

local_master

局部Master的實現。局部Master的含義是,與Client的通信不是跨設備的,而是直接在進程內部進行的。這個Master的實現,是為了給同進程內部的Client提供更高效的Master服務。

graph_mgr

GraphMgr包含了注冊到某個worker的圖的集合。每一個注冊的圖都會被一個句柄標識,這個句柄由GraphMgr產生,並且返回給調用者。在注冊成功之后,調用者通過一個圖句柄來執行一張圖。每一次的執行都被一個全局的"step_id"唯一標識。在同一張圖上,可以重復和獨立的執行多次,只要每一次執行的"step_id"都是不同的。

call_options

為不同的RPC系統提供了可插拔的調用接口。

base_rendezvous_mgr

為RendezvousMgrInterface提供了不同的實現,具體框架圖如下:

graph TB RendezvousMgrInterface-->|派生|BaseRendezvousMgr RemoteRendezvous-->|派生|BaseRemoteRendezvous Rendezvous-->|派生|RemoteRendezvous

github地址


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM