【caffe】模板分离编译模式和工厂模式

本文转自: https://blog.csdn.net/raby_gyl/article/details/68489152 

caffe中的模板分离编译模式和工厂模式
1.caffe中模板分离编译模式的实现方式是在每一个模板源文件的最后添加一条类似于下面的语句:

INSTANTIATE_CLASS(PowerLayer);
该方法属于文献[1]中所说的显示实例化方法。

2.caffe中工厂模式的实现,是通过在每一个模板源文件的最后添加一条类似于下面的语句:

REGISTER_LAYER_CLASS(Power);
其通过全局静态对象利用构造函数的形式,往静态map对象中添加类对象生成信息,如一个string类型的名称和一个创建“名称”类对象的函数。

下面给出具体的引用过程:

power_lay.hpp和power_lay.cpp分别类PowerLayer的声明和实现。

在模板的定义cpp中,即power_lay.cpp中最后:

INSTANTIATE_CLASS(PowerLayer);
REGISTER_LAYER_CLASS(Power);
common.hpp中:

#define INSTANTIATE_CLASS(classname) \
  char gInstantiationGuard##classname; \
  template class classname<float>; \
  template class classname<double>
layer_factory.hpp中,最后

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


例如,对于pow_layer层,调用形式为:

INSTANTIATE_CLASS(PowerLayer);
REGISTER_LAYER_CLASS(Power);
等价于:

char gInstantiationGuardPowerLayer; 
template class PowerLayer<float>; 
template class PowerLayer<double>;

 template <typename Dtype>                                                    
  shared_ptr<Layer<Dtype> > Creator_PowerLayer(const LayerParameter& param) 
  {                                                                            
    return shared_ptr<Layer<Dtype> >(new PowerLayer<Dtype>(param));           
  } 
static LayerRegisterer<float> g_creator_f_Power(“Power”, Creator_PowerLayer<float>);     
static LayerRegisterer<double> g_creator_d_Power(“Power”, Creator_PowerLayer<double>);
其中,LayerRegisterer 类的构造函数声明为:

 LayerRegisterer(const string& type,
                  shared_ptr<Layer<Dtype> > (*creator)(const LayerParameter&)); 
定义为:

template <typename Dtype>
LayerRegisterer<Dtype>::LayerRegisterer(
    const string& type,
    shared_ptr<Layer<Dtype> > (*creator)(const LayerParameter&)) {
  // LOG(INFO) << "Registering layer type: " << type;
  LayerRegistry<Dtype>::AddCreator(type, creator);
}   
AddCreator函数的定义为:

template <typename Dtype>
void LayerRegistry<Dtype>::AddCreator(const string& type, Creator creator) {
  CreatorRegistry& registry = Registry();

  CHECK_EQ(registry.count(type), 0) << "Layer type " << type
                                    << " already registered.";
  registry[type] = creator;

}  
其中:

typedef shared_ptr<Layer<Dtype> > (*Creator)(const LayerParameter&);//函数指针
typedef std::map<string, Creator> CreatorRegistry;  //map
Registry函数为:

template <typename Dtype>
typename LayerRegistry<Dtype>::CreatorRegistry&
LayerRegistry<Dtype>::Registry() {
  static CreatorRegistry* g_registry_ = new CreatorRegistry();
  return *g_registry_;
}
为了理解仿写的测试代码:
person.hpp


#ifndef PERSON_HPP_
#define PERSON_HPP_


#include <string>

using std::string;

struct PersonParameter
{
    string name;
    string type;//student ,teacher,worker
};


template<typename Dtype> class  Person
{
public:
    Person() :name_(""), type_("") {};
    Person(const PersonParameter &pp):name_(pp.name),type_(pp.type){}
    ~Person() {}
    virtual string getName() = 0;
    virtual void setName(string name) = 0;
protected:
    string name_;
    string type_;
};

template<typename Dtype> class Student :public Person<Dtype>
{
public:
    Student(const PersonParameter &pp) :Person(pp) {};
    virtual string getName();
    virtual void setName(string name);
};

template<typename Dtype> class Teacher :public Person<Dtype>

{
public:
    Teacher(const PersonParameter &pp) :Person(pp) {};
    virtual string getName();
    virtual void setName(string name);
};

template<typename Dtype> class Worker :public Person<Dtype>

{
public:
    Worker(const PersonParameter &pp) :Person(pp) {};
    virtual string getName();
    virtual void setName(string name);

};

#endif
person.cpp

#include"person.hpp"
#include"person_factory.hpp"
#include<iostream>
using std::cout;
using std::endl;


template<typename Dtype> string Student<Dtype>::getName()
{
    cout << "Student getName():" << endl;
    return name_;
};

template<typename Dtype> void Student<Dtype>::setName(string name)
{
    cout << "Student setName():" << endl;
    name_ = name;
}

//
template<typename Dtype> string Teacher<Dtype>::getName()
{
    cout << "Teacher getName():" << endl;
    return name_;
};

template<typename Dtype> void Teacher<Dtype>::setName(string name)
{
    cout << "Teacher setName():" << endl;
    name_ = name;
}

//
template<typename Dtype> string Worker<Dtype>::getName()
{
    cout << "Worker getName():" << endl;
    return name_;
};

template<typename Dtype> void Worker<Dtype>::setName(string name)
{
    cout << "Worker setName():" << endl;
    name_ = name;
}


template class Student<float>;
template class Student<double>;

template class Teacher<float>;
template class Teacher<double>;

template class Worker<float>;
template class Worker<double>;


REGISTER_PERSON_CLASS(Student);
REGISTER_PERSON_CLASS(Teacher);
REGISTER_PERSON_CLASS(Worker);

person_factory.hpp


#include"person.hpp"
#include<string>
#include<map>
#include<vector>
#include<iostream>
using namespace std;

template <typename Dtype> class  PersonRegistry
{
public:
    typedef Person<Dtype>* (*Creator)(const PersonParameter&); // 函数指针
    typedef std::map<string, Creator> CreatorRegistry; //存储注册信息

    static CreatorRegistry& Registry();
    static void AddCreator(const string& type, Creator creator);

    // Get a person using a PeronParameter.
    static Person<Dtype>* CreatePerson(const PersonParameter& param);

    static vector<string> PersonTypeList();

private:

    //将构造函数设置为private,不同通过其他方式创建该对象,所有的操作使用静态方法和变量。
    PersonRegistry();
    static string PersonTypeListString();
};

// PersonRegisterer 是PersonRegistry的对外管理接口

template <typename Dtype>
class   PersonRegisterer {
public:
    PersonRegisterer(const string& type,
        Person<Dtype>* (*creator)(const PersonParameter&));
};


// 定义静态对象,静态对象利用其构造函数,将自己的“type”和"creator"添加到静态分配的map对象中。

#define REGISTER_PERSON_CREATOR(type, creator)                                  \
  static PersonRegisterer<float> g_creator_f_##type(#type, creator<float>);     \
  static PersonRegisterer<double> g_creator_d_##type(#type, creator<double>)    \

// REGISTER_PERSON_CLASS 对外调用,每一个PERSON子类实现cpp中调用该宏。
#define REGISTER_PERSON_CLASS(type)                                             \
  template <typename Dtype>                                                    \
  Person<Dtype>*  Creator_##type(const PersonParameter& param) \
  {                                                                            \
    return (new type<Dtype>(param));           \
  }                                                                             \
  REGISTER_PERSON_CREATOR(type, Creator_##type)
person_factory.cpp

#include "person_factory.hpp"


// CreatorRegistry 的实现
template<typename Dtype> typename PersonRegistry<Dtype>::CreatorRegistry & PersonRegistry<Dtype>::Registry()
{
    //静态指针,指向动态申请的内存
    static CreatorRegistry * g_registry_ = new CreatorRegistry();//map<string,Creator>
    return *g_registry_;//返回map<string,Creator>引用

}
// PersonRegisterer的构造函数调用。
template<typename Dtype> void  PersonRegistry<Dtype>::AddCreator(const string &type,Creator creator)
{
    CreatorRegistry& registry = Registry();//动态申请一个map,静态对象不会被创建第二次。
    //检查map<string,Creator>中是否已经注册。
    if (registry.count(type) != 0)
    {
        cerr<< "Person type " << type<< " already registered.";
    }
    //添加键值对,将<type,creator>添加到map中
    registry[type] = creator;
}

template<typename Dtype> Person<Dtype>*  PersonRegistry<Dtype>::CreatePerson(const PersonParameter & param)
{
    //实例化一个对象,如Student ,Worker,Teacher
    const string & type = param.type;
    CreatorRegistry& registry = Registry();
    //检查map中是否存在该类型(如Student ,Worker,Teacher),如果该map找不到,说明我们算法没有实现。
    if (registry.count(type) != 1)
    {
        cerr<< "Unknown Person type: " << type
            << " (known types: " << PersonTypeListString() << ")";
    }
    return registry[type](param); //调用该类型的函数,动态创建改类型的对象。

}

template<typename Dtype>  vector<string> PersonRegistry<Dtype>::PersonTypeList()
{
    CreatorRegistry& registry = Registry();
    //遍历map容器
    vector<string> person_types;
    for (typename CreatorRegistry::iterator iter = registry.begin();
        iter != registry.end(); ++iter) {
        person_types.push_back(iter->first);
    }
    return person_types;
}

template<typename Dtype> string  PersonRegistry<Dtype>::PersonTypeListString()
{
    vector<string> person_types = PersonTypeList();
    string person_types_str;
    //将所有type串联成一个string 返回
    for (vector<string>::iterator iter = person_types.begin();
        iter != person_types.end(); ++iter) {
        if (iter != person_types.begin()) {
            person_types_str += ", ";
        }
        person_types_str += *iter;
    }
    return person_types_str;
}

// LayerRegisterer 类的实现

template <typename Dtype>
PersonRegisterer<Dtype>::PersonRegisterer(
    const string& type,
    Person<Dtype>* (*creator)(const PersonParameter&)) {
    cout << "Registering person type: " << type << endl;
    //调用LayerRigistry类的AddCreator函数增加一个到map
    PersonRegistry<Dtype>::AddCreator(type, creator);
}

// 为了让编译器看到两个模板类:LayerRegisterer,CreatorRegistry

template class PersonRegisterer<float>; //声明
template class PersonRegisterer<double>;

template class PersonRegistry<float>;
template class PersonRegistry<double>;

//上述等价于于下面的caffe中的代码:

//INSTANTIATE_CLASS(LayerRegistry);
//INSTANTIATE_CLASS(LayerRegisterer);

test_template.cpp


#include"stdafx.h"
#include"person.hpp"
#include"person_factory.hpp"

void main()
{
    //registor : map<string,creator>
    PersonRegistry<float>::CreatorRegistry &registor = PersonRegistry<float >::Registry();

    PersonParameter pp;
    pp.type = "Student";
    pp.name = "zhangsan";

    //调用map中Student键对应的ceator函数,创建Student 对象。
    Person<float> *student = registor["Student"](pp);

    cout << student->getName()<< endl;

}

下载地址:

参考文献:

http://blog.csdn.net/k346k346/article/details/49500635 [模板与分离编译模式]

猜你喜欢

转载自blog.csdn.net/piaopiaopiaopiaopiao/article/details/84247334