/**
* @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