Caffe中Layer注册机制

来源:互联网 发布:腾讯云域名建站教程 编辑:程序博客网 时间:2024/06/05 10:49

 

        Caffe内部维护一个注册表用于查找特定Layer对应的工厂函数,(Layer Factory的设计用到了设计模式里的工厂模式)。Caffe的Layer注册表是一组键值对(key, value)( LayerRegistry里用map数据结构维护一个CreatorRegistry list, 保存各个Layer的creator的函数句柄),key为Layer的类型(Layer类名去掉后面的”Layer”字符串),value为其对应的工厂函数(creator的函数句柄),注册表类型为CreatorRegistry,实际类型为std::map。可以通过Registry 函数获取注册表的全局单例。而注册的过程就是一个map操作

       Caffe是通过宏定义的方式注册各种Layer,在编译阶段自动执行宏替换就注册了所有的Layer. 每一个Layer type只允许注册一次。使用两组宏来控制Layer的注册.:

#define REGISTER_LAYER_CREATOR(type, creator)                                  \
  LayerRegisterer<float> g_creator_f_##type(#type, creator<float>);     \
  LayerRegisterer<double> g_creator_d_##type(#type, creator<double>)    \
 
#define REGISTER_LAYER_CLASS(type)                                             \
  template <typename dtype="">                                                    \
  shared_ptr<layer<dtype> > Creator_##type##Layer(constLayerParameter& param) \
  {                                                                            \
    returnshared_ptr<layer<dtype> >(newtype##Layer<dtype>(param));           \
  }                                                                            \
  REGISTER_LAYER_CREATOR(type, Creator_##type##Layer)</dtype></layer<dtype></layer<dtype></typename></double></double></float></float>

      REGISTER_LAYER_CLASS宏可以实现将指定Layer注册到全局注册表中,首先定义一个工厂函数用来产生Layer对象,然后调用REGISTER_LAYER_CREATOR将工厂函数和Layer的类型名进行注册,支持两种Layer的数据类型,float和double。两个变量一个对应float,一个对应double,这两个变量的初始化,也就是它们的构造函数实际上完成Layer的注册动作。REGISTER_LAYER_CLASS实际上是为每一个Layer创建一个creator函数.

     LayerRegisterer对象初始化时(会调用LayerRegisterer类构造函数)实际上又是调用LayerRegistry类的静态方法 AddCreator函数。


以下是对Caffe code中layer_factory.hpp文件的注释:

#ifndef CAFFE_LAYER_FACTORY_H_
#define CAFFE_LAYER_FACTORY_H_
 
#include<map>
#include <string>
 
#include "caffe/common.hpp"
#include "caffe/proto/caffe.pb.h"
 
namespace caffe {
 
template <typename dtype="">
class Layer;
 
// LayerRegistry:注册类,将每一个Layer的type(std::string)和对应的creator(函数指针)存放到一个map中
template <typename dtype="">
class LayerRegistry {
 public:
  // LayerRegistry里用map数据结构, 维护一个CreatorRegistry list, 保存各个layer的creator的函数句柄
  typedef shared_ptr<layer<dtype> > (*Creator)(constLayerParameter&); // 函数指针,返回Layer<dtype>类型的指针
  typedef std::map<string, creator=""> CreatorRegistry;
 
  // 获取注册表,内部注册表,静态函数,仅第一次调用时会new,其它直接return
  staticCreatorRegistry& Registry() { // 只创建一个map实例
    // 全局静态变量(map实例)
    staticCreatorRegistry* g_registry_ = newCreatorRegistry();
    return*g_registry_;
  }
 
  // Adds a creator.
  // AddCreator函数用来向Registry列表中添加一组<type, creator="">
  // 向map中加入一个映射
  staticvoid AddCreator(conststring& type, Creator creator) {
    CreatorRegistry& registry = Registry();
    CHECK_EQ(registry.count(type),0)
        <<"Layer type " << type <<" already registered.";
    registry[type] = creator;
  }
 
  // Get a layer using a LayerParameter.
  // 在net.cpp中会被调用,在初始化整个网络的时候会根据参数文件中的层的类型去创建该层的实例
  staticshared_ptr<layer<dtype> > CreateLayer(constLayerParameter& param) {
    if(Caffe::root_solver()) {
      LOG(INFO) <<"Creating layer " << param.name();
    }
    conststring& type = param.type(); // 从LayerParameter中获得字符串type
    CreatorRegistry& registry = Registry();// 获取注册表指针
    // 验证是否查找到给定type的creator
    CHECK_EQ(registry.count(type),1) << "Unknown layer type: "<< type
        <<" (known types: " << LayerTypeList() << ")";
    returnregistry[type](param); // 根据layer name, 调用相应creator函数
  }
 
 private:
  // Layer registry should never be instantiated - everything is done with its
  // static variables.
  // 禁止实例化
  LayerRegistry() {}
 
  // 返回layer type
  staticstring LayerTypeList() {
    CreatorRegistry& registry = Registry();// 获取注册表指针
    string layer_types;
    // 遍历注册表
    for(typename CreatorRegistry::iterator iter = registry.begin();
         iter != registry.end(); ++iter) {
      if(iter != registry.begin()) {
        layer_types +=", ";
      }
      layer_types += iter->first;
    }
    returnlayer_types;
  }
};
 
// LayerRegisterer:Layer注册器,供后面的宏使用
template <typename dtype="">
classLayerRegisterer {
 public:
  // 向LayerRegistry的registry list中, 添加一个layer的creator
  LayerRegisterer(conststring& type,
                  shared_ptr<layer<dtype> > (*creator)(constLayerParameter&)) {
    // LOG(INFO) << "Registering layer type: " << type;
    LayerRegistry<dtype>::AddCreator(type, creator);
  }
};
 
// 通过宏定义注册各种Layer
// 将创建layer对象的函数指针加入map
#define REGISTER_LAYER_CREATOR(type, creator)                                  \
  LayerRegisterer<float> g_creator_f_##type(#type, creator<float>);     \
  LayerRegisterer<double> g_creator_d_##type(#type, creator<double>)    \
 
#define REGISTER_LAYER_CLASS(type)                                             \
  template <typename dtype="">                                                    \
  shared_ptr<layer<dtype> > Creator_##type##Layer(constLayerParameter& param) \
  {                                                                            \
    returnshared_ptr<layer<dtype> >(newtype##Layer<dtype>(param));           \
  }                                                                            \
  REGISTER_LAYER_CREATOR(type, Creator_##type##Layer)
 
// namespace caffe
 
#endif  // CAFFE_LAYER_FACTORY_H_
</dtype></layer<dtype></layer<dtype></typename></double></double></float></float></dtype></layer<dtype></typename></layer<dtype></type,></string,></dtype></layer<dtype></typename></typename></string></map></dtype*></typename></dtype></typename></dtype>