layer_factory.hpp/layer_factory.cpp代码解析

/**
 * @brief A layer factory that allows one to register layers.
 * During runtime, registered layers could be called by passing a LayerParameter
 * protobuffer to the CreateLayer function:
 *
 *     LayerRegistry<Dtype>::CreateLayer(param);
 *
 * There are two ways to register a layer. Assuming that we have a layer like:
 *
 *   template <typename Dtype>
 *   class MyAwesomeLayer : public Layer<Dtype> {
 *     // your implementations
 *   };
 *
 * and its type is its C++ class name, but without the "Layer" at the end
 * ("MyAwesomeLayer" -> "MyAwesome").
 *
 * If the layer is going to be created simply by its constructor, in your c++
 * file, add the following line:
 *
 *    REGISTER_LAYER_CLASS(MyAwesome);
 *
 * Or, if the layer is going to be created by another creator function, in the
 * format of:
 *
 *    template <typename Dtype>
 *    Layer<Dtype*> GetMyAwesomeLayer(const LayerParameter& param) {
 *      // your implementation
 *    }
 *
 * (for example, when your layer has multiple backends, see GetConvolutionLayer
 * for a use case), then you can register the creator function instead, like
 *
 * REGISTER_LAYER_CREATOR(MyAwesome, GetMyAwesomeLayer)
 *
 * Note that each layer type should only be registered once.
 */

#ifndef CAFFE_LAYER_FACTORY_H_
#define CAFFE_LAYER_FACTORY_H_

#include <map>
#include <string>
#include <vector>

#include "caffe/common.hpp"
#include "caffe/layer.hpp"
#include "caffe/proto/caffe.pb.h"

namespace caffe {

template <typename Dtype>
class Layer;

template <typename Dtype>
class LayerRegistry {
 public:
  typedef shared_ptr<Layer<Dtype> > (*Creator)(const LayerParameter&);
  typedef std::map<string, Creator> CreatorRegistry;

  /* 创建map<string, Creator>容器,该容器将包含所有layer层描述字符串和对应的Creator函数,
     Creator函数用于实例化对应的layer层,
	 部分网络层的Creator函数是通过REGISTER_LAYER_CLASS宏实现的,
	 如absval、accuracy网络层,对应的Creator函数为:
	 template <typename Dtype>                                                    \
	 shared_ptr<Layer<Dtype> > Creator_##type##Layer(const LayerParameter& param) \
	 {                                                                            \
	 return shared_ptr<Layer<Dtype> >(new type##Layer<Dtype>(param));           \
	 }

	 部分网络层的Creator函数在layer_factory.cpp文件实现的,
	 如Convolution、Pooling层,对应的Creator函数为:
	 GetConvolutionLayer、GetPoolingLayer。

	 以上两种方法都是通过宏REGISTER_LAYER_CREATOR(type, Creator_##type##Layer)进行注册的。
	 该宏会实例化LayerRegisterer<float>,LayerRegisterer<double>类,
	 然后会调用类的构造函数:
	 LayerRegisterer(const string& type, shared_ptr<Layer<Dtype> > (*creator)(const LayerParameter&))
	 {
		LayerRegistry<Dtype>::AddCreator(type, creator);
	 }
	 该构造函数会调用LayerRegistry<Dtype>::AddCreator(type, creator)函数,
	 将网络层type及对应的creator函数添加到map<string, Creator>容器中
	 */
  static CreatorRegistry& Registry() {
    static CreatorRegistry* g_registry_ = new CreatorRegistry();
    return *g_registry_;
  }

  /* 被LayerRegisterer构造函数调用,增加网络层type对应的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;
  }

  /* 被Net<Dtype>::Init函数调用,实例化对应的网络层 */
  static shared_ptr<Layer<Dtype> > CreateLayer(const LayerParameter& param) {
    if (Caffe::root_solver()) {
      LOG(INFO) << "Creating layer " << param.name();
    }
    const string& type = param.type();
    CreatorRegistry& registry = Registry();
    CHECK_EQ(registry.count(type), 1) << "Unknown layer type: " << type
        << " (known types: " << LayerTypeListString() << ")";
    return registry[type](param);
  }

  /* 将所有的网络层type存放在vector<string>中,被LayerTypeListString调用 */
  static vector<string> LayerTypeList() {
    CreatorRegistry& registry = Registry();
    vector<string> layer_types;
    for (typename CreatorRegistry::iterator iter = registry.begin();
         iter != registry.end(); ++iter) {
      layer_types.push_back(iter->first);
    }
    return layer_types;
  }

 private:
  // Layer registry should never be instantiated - everything is done with its
  // static variables.
  LayerRegistry() {}

  /* 将所有的网络层type转化为字符串string, CreateLayer调用 */
  static string LayerTypeListString() {
    vector<string> layer_types = LayerTypeList();
    string layer_types_str;
    for (vector<string>::iterator iter = layer_types.begin();
         iter != layer_types.end(); ++iter) {
      if (iter != layer_types.begin()) {
        layer_types_str += ", ";
      }
      layer_types_str += *iter;
    }
    return layer_types_str;
  }
};


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);
  }
};


#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>)    \

#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)

}  // namespace caffe

#endif  // CAFFE_LAYER_FACTORY_H_

--------------------------------------------------------------------------------------------------------------------------------

layer_factory.hpp中Registry()函数重复调用,g_registry_空间是否会从新分配。

static CreatorRegistry& Registry() {
    static CreatorRegistry* g_registry_ = new CreatorRegistry();
    return *g_registry_;
  }

验证代码:

#include "stdio.h"

class test
{
public:

	static int& Registry()
	{
		static int* g_registry_ = new int();
		printf("address:%p\n", g_registry_);
		return *g_registry_;
	}
};

int main()
{
	printf("hello world\n");
	int& i =  test::Registry();
	int& j =  test::Registry();
	
	return 0;
}

地址打印相同,证明g_registry_不会从新分配,静态变量只在第一次new时分配空间。

-------------------------------------------------------------------------------------------------------------------------------------------

absval_layer.cpp

宏展开方法:
g++ -E -o cc.i src/caffe/layers/absval_layer.cpp -MMD -MP -pthread -fPIC -DCAFFE_VERSION=1.0.0 -DDEBUG -g -O0 -DUSE_CUDNN -DUSE_OPENCV -DUSE_LEVELDB -DUSE_LMDB -DWITH_PYTHON_LAYER -I/usr/include/python2.7 -I/usr/local/lib/python2.7/dist-packages/numpy/core/include -I/usr/local/include -I/usr/include/hdf5/serial -I.build_debug/src -I./src -I./include -I/usr/local/cuda/include -Wall -Wno-sign-compare

1: 
INSTANTIATE_CLASS(AbsValLayer);展开得:
char gInstantiationGuardAbsValLayer; 
template class AbsValLayer<float>; 
template class AbsValLayer<double>;
作用是模板具化,具化类:AbsValLayer<float>和AbsValLayer<double>


REGISTER_LAYER_CLASS(AbsVal);展开得:
/* 实例化AbsValLayer<Dtype>网络层 */
template <typename Dtype> shared_ptr<Layer<Dtype> > Creator_AbsValLayer(const LayerParameter& param) 
{
    return shared_ptr<Layer<Dtype> >(new AbsValLayer<Dtype>(param));
}
/* 网络层注册 */
static LayerRegisterer<float> g_creator_f_AbsVal("AbsVal", Creator_AbsValLayer<float>); 
static LayerRegisterer<double> g_creator_d_AbsVal("AbsVal", Creator_AbsValLayer<double>);

g_creator_f_AbsVal和g_creator_d_AbsVal实例化,会调用构造函数:
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);
    }
};
这时就将网络层AbsVal和Creator_AbsValLayer<float>加入到map容器中

另外有些网络层之间在layer_factory.cpp中使用宏:
#define REGISTER_LAYER_CREATOR(type, creator)注册
如卷基层、池化层等:
REGISTER_LAYER_CREATOR(Convolution, GetConvolutionLayer);
REGISTER_LAYER_CREATOR(Pooling, GetPoolingLayer);

综上,有两类网络层注册方式,分别为:
REGISTER_LAYER_CLASS(AbsVal)和REGISTER_LAYER_CREATOR(Pooling, GetPoolingLayer);
底层都使用了宏和REGISTER_LAYER_CREATOR
 

猜你喜欢

转载自blog.csdn.net/piaopiaopiaopiaopiao/article/details/84823327
今日推荐