tensorflow原始碼解析之framework-resource
核心概念
資源大多數情況下指的是記憶體,首先我們來看下相關的序列化結構,ResourceHandleProto
message ResourceHandleProto { //包含該資源的裝置唯一名稱 string device = 1; //包含該資源的容器名稱 string container = 2; //該資源的唯一名稱 string name = 3; //該資源所屬型別的唯一雜湊值,僅在當前裝置和當前執行中有效 uint64 hash_code = 4; //如果可以獲取的話,表示當前控制程式碼指向資源的型別,僅除錯使用 string maybe_type_name = 5; }
簡單來說,這是一個資源的控制程式碼,它包含了描述這個資源的位置、屬性的關鍵資訊。
resource_handle
細看一下resource_handle.h,就會發現其中的ResrouceHandle類根本就是前面proto的C++實現。之所以要單獨再實現一個C++版本的資源控制程式碼,是為了避免讓kernels依賴於protos。
resource_mgr
系統中的大量資源需要被高效的管理,這些資源型別繁多,用處又各有不同,因此TF提出了包含容器的資源管理類——ResourceMgr。三者的關係如下:
graph LRResourceMgr-->ContainerContainer-->Resource
看看ResourceMgr類中都包含了哪些私有資料成員:
class ResourceMgr { //...private: //... typedef std::pairKey; typedef std::unordered_map Container; const string default_container_; mutable mutext mu_; std::unordered_map containers_ GUARDED_BY(mu_); std::unordered_map debug_type_names GUARDED_BY(mu_); }
其中,容器Container本質上是一個對映,從Key到ResourceBase*的對映,前者包含資源型別的雜湊值(想想ResourceHandleProto中的hash_code欄位)和資源的名稱,而後者就是所有資源的基類物件的指標,這個基類物件我們後面會講到。資源管理器中最核心的私有資料是containers_,它也是一個對映,把容器的名稱對映為容器指標。透過這樣一個兩層的對映,TF實現了資源管理的功能。
剛才提到了ResourceBase類,我們看一下它的實現:
class ResourceBase : public core::RefCounted {public: virtual string DebugString() = 0; virtual int64 MemoryUsed() const {return 0;}; };
因此,ResourceBase徒有其名,本質上只是一個提供了引用計數功能的物件。資源的使用一定要慎之又慎,提供引用計數功能也是為了方便對資源做回收。
再回到ResourceMgr類,為了透徹理解它的功能,我們再看下它包含的主要介面:
class ResourceMgr {public: //在container容器中建立一個名為name的資源 Status Create(const string& container, const string& name, T* resource); //在container中查詢一個名為name的資源 Status Lookup(const string& container, const string& name, T** resource) const; //如果container中包含名為name的資源,填充到*resource中,否則,使用creater()建立一個資源 Status LookupOrCreate(const string& container, const string& name, T** resource, std::functioncreater); //刪除container中的名為name的資源 Status Delete(const string& container, const string& name); //刪除控制程式碼handle指向的資源 Status Delete(const ResourceHandle& handle); //刪除container中的所有資源,並刪除該container Status Cleanup(const string& container); //刪除所有容器中的所有資源 void Clear(); }
有意思的是,ResourceMgr包含了兩個Delete函式,其中一個以容器名稱和資源名稱為引數,另一個以ResourceHandle為引數,這裡資源控制程式碼的作用就很明顯了,它可以方便的指代一個資源的位置。
為了更方便的使用ResourceHandle,TF還提供了很多輔助函式,為了節省篇幅,僅列出函式名:
//產生ResourceHandleMakeResourceHandle MakeResourceHandleToOutput MakePerStepResourceHandle HandleFromInput//根據ResourceHandle查詢或構造資源CreateResource LookupResource LookupOrCreateResource DeleteResource
說了這麼多,resource到底是什麼呢?在TF中,有些kernel是帶狀態的,在某次執行完成後,它需要儲存一些狀態資訊,方便下次執行的時候時候。這些狀態資訊就是resource的一種,為了方便管理這些狀態資訊,才構造了資源相關的類。對於一個kernel來說,一個很自然的問題是,如果它需要將中間狀態作為resource儲存起來,它需要選擇哪個container呢?如果不同kernel的臨時狀態被隨機的存放在資源管理器中,很不方便,因此TF設計了一個類,專門用來輔助kernel,幫它找到一個合適的容器,這個類就是ContainerInfo:
class ContainerInfo {public: Status Init(ResourceMgr* rmgr, const NodeDef& ndef, bool use_node_name_as_default); //...private: ResourceMgr* rmgr_ = nullptr; string container_; string name_; bool resource_is_private_to_kernel_ = false; }
這個決定的具體過程是這樣的:
如果container引數非空,就使用它,否則使用資源管理器的預設container
如果shared_name引數是非空的,就使用它,否則,如果use_node_name_as_default為真,這個kernel的節點名稱被用作資源名稱,否則,建立一個專屬於當前程式的名稱
注意,這裡的container和shared_name都是NodeDef的屬性值。
於是就有了如下這個,幫助kernel從ctx->resource_manager()中獲取資源的函式:
Status GetResourceFromContext(OpKernelContext* ctx, const string& input_name, T** resource);
另外,resource_mgr.h還包含了如下的內容:
一個判斷資源是否被初始化的OpKernel
一個用來註冊op的宏,這個op可以生成某種型別的資源控制程式碼
一個用於生成指定資源的控制程式碼的類
一個用於註冊kernel的宏,這個kernel針對的是可以生成某種型別資源控制程式碼的op
原文出處:https://www.cnblogs.com/jicanghai/p/9535504.html
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4822/viewspace-2813233/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- tensorflow原始碼解析之framework-allocator原始碼Framework
- [原始碼解析] TensorFlow 分散式之 ClusterCoordinator原始碼分散式
- [原始碼解析] TensorFlow 分散式之 MirroredStrategy原始碼分散式
- [原始碼解析] TensorFlow 之 分散式變數原始碼分散式變數
- [原始碼解析] TensorFlow 分散式之 ParameterServerStrategy V2原始碼分散式Server
- [原始碼解析] TensorFlow 分散式之 ParameterServerStrategy V1原始碼分散式Server
- [原始碼解析] TensorFlow 分散式 DistributedStrategy 之基礎篇原始碼分散式
- [原始碼解析] TensorFlow 分散式之 MirroredStrategy 分發計算原始碼分散式
- [原始碼解析] TensorFlow 分散式環境(5) --- Session原始碼分散式Session
- [原始碼解析] TensorFlow 分散式環境(4) --- WorkerCache原始碼分散式
- Dubbo原始碼解析之SPI原始碼
- Vue原始碼解析之nextTickVue原始碼
- Flutter之Navigator原始碼解析Flutter原始碼
- Vue原始碼解析之parseVue原始碼
- jQuery原始碼解析之position()jQuery原始碼
- jQuery原始碼解析之clone()jQuery原始碼
- LevelDB 原始碼解析之 Arena原始碼
- Spring原始碼之IOC(一)BeanDefinition原始碼解析Spring原始碼Bean
- Android 原始碼分析之 EventBus 的原始碼解析Android原始碼
- YOLOv3 的 TensorFlow 實現,GitHub 完整原始碼解析YOLOGithub原始碼
- LevelDB 原始碼解析之 Varint 編碼原始碼
- spring 原始碼解析之開篇Spring原始碼
- Java集合之Hashtable原始碼解析Java原始碼
- jQuery原始碼解析之replaceWith()/unwrap()jQuery原始碼
- Java集合之ArrayList原始碼解析Java原始碼
- JDK原始碼解析系列之objectJDK原始碼Object
- Drill-on-YARN之原始碼解析Yarn原始碼
- @angular/forms 原始碼解析之 ValidatorsAngularORM原始碼
- Java集合之LinkedList原始碼解析Java原始碼
- Spring原始碼解析之BeanFactoryPostProcessor(一)Spring原始碼Bean
- Spring原始碼解析之ConfigurationClassPostProcessor(一)Spring原始碼
- Spring原始碼解析之BeanFactoryPostProcessor(三)Spring原始碼Bean
- Spring原始碼解析之ConfigurationClassPostProcessor(二)Spring原始碼
- Spring原始碼解析之ConfigurationClassPostProcessor(三)Spring原始碼
- 【spring原始碼系列】之【xml解析】Spring原始碼XML
- Spring原始碼解析之BeanFactoryPostProcessor(二)Spring原始碼Bean
- [原始碼解析] TensorFlow 分散式環境(8) --- 通訊機制原始碼分散式
- [原始碼解析] TensorFlow 分散式環境(1) --- 總體架構原始碼分散式架構