1 // Make sure we include Python.h before any system header
2 // to avoid _POSIX_C_SOURCE redefinition
3 #ifdef WITH_PYTHON_LAYER
4 #include <boost/python.hpp>
8 #include "caffe/layer.hpp"
9 #include "caffe/layer_factory.hpp"
10 #include "caffe/layers/conv_layer.hpp"
11 #include "caffe/layers/lrn_layer.hpp"
12 #include "caffe/layers/pooling_layer.hpp"
13 #include "caffe/layers/relu_layer.hpp"
14 #include "caffe/layers/sigmoid_layer.hpp"
15 #include "caffe/layers/softmax_layer.hpp"
16 #include "caffe/layers/tanh_layer.hpp"
17 #include "caffe/proto/caffe.pb.h"
20 #include "caffe/layers/cudnn_conv_layer.hpp"
21 #include "caffe/layers/cudnn_lcn_layer.hpp"
22 #include "caffe/layers/cudnn_lrn_layer.hpp"
23 #include "caffe/layers/cudnn_pooling_layer.hpp"
24 #include "caffe/layers/cudnn_relu_layer.hpp"
25 #include "caffe/layers/cudnn_sigmoid_layer.hpp"
26 #include "caffe/layers/cudnn_softmax_layer.hpp"
27 #include "caffe/layers/cudnn_tanh_layer.hpp"
31 #include "caffe/layers/acl_absval_layer.hpp"
32 #include "caffe/layers/acl_bnll_layer.hpp"
33 #include "caffe/layers/acl_conv_layer.hpp"
34 #include "caffe/layers/acl_inner_product_layer.hpp"
35 #include "caffe/layers/acl_lrn_layer.hpp"
36 #include "caffe/layers/acl_pooling_layer.hpp"
37 #include "caffe/layers/acl_relu_layer.hpp"
38 #include "caffe/layers/acl_sigmoid_layer.hpp"
39 #include "caffe/layers/acl_softmax_layer.hpp"
40 #include "caffe/layers/acl_tanh_layer.hpp"
41 #include "caffe/layers/acl_local_connect_layer.hpp"
42 #include "caffe/layers/acl_batch_norm_layer.hpp"
43 #include "caffe/layers/acl_concat_layer.hpp"
46 #ifdef WITH_PYTHON_LAYER
47 #include "caffe/layers/python_layer.hpp"
52 // Get convolution layer according to engine.
53 template <typename Dtype>
54 shared_ptr<Layer<Dtype> > GetConvolutionLayer(
55 const LayerParameter& param) {
56 ConvolutionParameter conv_param = param.convolution_param();
57 ConvolutionParameter_Engine engine = conv_param.engine();
59 return GetACLConvolutionLayer<Dtype>(param);
62 bool use_dilation = false;
63 for (int i = 0; i < conv_param.dilation_size(); ++i) {
64 if (conv_param.dilation(i) > 1) {
69 if (engine == ConvolutionParameter_Engine_DEFAULT) {
70 engine = ConvolutionParameter_Engine_CAFFE;
73 engine = ConvolutionParameter_Engine_CUDNN;
77 if (engine == ConvolutionParameter_Engine_CAFFE) {
78 return shared_ptr<Layer<Dtype> >(new ConvolutionLayer<Dtype>(param));
80 } else if (engine == ConvolutionParameter_Engine_CUDNN) {
82 LOG(FATAL) << "CuDNN doesn't support the dilated convolution at Layer "
85 return shared_ptr<Layer<Dtype> >(new CuDNNConvolutionLayer<Dtype>(param));
88 LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
89 throw; // Avoids missing return warning
93 REGISTER_LAYER_CREATOR(Convolution, GetConvolutionLayer);
95 // Get pooling layer according to engine.
96 template <typename Dtype>
97 shared_ptr<Layer<Dtype> > GetPoolingLayer(const LayerParameter& param) {
98 PoolingParameter_Engine engine = param.pooling_param().engine();
100 return shared_ptr<Layer<Dtype> >(new ACLPoolingLayer<Dtype>(param));
102 if (engine == PoolingParameter_Engine_DEFAULT) {
103 engine = PoolingParameter_Engine_CAFFE;
105 engine = PoolingParameter_Engine_CUDNN;
108 if (engine == PoolingParameter_Engine_CAFFE) {
109 return shared_ptr<Layer<Dtype> >(new PoolingLayer<Dtype>(param));
111 } else if (engine == PoolingParameter_Engine_CUDNN) {
112 if (param.top_size() > 1) {
113 LOG(INFO) << "cuDNN does not support multiple tops. "
114 << "Using Caffe's own pooling layer.";
115 return shared_ptr<Layer<Dtype> >(new PoolingLayer<Dtype>(param));
117 // CuDNN assumes layers are not being modified in place, thus
118 // breaking our index tracking for updates in some cases in Caffe.
119 // Until there is a workaround in Caffe (index management) or
120 // cuDNN, use Caffe layer to max pooling, or don't use in place
121 // layers after max pooling layers
122 if (param.pooling_param().pool() == PoolingParameter_PoolMethod_MAX) {
123 return shared_ptr<Layer<Dtype> >(new PoolingLayer<Dtype>(param));
125 return shared_ptr<Layer<Dtype> >(new CuDNNPoolingLayer<Dtype>(param));
129 LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
130 throw; // Avoids missing return warning
134 REGISTER_LAYER_CREATOR(Pooling, GetPoolingLayer);
136 // Get LRN layer according to engine
137 template <typename Dtype>
138 shared_ptr<Layer<Dtype> > GetLRNLayer(const LayerParameter& param) {
139 LRNParameter_Engine engine = param.lrn_param().engine();
141 return shared_ptr<Layer<Dtype> >(new ACLLRNLayer<Dtype>(param));
143 if (engine == LRNParameter_Engine_DEFAULT) {
145 engine = LRNParameter_Engine_CUDNN;
147 engine = LRNParameter_Engine_CAFFE;
151 if (engine == LRNParameter_Engine_CAFFE) {
152 return shared_ptr<Layer<Dtype> >(new LRNLayer<Dtype>(param));
154 } else if (engine == LRNParameter_Engine_CUDNN) {
155 LRNParameter lrn_param = param.lrn_param();
157 if (lrn_param.norm_region() ==LRNParameter_NormRegion_WITHIN_CHANNEL) {
158 return shared_ptr<Layer<Dtype> >(new CuDNNLCNLayer<Dtype>(param));
160 // local size is too big to be handled through cuDNN
161 if (param.lrn_param().local_size() > CUDNN_LRN_MAX_N) {
162 return shared_ptr<Layer<Dtype> >(new LRNLayer<Dtype>(param));
164 return shared_ptr<Layer<Dtype> >(new CuDNNLRNLayer<Dtype>(param));
169 LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
170 throw; // Avoids missing return warning
174 REGISTER_LAYER_CREATOR(LRN, GetLRNLayer);
176 // Get relu layer according to engine.
177 template <typename Dtype>
178 shared_ptr<Layer<Dtype> > GetReLULayer(const LayerParameter& param) {
179 ReLUParameter_Engine engine = param.relu_param().engine();
181 return shared_ptr<Layer<Dtype> >(new ACLReLULayer<Dtype>(param));
183 if (engine == ReLUParameter_Engine_DEFAULT) {
184 engine = ReLUParameter_Engine_CAFFE;
186 engine = ReLUParameter_Engine_CUDNN;
189 if (engine == ReLUParameter_Engine_CAFFE) {
190 return shared_ptr<Layer<Dtype> >(new ReLULayer<Dtype>(param));
192 } else if (engine == ReLUParameter_Engine_CUDNN) {
193 return shared_ptr<Layer<Dtype> >(new CuDNNReLULayer<Dtype>(param));
196 LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
197 throw; // Avoids missing return warning
201 REGISTER_LAYER_CREATOR(ReLU, GetReLULayer);
203 // Get sigmoid layer according to engine.
204 template <typename Dtype>
205 shared_ptr<Layer<Dtype> > GetSigmoidLayer(const LayerParameter& param) {
206 SigmoidParameter_Engine engine = param.sigmoid_param().engine();
208 return shared_ptr<Layer<Dtype> >(new ACLSigmoidLayer<Dtype>(param));
210 if (engine == SigmoidParameter_Engine_DEFAULT) {
211 engine = SigmoidParameter_Engine_CAFFE;
213 engine = SigmoidParameter_Engine_CUDNN;
216 if (engine == SigmoidParameter_Engine_CAFFE) {
217 return shared_ptr<Layer<Dtype> >(new SigmoidLayer<Dtype>(param));
219 } else if (engine == SigmoidParameter_Engine_CUDNN) {
220 return shared_ptr<Layer<Dtype> >(new CuDNNSigmoidLayer<Dtype>(param));
223 LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
224 throw; // Avoids missing return warning
228 REGISTER_LAYER_CREATOR(Sigmoid, GetSigmoidLayer);
230 // Get softmax layer according to engine.
231 template <typename Dtype>
232 shared_ptr<Layer<Dtype> > GetSoftmaxLayer(const LayerParameter& param) {
233 SoftmaxParameter_Engine engine = param.softmax_param().engine();
235 return shared_ptr<Layer<Dtype> >(new ACLSoftmaxLayer<Dtype>(param));
237 if (engine == SoftmaxParameter_Engine_DEFAULT) {
238 engine = SoftmaxParameter_Engine_CAFFE;
240 engine = SoftmaxParameter_Engine_CUDNN;
243 if (engine == SoftmaxParameter_Engine_CAFFE) {
244 return shared_ptr<Layer<Dtype> >(new SoftmaxLayer<Dtype>(param));
246 } else if (engine == SoftmaxParameter_Engine_CUDNN) {
247 return shared_ptr<Layer<Dtype> >(new CuDNNSoftmaxLayer<Dtype>(param));
250 LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
251 throw; // Avoids missing return warning
255 REGISTER_LAYER_CREATOR(Softmax, GetSoftmaxLayer);
257 // Get tanh layer according to engine.
258 template <typename Dtype>
259 shared_ptr<Layer<Dtype> > GetTanHLayer(const LayerParameter& param) {
260 TanHParameter_Engine engine = param.tanh_param().engine();
262 return shared_ptr<Layer<Dtype> >(new ACLTanHLayer<Dtype>(param));
264 if (engine == TanHParameter_Engine_DEFAULT) {
265 engine = TanHParameter_Engine_CAFFE;
267 engine = TanHParameter_Engine_CUDNN;
270 if (engine == TanHParameter_Engine_CAFFE) {
271 return shared_ptr<Layer<Dtype> >(new TanHLayer<Dtype>(param));
273 } else if (engine == TanHParameter_Engine_CUDNN) {
274 return shared_ptr<Layer<Dtype> >(new CuDNNTanHLayer<Dtype>(param));
277 LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
278 throw; // Avoids missing return warning
282 REGISTER_LAYER_CREATOR(TanH, GetTanHLayer);
285 // Get AbsVal layer according to engine.
286 template <typename Dtype>
287 shared_ptr<Layer<Dtype> > GetAbsValLayer(const LayerParameter& param) {
288 return shared_ptr<Layer<Dtype> >(new ACLAbsValLayer<Dtype>(param));
291 REGISTER_LAYER_CREATOR(AbsVal, GetAbsValLayer);
293 // Get BNLL layer according to engine.
294 template <typename Dtype>
295 shared_ptr<Layer<Dtype> > GetBNLLLayer(const LayerParameter& param) {
296 return shared_ptr<Layer<Dtype> >(new ACLBNLLLayer<Dtype>(param));
299 REGISTER_LAYER_CREATOR(BNLL, GetBNLLLayer);
301 // Get InnerProduct layer according to engine.
302 template <typename Dtype>
303 shared_ptr<Layer<Dtype> > GetInnerProductLayer(const LayerParameter& param) {
304 return shared_ptr<Layer<Dtype> >(new ACLInnerProductLayer<Dtype>(param));
307 REGISTER_LAYER_CREATOR(InnerProduct, GetInnerProductLayer);
309 // Get BatchNorm layer according to engine.
310 template <typename Dtype>
311 shared_ptr<Layer<Dtype> > GetBatchNormLayer(const LayerParameter& param) {
312 return shared_ptr<Layer<Dtype> >(new ACLBatchNormLayer<Dtype>(param));
315 REGISTER_LAYER_CREATOR(BatchNorm, GetBatchNormLayer);
317 // Get LocalConnect layer according to engine.
318 template <typename Dtype>
319 shared_ptr<Layer<Dtype> > GetLocalConnectLayer(const LayerParameter& param) {
320 return shared_ptr<Layer<Dtype> >(new ACLLocalConnectLayer<Dtype>(param));
323 REGISTER_LAYER_CREATOR(LocalConnect, GetLocalConnectLayer);
325 // Get Concat layer according to engine.
326 template <typename Dtype>
327 shared_ptr<Layer<Dtype> > GetConcatLayer(const LayerParameter& param) {
328 return shared_ptr<Layer<Dtype> >(new ACLConcatLayer<Dtype>(param));
331 REGISTER_LAYER_CREATOR(Concat, GetConcatLayer);
335 #ifdef WITH_PYTHON_LAYER
336 template <typename Dtype>
337 shared_ptr<Layer<Dtype> > GetPythonLayer(const LayerParameter& param) {
340 bp::object module = bp::import(param.python_param().module().c_str());
341 bp::object layer = module.attr(param.python_param().layer().c_str())(param);
342 return bp::extract<shared_ptr<PythonLayer<Dtype> > >(layer)();
343 } catch (bp::error_already_set) {
349 REGISTER_LAYER_CREATOR(Python, GetPythonLayer);
352 // Layers that use their constructor as their default creator should be
353 // registered in their corresponding cpp files. Do not register them here.