# The target shared library and static library name
LIB_BUILD_DIR := $(BUILD_DIR)/lib
NAME := $(LIB_BUILD_DIR)/lib$(PROJECT).so
-STATIC_NAME := $(LIB_BUILD_DIR)/lib$(PROJECT).a
##############################
# Get all source files
py mat py$(PROJECT) mat$(PROJECT) proto runtest \
superclean supercleanlist supercleanfiles warn everything
-all: $(NAME) $(STATIC_NAME) tools examples
+all: $(NAME) tools examples
everything: all py$(PROJECT) mat$(PROJECT) test warn lint runtest
py: $(PY$(PROJECT)_SO) $(PROTO_GEN_PY)
-$(PY$(PROJECT)_SO): $(STATIC_NAME) $(PY$(PROJECT)_SRC) $(PY$(PROJECT)_HXX_SRC)
+$(PY$(PROJECT)_SO): $(OBJS) $(PY$(PROJECT)_SRC) $(PY$(PROJECT)_HXX_SRC)
$(CXX) -shared -o $@ $(PY$(PROJECT)_SRC) \
- $(STATIC_NAME) $(LINKFLAGS) $(PYTHON_LDFLAGS)
+ $(OBJS) $(LINKFLAGS) $(PYTHON_LDFLAGS)
@ echo
mat$(PROJECT): mat
mat: $(MAT$(PROJECT)_SO)
-$(MAT$(PROJECT)_SO): $(MAT$(PROJECT)_SRC) $(STATIC_NAME)
+$(MAT$(PROJECT)_SO): $(MAT$(PROJECT)_SRC) $(OBJS)
@ if [ -z "$(MATLAB_DIR)" ]; then \
echo "MATLAB_DIR must be specified in $(CONFIG_FILE)" \
"to build mat$(PROJECT)."; \
$(MATLAB_DIR)/bin/mex $(MAT$(PROJECT)_SRC) \
CXX="$(CXX)" \
CXXFLAGS="\$$CXXFLAGS $(MATLAB_CXXFLAGS)" \
- CXXLIBS="\$$CXXLIBS $(STATIC_NAME) $(LDFLAGS)" -output $@
+ CXXLIBS="\$$CXXLIBS $(OBJS) $(LDFLAGS)" -output $@
@ echo
runtest: $(TEST_ALL_BIN)
$(ALL_BUILD_DIRS): | $(BUILD_DIR_LINK)
@ mkdir -p $@
-$(NAME): $(PROTO_OBJS) $(OBJS) | $(LIB_BUILD_DIR)
+$(NAME): $(OBJS) | $(LIB_BUILD_DIR)
$(CXX) -shared -o $@ $(OBJS) $(LINKFLAGS) $(LDFLAGS)
@ echo
-$(STATIC_NAME): $(PROTO_OBJS) $(OBJS) | $(LIB_BUILD_DIR)
- ar rcs $@ $(PROTO_OBJS) $(OBJS)
- @ echo
-
$(TEST_BUILD_DIR)/%.o: src/$(PROJECT)/test/%.cpp $(HXX_SRCS) $(TEST_HXX_SRCS) \
| $(TEST_BUILD_DIR)
$(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \
@ cat $@.$(WARNS_EXT)
@ echo
-$(TEST_ALL_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(STATIC_NAME) \
+$(TEST_ALL_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(OBJS) \
| $(TEST_BIN_DIR)
- $(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(STATIC_NAME) \
+ $(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(OBJS) \
-o $@ $(LINKFLAGS) $(LDFLAGS)
@ echo
-$(TEST_CU_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_BUILD_DIR)/%.cuo $(GTEST_OBJ) $(STATIC_NAME) \
+$(TEST_CU_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_BUILD_DIR)/%.cuo $(GTEST_OBJ) $(OBJS) \
| $(TEST_BIN_DIR)
- $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(STATIC_NAME) \
+ $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(OBJS) \
-o $@ $(LINKFLAGS) $(LDFLAGS)
@ echo
-$(TEST_CXX_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_BUILD_DIR)/%.o $(GTEST_OBJ) $(STATIC_NAME) \
+$(TEST_CXX_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_BUILD_DIR)/%.o $(GTEST_OBJ) $(OBJS) \
| $(TEST_BIN_DIR)
- $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(STATIC_NAME) \
+ $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(OBJS) \
-o $@ $(LINKFLAGS) $(LDFLAGS)
@ echo
@ $(RM) $@
@ ln -s $(abspath $<) $@
-$(TOOL_BINS): %.bin : %.o $(STATIC_NAME)
- $(CXX) $< $(STATIC_NAME) -o $@ $(LINKFLAGS) $(LDFLAGS)
+$(TOOL_BINS): %.bin : %.o $(OBJS)
+ $(CXX) $< $(OBJS) -o $@ $(LINKFLAGS) $(LDFLAGS)
@ echo
-$(EXAMPLE_BINS): %.bin : %.o $(STATIC_NAME)
- $(CXX) $< $(STATIC_NAME) -o $@ $(LINKFLAGS) $(LDFLAGS)
+$(EXAMPLE_BINS): %.bin : %.o $(OBJS)
+ $(CXX) $< $(OBJS) -o $@ $(LINKFLAGS) $(LDFLAGS)
@ echo
$(LAYER_BUILD_DIR)/%.o: src/$(PROJECT)/layers/%.cpp $(HXX_SRCS) \
cp $(EXAMPLE_BINS) $(DISTRIBUTE_DIR)/bin
# add libraries
cp $(NAME) $(DISTRIBUTE_DIR)/lib
- cp $(STATIC_NAME) $(DISTRIBUTE_DIR)/lib
# add python - it's not the standard way, indeed...
cp -r python $(DISTRIBUTE_DIR)/python
--- /dev/null
+#ifndef CAFFE_LAYER_FACTORY_H_
+#define CAFFE_LAYER_FACTORY_H_
+
+#include <map>
+
+#include "caffe/common.hpp"
+#include "caffe/proto/caffe.pb.h"
+
+namespace caffe {
+
+template <typename Dtype>
+class Layer;
+
+template <typename Dtype>
+class LayerRegistry {
+ public:
+ typedef Layer<Dtype>* (*Creator)(const LayerParameter&);
+ typedef std::map<LayerParameter_LayerType, Creator> CreatorRegistry;
+
+ // Adds a creator.
+ static void AddCreator(const LayerParameter_LayerType& type,
+ Creator creator) {
+ CHECK_EQ(registry_.count(type), 0)
+ << "Layer type " << type << " already registered.";
+ registry_[type] = creator;
+ }
+
+ // Get a layer using a LayerParameter.
+ static Layer<Dtype>* CreateLayer(const LayerParameter& param) {
+ LOG(INFO) << "Creating layer " << param.name();
+ const LayerParameter_LayerType& type = param.type();
+ CHECK_EQ(registry_.count(type), 1);
+ return registry_[type](param);
+ }
+
+ private:
+ // Layer registry should never be instantiated - everything is done with its
+ // static variables.
+ LayerRegistry() {}
+ static CreatorRegistry registry_;
+};
+
+// Static variables for the templated layer factory registry.
+template <typename Dtype>
+typename LayerRegistry<Dtype>::CreatorRegistry LayerRegistry<Dtype>::registry_;
+
+template <typename Dtype>
+class LayerRegisterer {
+ public:
+ LayerRegisterer(const LayerParameter_LayerType& type,
+ Layer<Dtype>* (*creator)(const LayerParameter&)) {
+ LOG(INFO) << "Registering layer type: " << type;
+ LayerRegistry<Dtype>::AddCreator(type, creator);
+ }
+};
+
+
+#define REGISTER_LAYER_CREATOR(type, creator, classname) \
+ static LayerRegisterer<float> g_creator_f_##classname(type, creator<float>); \
+ static LayerRegisterer<double> g_creator_d_##classname(type, creator<double>)
+
+#define REGISTER_LAYER_CLASS(type, clsname) \
+ template <typename Dtype> \
+ Layer<Dtype>* Creator_##clsname(const LayerParameter& param) { \
+ return new clsname<Dtype>(param); \
+ } \
+ static LayerRegisterer<float> g_creator_f_##clsname( \
+ type, Creator_##clsname<float>); \
+ static LayerRegisterer<double> g_creator_d_##clsname( \
+ type, Creator_##clsname<double>)
+
+// A function to get a specific layer from the specification given in
+// LayerParameter. Ideally this would be replaced by a factory pattern,
+// but we will leave it this way for now.
+// Yangqing's note: With LayerRegistry, we no longer need this thin wrapper any
+// more. It is provided here for backward compatibility and should be removed in
+// the future.
+template <typename Dtype>
+Layer<Dtype>* GetLayer(const LayerParameter& param) {
+ return LayerRegistry<Dtype>::CreateLayer(param);
+}
+
+} // namespace caffe
+
+#endif // CAFFE_LAYER_FACTORY_H_
#include <string>
#include "caffe/layer.hpp"
+#include "caffe/layer_factory.hpp"
#include "caffe/proto/caffe.pb.h"
#include "caffe/vision_layers.hpp"
// Get convolution layer according to engine.
template <typename Dtype>
-ConvolutionLayer<Dtype>* GetConvolutionLayer(const string& name,
+Layer<Dtype>* GetConvolutionLayer(
const LayerParameter& param) {
ConvolutionParameter_Engine engine = param.convolution_param().engine();
if (engine == ConvolutionParameter_Engine_DEFAULT) {
return new CuDNNConvolutionLayer<Dtype>(param);
#endif
} else {
- LOG(FATAL) << "Layer " << name << " has unknown engine.";
+ LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
}
}
-template ConvolutionLayer<float>* GetConvolutionLayer(const string& name,
- const LayerParameter& param);
-template ConvolutionLayer<double>* GetConvolutionLayer(const string& name,
- const LayerParameter& param);
-
// Get pooling layer according to engine.
template <typename Dtype>
-PoolingLayer<Dtype>* GetPoolingLayer(const string& name,
- const LayerParameter& param) {
- const PoolingParameter& p_param = param.pooling_param();
- PoolingParameter_Engine engine = p_param.engine();
+Layer<Dtype>* GetPoolingLayer(const LayerParameter& param) {
+ PoolingParameter_Engine engine = param.pooling_param().engine();
if (engine == PoolingParameter_Engine_DEFAULT) {
engine = PoolingParameter_Engine_CAFFE;
#ifdef USE_CUDNN
return new CuDNNPoolingLayer<Dtype>(param);
#endif
} else {
- LOG(FATAL) << "Layer " << name << " has unknown engine.";
+ LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
}
}
-template PoolingLayer<float>* GetPoolingLayer(const string& name,
- const LayerParameter& param);
-template PoolingLayer<double>* GetPoolingLayer(const string& name,
- const LayerParameter& param);
-
// Get relu layer according to engine.
template <typename Dtype>
-ReLULayer<Dtype>* GetReLULayer(const string& name,
- const LayerParameter& param) {
+Layer<Dtype>* GetReLULayer(const LayerParameter& param) {
ReLUParameter_Engine engine = param.relu_param().engine();
if (engine == ReLUParameter_Engine_DEFAULT) {
engine = ReLUParameter_Engine_CAFFE;
return new CuDNNReLULayer<Dtype>(param);
#endif
} else {
- LOG(FATAL) << "Layer " << name << " has unknown engine.";
+ LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
}
}
-template ReLULayer<float>* GetReLULayer(const string& name,
- const LayerParameter& param);
-template ReLULayer<double>* GetReLULayer(const string& name,
- const LayerParameter& param);
-
// Get sigmoid layer according to engine.
template <typename Dtype>
-SigmoidLayer<Dtype>* GetSigmoidLayer(const string& name,
- const LayerParameter& param) {
+Layer<Dtype>* GetSigmoidLayer(const LayerParameter& param) {
SigmoidParameter_Engine engine = param.sigmoid_param().engine();
if (engine == SigmoidParameter_Engine_DEFAULT) {
engine = SigmoidParameter_Engine_CAFFE;
return new CuDNNSigmoidLayer<Dtype>(param);
#endif
} else {
- LOG(FATAL) << "Layer " << name << " has unknown engine.";
+ LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
}
}
-template SigmoidLayer<float>* GetSigmoidLayer(const string& name,
- const LayerParameter& param);
-template SigmoidLayer<double>* GetSigmoidLayer(const string& name,
- const LayerParameter& param);
-
// Get tanh layer according to engine.
template <typename Dtype>
-TanHLayer<Dtype>* GetTanHLayer(const string& name,
- const LayerParameter& param) {
+Layer<Dtype>* GetTanHLayer(const LayerParameter& param) {
TanHParameter_Engine engine = param.tanh_param().engine();
if (engine == TanHParameter_Engine_DEFAULT) {
engine = TanHParameter_Engine_CAFFE;
return new CuDNNTanHLayer<Dtype>(param);
#endif
} else {
- LOG(FATAL) << "Layer " << name << " has unknown engine.";
+ LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
}
}
-template TanHLayer<float>* GetTanHLayer(const string& name,
- const LayerParameter& param);
-template TanHLayer<double>* GetTanHLayer(const string& name,
- const LayerParameter& param);
-
// Get softmax layer according to engine.
template <typename Dtype>
-SoftmaxLayer<Dtype>* GetSoftmaxLayer(const string& name,
- const LayerParameter& param) {
+Layer<Dtype>* GetSoftmaxLayer(const LayerParameter& param) {
SoftmaxParameter_Engine engine = param.softmax_param().engine();
if (engine == SoftmaxParameter_Engine_DEFAULT) {
engine = SoftmaxParameter_Engine_CAFFE;
return new CuDNNSoftmaxLayer<Dtype>(param);
#endif
} else {
- LOG(FATAL) << "Layer " << name << " has unknown engine.";
- }
-}
-
-template SoftmaxLayer<float>* GetSoftmaxLayer(const string& name,
- const LayerParameter& param);
-template SoftmaxLayer<double>* GetSoftmaxLayer(const string& name,
- const LayerParameter& param);
-
-// A function to get a specific layer from the specification given in
-// LayerParameter. Ideally this would be replaced by a factory pattern,
-// but we will leave it this way for now.
-template <typename Dtype>
-Layer<Dtype>* GetLayer(const LayerParameter& param) {
- const string& name = param.name();
- const LayerParameter_LayerType& type = param.type();
- switch (type) {
- case LayerParameter_LayerType_ACCURACY:
- return new AccuracyLayer<Dtype>(param);
- case LayerParameter_LayerType_ABSVAL:
- return new AbsValLayer<Dtype>(param);
- case LayerParameter_LayerType_ARGMAX:
- return new ArgMaxLayer<Dtype>(param);
- case LayerParameter_LayerType_BNLL:
- return new BNLLLayer<Dtype>(param);
- case LayerParameter_LayerType_CONCAT:
- return new ConcatLayer<Dtype>(param);
- case LayerParameter_LayerType_CONTRASTIVE_LOSS:
- return new ContrastiveLossLayer<Dtype>(param);
- case LayerParameter_LayerType_CONVOLUTION:
- return GetConvolutionLayer<Dtype>(name, param);
- case LayerParameter_LayerType_DATA:
- return new DataLayer<Dtype>(param);
- case LayerParameter_LayerType_DROPOUT:
- return new DropoutLayer<Dtype>(param);
- case LayerParameter_LayerType_DUMMY_DATA:
- return new DummyDataLayer<Dtype>(param);
- case LayerParameter_LayerType_EUCLIDEAN_LOSS:
- return new EuclideanLossLayer<Dtype>(param);
- case LayerParameter_LayerType_ELTWISE:
- return new EltwiseLayer<Dtype>(param);
- case LayerParameter_LayerType_FLATTEN:
- return new FlattenLayer<Dtype>(param);
- case LayerParameter_LayerType_HDF5_DATA:
- return new HDF5DataLayer<Dtype>(param);
- case LayerParameter_LayerType_HDF5_OUTPUT:
- return new HDF5OutputLayer<Dtype>(param);
- case LayerParameter_LayerType_HINGE_LOSS:
- return new HingeLossLayer<Dtype>(param);
- case LayerParameter_LayerType_IMAGE_DATA:
- return new ImageDataLayer<Dtype>(param);
- case LayerParameter_LayerType_IM2COL:
- return new Im2colLayer<Dtype>(param);
- case LayerParameter_LayerType_INFOGAIN_LOSS:
- return new InfogainLossLayer<Dtype>(param);
- case LayerParameter_LayerType_INNER_PRODUCT:
- return new InnerProductLayer<Dtype>(param);
- case LayerParameter_LayerType_LRN:
- return new LRNLayer<Dtype>(param);
- case LayerParameter_LayerType_MEMORY_DATA:
- return new MemoryDataLayer<Dtype>(param);
- case LayerParameter_LayerType_MVN:
- return new MVNLayer<Dtype>(param);
- case LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS:
- return new MultinomialLogisticLossLayer<Dtype>(param);
- case LayerParameter_LayerType_POOLING:
- return GetPoolingLayer<Dtype>(name, param);
- case LayerParameter_LayerType_POWER:
- return new PowerLayer<Dtype>(param);
- case LayerParameter_LayerType_RELU:
- return GetReLULayer<Dtype>(name, param);
- case LayerParameter_LayerType_SILENCE:
- return new SilenceLayer<Dtype>(param);
- case LayerParameter_LayerType_SIGMOID:
- return GetSigmoidLayer<Dtype>(name, param);
- case LayerParameter_LayerType_SIGMOID_CROSS_ENTROPY_LOSS:
- return new SigmoidCrossEntropyLossLayer<Dtype>(param);
- case LayerParameter_LayerType_SLICE:
- return new SliceLayer<Dtype>(param);
- case LayerParameter_LayerType_SOFTMAX:
- return GetSoftmaxLayer<Dtype>(name, param);
- case LayerParameter_LayerType_SOFTMAX_LOSS:
- return new SoftmaxWithLossLayer<Dtype>(param);
- case LayerParameter_LayerType_SPLIT:
- return new SplitLayer<Dtype>(param);
- case LayerParameter_LayerType_TANH:
- return GetTanHLayer<Dtype>(name, param);
- case LayerParameter_LayerType_WINDOW_DATA:
- return new WindowDataLayer<Dtype>(param);
- case LayerParameter_LayerType_THRESHOLD:
- return new ThresholdLayer<Dtype>(param);
- case LayerParameter_LayerType_NONE:
- LOG(FATAL) << "Layer " << name << " has unspecified type.";
- default:
- LOG(FATAL) << "Layer " << name << " has unknown type " << type;
+ LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
}
- // just to suppress old compiler warnings.
- return (Layer<Dtype>*)(NULL);
}
-template Layer<float>* GetLayer(const LayerParameter& param);
-template Layer<double>* GetLayer(const LayerParameter& param);
+// Layers that have a specific creator function.
+REGISTER_LAYER_CREATOR(LayerParameter_LayerType_CONVOLUTION,
+ GetConvolutionLayer, ConvolutionLayer);
+REGISTER_LAYER_CREATOR(LayerParameter_LayerType_POOLING,
+ GetPoolingLayer, PoolingLayer);
+REGISTER_LAYER_CREATOR(LayerParameter_LayerType_RELU,
+ GetReLULayer, ReLULayer);
+REGISTER_LAYER_CREATOR(LayerParameter_LayerType_SIGMOID,
+ GetSigmoidLayer, SigmoidLayer);
+REGISTER_LAYER_CREATOR(LayerParameter_LayerType_SOFTMAX,
+ GetSoftmaxLayer, SoftmaxLayer);
+REGISTER_LAYER_CREATOR(LayerParameter_LayerType_TANH,
+ GetTanHLayer, TanHLayer);
+// Layers that use their constructor as their default creator.
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_ACCURACY, AccuracyLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_ABSVAL, AbsValLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_ARGMAX, ArgMaxLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_BNLL, BNLLLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_CONCAT, ConcatLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_CONTRASTIVE_LOSS,
+ ContrastiveLossLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_DATA, DataLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_DROPOUT, DropoutLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_DUMMY_DATA, DummyDataLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_EUCLIDEAN_LOSS,
+ EuclideanLossLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_ELTWISE, EltwiseLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_FLATTEN, FlattenLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_HDF5_DATA, HDF5DataLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_HDF5_OUTPUT, HDF5OutputLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_HINGE_LOSS, HingeLossLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_IMAGE_DATA, ImageDataLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_IM2COL, Im2colLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_INFOGAIN_LOSS, InfogainLossLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_INNER_PRODUCT, InnerProductLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_LRN, LRNLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_MEMORY_DATA, MemoryDataLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_MVN, MVNLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS,
+ MultinomialLogisticLossLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_POWER, PowerLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_SILENCE, SilenceLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_SIGMOID_CROSS_ENTROPY_LOSS,
+ SigmoidCrossEntropyLossLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_SLICE, SliceLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_SOFTMAX_LOSS,
+ SoftmaxWithLossLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_SPLIT, SplitLayer);
+REGISTER_LAYER_CLASS(LayerParameter_LayerType_WINDOW_DATA, WindowDataLayer);
} // namespace caffe