f9e2908c55d5caac9d069d5358074e4cd14c2c2e
[platform/upstream/caffeonacl.git] / src / caffe / layer_factory.cpp
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>
5 #endif
6 #include <string>
7
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"
18
19 #ifdef USE_CUDNN
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"
28 #endif
29
30 #ifdef USE_ACL
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"
44 #endif
45
46 #ifdef WITH_PYTHON_LAYER
47 #include "caffe/layers/python_layer.hpp"
48 #endif
49
50 namespace caffe {
51
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();
58 #ifdef USE_ACL
59   return GetACLConvolutionLayer<Dtype>(param);
60 #endif  
61 #ifdef USE_CUDNN
62   bool use_dilation = false;
63   for (int i = 0; i < conv_param.dilation_size(); ++i) {
64     if (conv_param.dilation(i) > 1) {
65       use_dilation = true;
66     }
67   }
68 #endif
69   if (engine == ConvolutionParameter_Engine_DEFAULT) {
70     engine = ConvolutionParameter_Engine_CAFFE;
71 #ifdef USE_CUDNN
72     if (!use_dilation) {
73       engine = ConvolutionParameter_Engine_CUDNN;
74     }
75 #endif
76   }
77   if (engine == ConvolutionParameter_Engine_CAFFE) {
78     return shared_ptr<Layer<Dtype> >(new ConvolutionLayer<Dtype>(param));
79 #ifdef USE_CUDNN
80   } else if (engine == ConvolutionParameter_Engine_CUDNN) {
81     if (use_dilation) {
82       LOG(FATAL) << "CuDNN doesn't support the dilated convolution at Layer "
83                  << param.name();
84     }
85     return shared_ptr<Layer<Dtype> >(new CuDNNConvolutionLayer<Dtype>(param));
86 #endif
87   } else {
88     LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
89     throw;  // Avoids missing return warning
90   }
91 }
92
93 REGISTER_LAYER_CREATOR(Convolution, GetConvolutionLayer);
94
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();
99 #ifdef USE_ACL
100   return shared_ptr<Layer<Dtype> >(new ACLPoolingLayer<Dtype>(param));
101 #endif  
102   if (engine == PoolingParameter_Engine_DEFAULT) {
103     engine = PoolingParameter_Engine_CAFFE;
104 #ifdef USE_CUDNN
105     engine = PoolingParameter_Engine_CUDNN;
106 #endif
107   }
108   if (engine == PoolingParameter_Engine_CAFFE) {
109     return shared_ptr<Layer<Dtype> >(new PoolingLayer<Dtype>(param));
110 #ifdef USE_CUDNN
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));
116     }
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));
124     } else {
125         return shared_ptr<Layer<Dtype> >(new CuDNNPoolingLayer<Dtype>(param));
126     }
127 #endif
128   } else {
129     LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
130     throw;  // Avoids missing return warning
131   }
132 }
133
134 REGISTER_LAYER_CREATOR(Pooling, GetPoolingLayer);
135
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();
140 #ifdef USE_ACL
141   return shared_ptr<Layer<Dtype> >(new ACLLRNLayer<Dtype>(param));
142 #endif  
143   if (engine == LRNParameter_Engine_DEFAULT) {
144 #ifdef USE_CUDNN
145     engine = LRNParameter_Engine_CUDNN;
146 #else
147     engine = LRNParameter_Engine_CAFFE;
148 #endif
149   }
150
151   if (engine == LRNParameter_Engine_CAFFE) {
152     return shared_ptr<Layer<Dtype> >(new LRNLayer<Dtype>(param));
153 #ifdef USE_CUDNN
154   } else if (engine == LRNParameter_Engine_CUDNN) {
155     LRNParameter lrn_param = param.lrn_param();
156
157     if (lrn_param.norm_region() ==LRNParameter_NormRegion_WITHIN_CHANNEL) {
158       return shared_ptr<Layer<Dtype> >(new CuDNNLCNLayer<Dtype>(param));
159     } else {
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));
163       } else {
164         return shared_ptr<Layer<Dtype> >(new CuDNNLRNLayer<Dtype>(param));
165       }
166     }
167 #endif
168   } else {
169     LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
170     throw;  // Avoids missing return warning
171   }
172 }
173
174 REGISTER_LAYER_CREATOR(LRN, GetLRNLayer);
175
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();
180 #ifdef USE_ACL
181   return shared_ptr<Layer<Dtype> >(new ACLReLULayer<Dtype>(param));
182 #endif    
183   if (engine == ReLUParameter_Engine_DEFAULT) {
184     engine = ReLUParameter_Engine_CAFFE;
185 #ifdef USE_CUDNN
186     engine = ReLUParameter_Engine_CUDNN;
187 #endif
188   }
189   if (engine == ReLUParameter_Engine_CAFFE) {
190     return shared_ptr<Layer<Dtype> >(new ReLULayer<Dtype>(param));
191 #ifdef USE_CUDNN
192   } else if (engine == ReLUParameter_Engine_CUDNN) {
193     return shared_ptr<Layer<Dtype> >(new CuDNNReLULayer<Dtype>(param));
194 #endif
195   } else {
196     LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
197     throw;  // Avoids missing return warning
198   }
199 }
200
201 REGISTER_LAYER_CREATOR(ReLU, GetReLULayer);
202
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();
207 #ifdef USE_ACL
208   return shared_ptr<Layer<Dtype> >(new ACLSigmoidLayer<Dtype>(param));
209 #endif    
210   if (engine == SigmoidParameter_Engine_DEFAULT) {
211     engine = SigmoidParameter_Engine_CAFFE;
212 #ifdef USE_CUDNN
213     engine = SigmoidParameter_Engine_CUDNN;
214 #endif
215   }
216   if (engine == SigmoidParameter_Engine_CAFFE) {
217     return shared_ptr<Layer<Dtype> >(new SigmoidLayer<Dtype>(param));
218 #ifdef USE_CUDNN
219   } else if (engine == SigmoidParameter_Engine_CUDNN) {
220     return shared_ptr<Layer<Dtype> >(new CuDNNSigmoidLayer<Dtype>(param));
221 #endif
222   } else {
223     LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
224     throw;  // Avoids missing return warning
225   }
226 }
227
228 REGISTER_LAYER_CREATOR(Sigmoid, GetSigmoidLayer);
229
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();
234 #ifdef USE_ACL
235   return shared_ptr<Layer<Dtype> >(new ACLSoftmaxLayer<Dtype>(param));
236 #endif    
237   if (engine == SoftmaxParameter_Engine_DEFAULT) {
238     engine = SoftmaxParameter_Engine_CAFFE;
239 #ifdef USE_CUDNN
240     engine = SoftmaxParameter_Engine_CUDNN;
241 #endif
242   }
243   if (engine == SoftmaxParameter_Engine_CAFFE) {
244     return shared_ptr<Layer<Dtype> >(new SoftmaxLayer<Dtype>(param));
245 #ifdef USE_CUDNN
246   } else if (engine == SoftmaxParameter_Engine_CUDNN) {
247     return shared_ptr<Layer<Dtype> >(new CuDNNSoftmaxLayer<Dtype>(param));
248 #endif
249   } else {
250     LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
251     throw;  // Avoids missing return warning
252   }
253 }
254
255 REGISTER_LAYER_CREATOR(Softmax, GetSoftmaxLayer);
256
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();
261 #ifdef USE_ACL
262   return shared_ptr<Layer<Dtype> >(new ACLTanHLayer<Dtype>(param));
263 #endif    
264   if (engine == TanHParameter_Engine_DEFAULT) {
265     engine = TanHParameter_Engine_CAFFE;
266 #ifdef USE_CUDNN
267     engine = TanHParameter_Engine_CUDNN;
268 #endif
269   }
270   if (engine == TanHParameter_Engine_CAFFE) {
271     return shared_ptr<Layer<Dtype> >(new TanHLayer<Dtype>(param));
272 #ifdef USE_CUDNN
273   } else if (engine == TanHParameter_Engine_CUDNN) {
274     return shared_ptr<Layer<Dtype> >(new CuDNNTanHLayer<Dtype>(param));
275 #endif
276   } else {
277     LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
278     throw;  // Avoids missing return warning
279   }
280 }
281
282 REGISTER_LAYER_CREATOR(TanH, GetTanHLayer);
283
284 #ifdef USE_ACL
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));
289 }
290
291 REGISTER_LAYER_CREATOR(AbsVal, GetAbsValLayer);
292
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));
297 }
298
299 REGISTER_LAYER_CREATOR(BNLL, GetBNLLLayer);
300
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));
305 }
306
307 REGISTER_LAYER_CREATOR(InnerProduct, GetInnerProductLayer);
308
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));
313 }
314
315 REGISTER_LAYER_CREATOR(BatchNorm, GetBatchNormLayer);
316
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));
321 }
322
323 REGISTER_LAYER_CREATOR(LocalConnect, GetLocalConnectLayer);
324
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));
329 }
330
331 REGISTER_LAYER_CREATOR(Concat, GetConcatLayer);
332
333 #endif // USE_ACL
334
335 #ifdef WITH_PYTHON_LAYER
336 template <typename Dtype>
337 shared_ptr<Layer<Dtype> > GetPythonLayer(const LayerParameter& param) {
338   Py_Initialize();
339   try {
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) {
344     PyErr_Print();
345     throw;
346   }
347 }
348
349 REGISTER_LAYER_CREATOR(Python, GetPythonLayer);
350 #endif
351
352 // Layers that use their constructor as their default creator should be
353 // registered in their corresponding cpp files. Do not register them here.
354 }  // namespace caffe