工廠模式: Layer Factory的設(shè)計(jì)用到了設(shè)計(jì)模式里的工廠模式. 我們先來看兩個(gè)很重要的macro definition. 在宏定義中, #
是把參數(shù)字符串化矩屁,##
是連接兩個(gè)參數(shù)成為一個(gè)整體 (參考這里). 那么第一個(gè)宏定義 REGISTER_LAYER_CLASS
實(shí)際上是為每一個(gè)layer創(chuàng)建一個(gè)creator函數(shù).
#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)
這個(gè)函數(shù)最后調(diào)用了另一個(gè)宏定義, 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為例, 在該類的最后, 調(diào)用 REGISTER_LAYER_CLASS(EuclideanLoss);
來注冊(cè)這一個(gè)類. 通過上面的兩個(gè)宏定義, 實(shí)際上是"創(chuàng)建"了下面的函數(shù).
template <typename Dtype>
// create一個(gè)EuclideanLossLayer對(duì)象, 并返回對(duì)象指針
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數(shù)據(jù)結(jié)構(gòu), 維護(hù)一個(gè)CreatorRegistry list, 保存各個(gè)layer的creator的函數(shù)句柄: key 是類名, val 是對(duì)應(yīng)的creator函數(shù)句柄.
typedef shared_ptr<Layer<Dtype> > (*Creator)(const LayerParameter&); // 定義類型 Creator為函數(shù)句柄
typedef std::map<string, Creator> CreatorRegistry; // 定義一個(gè) <LayerName, CreatorHandler>的Creator列表
static CreatorRegistry& Registry() {
static CreatorRegistry* g_registry_ = new CreatorRegistry();
return *g_registry_;
} // 只創(chuàng)建一個(gè)列表實(shí)例
AddCreator
函數(shù)用來向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
用于根據(jù)輸入的LayerParam, 獲取當(dāng)前Layer的layername, 再去registry里通過layername獲取對(duì)應(yīng)的creator來創(chuàng)建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); // 根據(jù)layer name, 調(diào)用相應(yīng)creator函數(shù) (registry里存的是函數(shù)句柄)
}
LayerRegisterer
這個(gè)類只有一個(gè)方法, 即其構(gòu)造函數(shù). 構(gòu)造函數(shù)只做一件事: 在LayerRegistry的registry list中, 添加一個(gè)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);
}
};
再次總結(jié): 創(chuàng)建一個(gè)新layer后, 先寫一個(gè)靜態(tài)函數(shù)創(chuàng)建并返回該函數(shù)的對(duì)象 (Creator), 然后創(chuàng)建對(duì)應(yīng)的LayerRegisterer
對(duì)象, 該對(duì)象在構(gòu)造時(shí)會(huì)調(diào)用 LayerRegistry 中的 AddCreator
, 將該layer 注冊(cè)到 registy中去.
在調(diào)用時(shí), xxxxx (補(bǔ)充net, solver 相關(guān)內(nèi)容).