工厂模式: 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 相关内容).