tensorflow源码解析之common_runtime-executor-下

 

目录

  1. 核心概念
  2. executor.h
    1. Executor
    2. NewLocalExecutor
    3. ExecutorBarrier
  3. executor.cc
    1. structs
    2. GraphView
    3. ExecutorImpl
    4. ExecutorState
    5. details

3.4 ExecutorState

在执行器的执行图计算的时候,需要一个结构来保存当前计算的即时信息,TF为此设计了类ExecutorState,它被用来保存每一个对ExecutorImpl::Run调用的状态信息。它会在一个节点已经准备好之后调度这个节点,并且保存每个节点尚未完成的输入信息。
下面让我们先来看一下这个类的结构:

class ExecutorState {   public:     ExecutorState(const Executor::Args& args, ExecutorImpl* impl);     void RunAsync(Executor::DoneCallback done);   private:     DeviceContextMap device_context_map_;          typedef gtl::InlinedVector<TaggedNode, 8> TaggedNodeSeq;     typedef gtl::InlinedVector<Entry, 4> EntryVector;          const bool vlog_;     const bool log_memory_;     int64 step_id_;          //未拥有     Rendezvous* rendezvous;     SessionState* session_state_;     TensorStore* tensor_store_;     //每个执行步级别的容器     ScopedStepContainer* step_container_;     StepStatesCollector* stats_collector_;          checkpoint::TensorSliceReaderCacheWrapper* slice_reader_cache_;     FunctionCallFrame* call_frame;     const ExecutorImpl* impl_;     CancellationManager* cancellation_manager_;     Executor::Args::Runner runner_;     bool sync_on_finish_;          //拥有     bool dumped_on_error_ = false;     //当前执行步骤开始的帧     FrameState* root_frame_;     //执行器结束时需要调用的回调函数     Executor::DoneCallback done_cb_;     std::atomic_int_fast32_t num_outstanding_ops_;     mutex mu_;     Status status_ GUARDED_BY(mu_);          //从帧名称到实际帧的映射。在当前帧的某个迭代周期内,可能会产生一个新的帧。新的子帧的唯一键值必须由父帧的名称、迭代编号、以及由nodedef推断出来的新帧的名称组合而成     gtl::FlatMap<string, FrameState*> outstanding_frames_ GUARDED_BY(mu_);          //一个帧的名称     inline string MakeFrameName(FrameState* frame, int64 iter_id, const string& name);          //找到一个现存的帧,或者创建一个新帧,在帧frame的iter迭代周期     void FindOrCreateChildFrame(FrameState* frame, int64 iter, const Node* node, FrameState** child);          //删除一个帧,当帧调用结束时使用     void DeleteFrame(FrameState* frame, TaggedNodeSeq* ready);          //清除那些起源于帧frame和迭代iter的帧,当一个子帧结束时调用     void CleanupFramesIterations(FrameState* frame, int64 iter, TaggedNodeSeq* ready);          //在当前的线程中处理一个已准备好的节点     void Process(TaggedNode node, int64 scheduled_usec);          //在调用item->kernel之前,先填入其输入     Status PrepareInputs(const NodeItem& item, Entry* first_input, TensorValueVec* inputs, DeviceContextVec* input_device_contexts, AllocatorAttributeVec* input_alloc_attrs, bool* is_input_dead);          //在item->kernel计算结束之后,处理输出     Status ProcessOutputs(const NodeItem& item, OpKernelContext* ctx, EntryVector* outputs, NodeExecStats* stats);          //在处理完输出之后,将输入传递给下一个输入     void PropagateOutputs(const TaggedNode& tagged_node, const NodeItem* item, EntryVector* outputs, TaggedNodeSeq* ready);          //节点计算结束后,接管stats,如果执行完成则返回true     bool NodeDone(const Status& s, const Node* node, const TaggedNodeSeq& ready, NodeExecStats* stats, TaggedNodeReadyQueue* inline_ready);          //调度ready中的所有复杂节点,然后将ready中的非复杂节点放入inline_ready     void ScheduleReady(const TaggedNodeSeq& ready, TaggedNodeReadyQueue* inline_ready);          //仅用作调试或记录     inline void MaybeMarkCompleted(FrameState* frame, int64 iter, int64 id);          //输出一个未完成或者活跃节点的信息     void DumpPendingNodeState(const int node_id, const Entry* input_vector, bool show_nodes_with_no_ready_inputs);     void DumpActiveNodeState(const FrameState* frame, IterationState* iteration);          //提供执行器的状态信息     void DumpState();     const Tensor* GetTensorValueForDump(const Entry& input);          //当执行器结束执行时,清理     void Finish(); };

从API上来看,ExecutorState几乎担当了执行器的职责,从后面的介绍也可以看出,实际上确实如此。执行器内部实际调用的就是ExecutorState内部的API。从类的结构中,我们还是看到了许多未曾相识的结构,下面我们先一一分析这些类的意义和结构。

首先来看Entry,Entry要么是一个张量指针,要么是一个张量值,为计算图中的节点的输入或输出提供了一种统一的类型。

struct Entry {     Entry(

                    
                
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信