Layer_factory.hpp
Layer_factory的主要作用是负责Layer的注册,已经注册完事的Layer在运行时可以通过传递一个 LayerParameter 给 CreaterLayer 函数的方式来调用:
LayerRegistry::CreateLayer(param);//可以参考net.cpp 中的调用方法
假设有一个如下的Layer:
template <typename Dtype>
class MyAwesomeLayer : public Layer<Dtype> {
// your implementations
};
它的type就是C++类名,除去后缀”Layer”:
(“MyAwesomeLayer” -> “MyAwesome”).
我们可以通过以下两种方式来注册一个Layer:
只有一个构造函数
如果这个Layer只能通过它的构造函数来创建的话,在对应的C++文件里面加入以下行就行:
REGISTER_LAYER_CLASS(MyAwesome);
有可选的构造函数
如果这个Layer还可以通过另外一个如下形式的构造函数构造:
template <typename Dtype>
Layer<Dtype*> GetMyAwesomeLayer(const LayerParameter& param) {
// your implementation
}
具体可以参考GetConvolutionLayer,Layer_factory.cpp。
这种情况下,我们可以通过注册构造函数的方式来进行Layer的注册:
REGISTER_LAYER_CREATOR(MyAwesome, GetMyAwesomeLayer)
注意:每一个Layer type 只允许注册一次
具体实现细节可以参考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;
template <typename Dtype>
class LayerRegistry {
public:
typedef shared_ptr<Layer<Dtype> > (*Creator)(const LayerParameter&);
typedef std::map<string, Creator> CreatorRegistry;
static CreatorRegistry& Registry() {
static CreatorRegistry* g_registry_ = new CreatorRegistry();
return *g_registry_;
}
// 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;
}
// Get a layer using a LayerParameter.
static shared_ptr<Layer<Dtype> > CreateLayer(const LayerParameter& param) {
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: " << LayerTypeList() << ")";
return registry[type](param);
}
private:
// Layer registry should never be instantiated - everything is done with its
// static variables.
LayerRegistry() {}
static string 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;
}
return layer_types;
}
};
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_