美文网首页
Caffe 代码学习 4: Layer Factory

Caffe 代码学习 4: Layer Factory

作者: platero | 来源:发表于2016-04-15 14:17 被阅读0次

工厂模式: Layer Factory的设计用到了设计模式里的工厂模式. 我们先来看两个很重要的macro definition. 在宏定义中, #是把参数字符串化,##是连接两个参数成为一个整体 (参考这里). 那么第一个宏定义 REGISTER_LAYER_CLASS实际上是为每一个layer创建一个creator函数.

#define REGISTER_LAYER_CLASS(type)                                             \
  template <typename Dtype>                                                    \
  shared_ptr<Layer<Dtype> > Creator_##type##Layer(const LayerParameter& param) \
  {                                                                            \
    return shared_ptr<Layer<Dtype> >(new type##Layer<Dtype>(param));           \
  }                                                                            \
  REGISTER_LAYER_CREATOR(type, Creator_##type##Layer)

这个函数最后调用了另一个宏定义, REGISTER_LAYER_CREATOR. 我们来看下他是怎么定义的.

#define REGISTER_LAYER_CREATOR(type, creator)                                  \
  static LayerRegisterer<float> g_creator_f_##type(#type, creator<float>);     \
  static LayerRegisterer<double> g_creator_d_##type(#type, creator<double>)    \

以EuclideanLossLayer为例, 在该类的最后, 调用 REGISTER_LAYER_CLASS(EuclideanLoss);来注册这一个类. 通过上面的两个宏定义, 实际上是"创建"了下面的函数.

template <typename Dtype>   
// create一个EuclideanLossLayer对象, 并返回对象指针                                                 
shared_ptr<Layer<Dtype> > Creator_EuclideanLossLayer(const LayerParameter& param) 
{                                                                            
  return shared_ptr<Layer<Dtype> >(new EuclideanLossLayer<Dtype>(param));           
}                                                                                       \
static LayerRegisterer<float> g_creator_f_EuclideanLoss("EuclideanLoss", Creator_EuclideanLossLayer<float>);     
static LayerRegisterer<double> g_creator_d_EuclideanLoss("EuclideanLoss", Creator_EuclideanLossLayer<double>);

LayerRegistry

LayerRegistry里用map数据结构, 维护一个CreatorRegistry list, 保存各个layer的creator的函数句柄: key 是类名, val 是对应的creator函数句柄.

  typedef shared_ptr<Layer<Dtype> > (*Creator)(const LayerParameter&); // 定义类型 Creator为函数句柄
  typedef std::map<string, Creator> CreatorRegistry;  // 定义一个 <LayerName, CreatorHandler>的Creator列表

  static CreatorRegistry& Registry() {
    static CreatorRegistry* g_registry_ = new CreatorRegistry();
    return *g_registry_;
  }  // 只创建一个列表实例

AddCreator函数用来向Registry列表中添加一组<layername, creatorhandlr>

  // Adds a creator.
  static void AddCreator(const string& type, Creator creator) {
    CreatorRegistry& registry = Registry();
    CHECK_EQ(registry.count(type), 0)
        << "Layer type " << type << " already registered.";
    registry[type] = creator;
  }

CreateLayer用于根据输入的LayerParam, 获取当前Layer的layername, 再去registry里通过layername获取对应的creator来创建layer

  // Get a layer using a LayerParameter.
  static shared_ptr<Layer<Dtype> > CreateLayer(const LayerParameter& param) {
    if (Caffe::root_solver()) {
      LOG(INFO) << "Creating layer " << param.name();
    }
    const string& type = param.type();  // 获取layer name
    CreatorRegistry& registry = Registry();
    CHECK_EQ(registry.count(type), 1) << "Unknown layer type: " << type
        << " (known types: " << LayerTypeListString() << ")";
    return registry[type](param);   //  根据layer name, 调用相应creator函数 (registry里存的是函数句柄)
  }

LayerRegisterer

这个类只有一个方法, 即其构造函数. 构造函数只做一件事: 在LayerRegistry的registry list中, 添加一个layer的creator

template <typename Dtype>
class LayerRegisterer {
 public:
  LayerRegisterer(const string& type,
                  shared_ptr<Layer<Dtype> > (*creator)(const LayerParameter&)) {
    // LOG(INFO) << "Registering layer type: " << type;
    LayerRegistry<Dtype>::AddCreator(type, creator);
  }
};

再次总结: 创建一个新layer后, 先写一个静态函数创建并返回该函数的对象 (Creator), 然后创建对应的LayerRegisterer对象, 该对象在构造时会调用 LayerRegistry 中的 AddCreator, 将该layer 注册到 registy中去.

在调用时, xxxxx (补充net, solver 相关内容).

相关文章

网友评论

      本文标题:Caffe 代码学习 4: Layer Factory

      本文链接:https://www.haomeiwen.com/subject/eodnlttx.html