tiny_dnn  1.0.0
A header only, dependency-free deep learning framework in C++11
backend_avx.h
1 /*
2  Copyright (c) 2016, Taiga Nomi, Edgar Riba
3  All rights reserved.
4 
5  Redistribution and use in source and binary forms, with or without
6  modification, are permitted provided that the following conditions are met:
7  * Redistributions of source code must retain the above copyright
8  notice, this list of conditions and the following disclaimer.
9  * Redistributions in binary form must reproduce the above copyright
10  notice, this list of conditions and the following disclaimer in the
11  documentation and/or other materials provided with the distribution.
12  * Neither the name of the <organization> nor the
13  names of its contributors may be used to endorse or promote products
14  derived from this software without specific prior written permission.
15 
16  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
17  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #pragma once
28 
29 #include "tiny_dnn/core/backend.h"
30 
31 #include "tiny_dnn/core/kernels/avx_deconv2d_kernel.h"
32 #include "tiny_dnn/core/kernels/avx_deconv2d_back_kernel.h"
33 
34 namespace tiny_dnn {
35 namespace core {
36 
37 class avx_backend : public backend {
38  public:
39  // context holds solution-dependent parameters
40  // context should be able to hold any types of structures (like boost::any)
41 
42  // convolution
43  avx_backend(conv_params* params,
44  std::function<void(const tensor_t&)> f1,
45  std::function<void(const tensor_t&, tensor_t&)> f2,
46  std::function<void(const tensor_t&, const tensor_t&, tensor_t&)> f3,
48  : params_c_(params)
49  , conv_layer_worker_storage_(ptr)
50  , copy_and_pad_input(f1)
51  , copy_and_unpad_delta(f2)
52  , backward_activation(f3) {}
53 
54  // deconvolution
55  avx_backend(deconv_params* params,
56  std::function<void(const tensor_t&)> f1,
57  std::function<void(const tensor_t&, tensor_t&)> f2,
58  std::function<void(const tensor_t&, const tensor_t&, tensor_t&)> f3,
60  : params_d_(params)
61  , deconv_layer_worker_storage_(ptr)
62  , copy_and_unpad_output(f1)
63  , copy_and_pad_delta(f2)
64  , backward_activation(f3) {}
65 
66  // maxpooling
67  avx_backend(std::vector<std::vector<serial_size_t>>* out2in,
68  std::vector<serial_size_t>* in2out,
69  std::function<void(const tensor_t&, const tensor_t&, tensor_t&)> f,
71  : max_pooling_layer_worker_storage_(ptr)
72  , out2in_(out2in)
73  , in2out_(in2out)
74  , backward_activation(f) {}
75 
76  // fully_connected
77  avx_backend(fully_params* params,
78  std::function<void(const tensor_t&, const tensor_t&, tensor_t&)> f)
79  : params_f_(params)
80  , backward_activation(f) {}
81 
82  // core math functions
83 
84  void conv2d(const std::vector<tensor_t*>& in_data,
85  std::vector<tensor_t*>& out_data) override {
86 
87  if (params_c_) return; // workaround to fix warnings
88  if (params_f_) return; // workaround to fix warnings
89  if (conv_layer_worker_storage_) return; // workaround to fix warnings
90  /*copy_and_pad_input(*in_data[0]);
91  const vec_t& W = (*in_data[1])[0];
92  const vec_t& bias = (*in_data[2])[0];
93  tensor_t& a = *out_data[1];
94  const std::vector<const vec_t*> &in = (*conv_layer_worker_storage_).prev_out_padded_; // input // NOLINT
95 
96  fill_tensor(a, float_t(0));
97 
98  kernels::avx_conv2d_kernel(*params_c_,
99  in, W, bias, a, layer_->parallelize());*/
100  }
101 
102  void conv2d_q(const std::vector<tensor_t*>& in_data,
103  std::vector<tensor_t*>& out_data) override {
104  throw nn_error("not implemented yet.");
105  }
106 
107  void conv2d_eq(const std::vector<tensor_t*>& in_data,
108  std::vector<tensor_t*>& out_data) override {
109  throw nn_error("not implemented yet.");
110  }
111 
112  void conv2d(const std::vector<tensor_t*>& in_data,
113  const std::vector<tensor_t*>& out_data,
114  std::vector<tensor_t*>& out_grad,
115  std::vector<tensor_t*>& in_grad) override {
116  /*conv_layer_worker_specific_storage& cws = (*conv_layer_worker_storage_);
117 
118  //std::vector<const vec_t*>& prev_out = cws.prev_out_padded_;
119  const vec_t& W = (*in_data[1])[0];
120  tensor_t& dW = *in_grad[1];
121  tensor_t& db = *in_grad[2];
122  tensor_t& curr_delta = *out_grad[1];
123  tensor_t* prev_delta = (params_c_->pad_type == padding::same) ?
124  &cws.prev_delta_padded_ : in_grad[0];
125 
126  assert(W.size() == params_c_->weight.size());
127  assert(dW[0].size() == params_c_->weight.size());
128  assert(curr_delta[0].size() == layer_->out_shape()[0].size());
129 
130  backward_activation(*out_grad[0], *out_data[0], curr_delta);
131 
132  fill_tensor(*prev_delta, float_t(0));
133 
134  kernels::avx_conv2d_back_kernel(*params_c_,
135  prev_out, W, dW, db, curr_delta, prev_delta);
136 
137  if (params_c_->pad_type == padding::same) {
138  copy_and_unpad_delta(cws.prev_delta_padded_, *in_grad[0]);
139  }*/
140  }
141 
142  void conv2d_q(const std::vector<tensor_t*>& in_data,
143  const std::vector<tensor_t*>& out_data,
144  std::vector<tensor_t*>& out_grad,
145  std::vector<tensor_t*>& in_grad) override {
146  throw nn_error("not implemented yet.");
147  }
148 
149  void deconv2d(const std::vector<tensor_t*>& in_data,
150  std::vector<tensor_t*>& out_data) override {
151  (*deconv_layer_worker_storage_).prev_out_ = in_data[0];
152  const vec_t& W = (*in_data[1])[0];
153  const vec_t& bias = (*in_data[2])[0];
154  tensor_t& a = *out_data[1];
155  const tensor_t &in = *in_data[0]; // input
156 
157  fill_tensor(a, float_t(0));
158 
159  kernels::avx_deconv2d_kernel(*params_d_,
160  in, W, bias, a, layer_->parallelize());
161 
162  copy_and_unpad_output(a);
163  a = *(*deconv_layer_worker_storage_).curr_out_unpadded_;
164  }
165 
166  void deconv2d_q(const std::vector<tensor_t*>& in_data,
167  std::vector<tensor_t*>& out_data) override {
168  throw nn_error("not implemented yet.");
169  }
170 
171  void deconv2d_eq(const std::vector<tensor_t*>& in_data,
172  std::vector<tensor_t*>& out_data) override {
173  throw nn_error("not implemented yet.");
174  }
175 
176  void deconv2d(const std::vector<tensor_t*>& in_data,
177  const std::vector<tensor_t*>& out_data,
178  std::vector<tensor_t*>& out_grad,
179  std::vector<tensor_t*>& in_grad) override {
180 
181  deconv_layer_worker_specific_storage& cws = (*deconv_layer_worker_storage_);
182  if (params_d_->pad_type == padding::same)
183  copy_and_pad_delta(cws.curr_delta_padded, *in_grad[0]);
184 
185  const tensor_t& prev_out = *(cws.prev_out_);
186  const vec_t& W = (*in_data[1])[0];
187  tensor_t& dW = *in_grad[1];
188  tensor_t& db = *in_grad[2];
189  tensor_t& curr_delta = (params_d_->pad_type == padding::same) ? cws.curr_delta_padded : *out_grad[1];
190  tensor_t* prev_delta = in_grad[0];
191 
192  assert(W.size() == params_d_->weight.size());
193  assert(dW[0].size() == params_d_->weight.size());
194  assert(curr_delta[0].size() == layer_->out_shape()[0].size());
195 
196  backward_activation(*out_grad[0], *out_data[0], curr_delta);
197 
198  fill_tensor(*prev_delta, float_t(0));
199 
200  kernels::avx_deconv2d_back_kernel(*params_d_,
201  prev_out, W, dW, db, curr_delta, prev_delta);
202  }
203 
204  void deconv2d_q(const std::vector<tensor_t*>& in_data,
205  const std::vector<tensor_t*>& out_data,
206  std::vector<tensor_t*>& out_grad,
207  std::vector<tensor_t*>& in_grad) override {
208  throw nn_error("not implemented yet.");
209  }
210 
211  void maxpool(const std::vector<tensor_t*>& in_data,
212  std::vector<tensor_t*>& out_data) override {
213  // just to fix warning. Remove in a future
214  if (max_pooling_layer_worker_storage_) {}
215  if (out2in_) {}
216  if (in2out_) {}
217 
218  /*const tensor_t& in = *in_data[0];
219  tensor_t& a = *out_data[1];
220  std::vector<std::vector<serial_size_t>>& max_idx =
221  (*max_pooling_layer_worker_storage_).out2inmax_;
222 
223  kernels::avx_maxpool_kernel(in, a,
224  max_idx, *out2in_, layer_->parallelize());*/
225  }
226 
227  void maxpool(const std::vector<tensor_t*>& in_data,
228  const std::vector<tensor_t*>& out_data,
229  std::vector<tensor_t*>& out_grad,
230  std::vector<tensor_t*>& in_grad) override {
231  /*tensor_t& prev_delta = *in_grad[0];
232  tensor_t& curr_delta = *out_grad[1];
233  std::vector<std::vector<serial_size_t>>& max_idx =
234  (*max_pooling_layer_worker_storage_).out2inmax_;
235 
236  CNN_UNREFERENCED_PARAMETER(in_data);
237 
238  backward_activation(*out_grad[0], *out_data[0], curr_delta);
239 
240  kernels::avx_maxpool_back_kernel(prev_delta, curr_delta,
241  max_idx, *in2out_, layer_->parallelize());*/
242  }
243 
244  void fully(const std::vector<tensor_t*>& in_data,
245  std::vector<tensor_t*>& out_data) override {
246  /*const tensor_t& in = *in_data[0];
247  const vec_t& W = (*in_data[1])[0];
248  tensor_t& a = *out_data[1];
249 
250  kernels::avx_fully_connected_kernel(*params_f_,
251  in, W, params_f_->has_bias_ ? (*in_data[2])[0] : vec_t(),
252  a, layer_->parallelize());*/
253  }
254 
255  void fully_q(const std::vector<tensor_t*>& in_data,
256  std::vector<tensor_t*>& out_data) override {
257  throw nn_error("not implemented yet.");
258  }
259 
260  void fully_eq(const std::vector<tensor_t*>& in_data,
261  std::vector<tensor_t*>& out_data) override {
262  throw nn_error("not implemented yet.");
263  }
264 
265  void fully(const std::vector<tensor_t*>& in_data,
266  const std::vector<tensor_t*>& out_data,
267  std::vector<tensor_t*>& out_grad,
268  std::vector<tensor_t*>& in_grad) override {
269  /*const tensor_t& prev_out = *in_data[0];
270  const vec_t& W = (*in_data[1])[0];
271  tensor_t& dW = *in_grad[1];
272  tensor_t& db = *in_grad[2];
273  tensor_t& prev_delta = *in_grad[0];
274  tensor_t& curr_delta = *out_grad[1];
275 
276  backward_activation(*out_grad[0], *out_data[0], curr_delta);
277 
278  kernels::avx_fully_connected_back_kernel(*params_f_, prev_out,
279  W, dW, prev_delta, curr_delta, db, layer_->parallelize());*/
280  }
281 
282  void fully_q(const std::vector<tensor_t*>& in_data,
283  const std::vector<tensor_t*>& out_data,
284  std::vector<tensor_t*>& out_grad,
285  std::vector<tensor_t*>& in_grad) override {
286  throw nn_error("not implemented yet.");
287  }
288 
289  backend_t type() const override { return backend_t::avx; }
290 
291  private:
292  /* Pointer to the convolution parameters */
293  conv_params* params_c_;
294  deconv_params* params_d_;
295  fully_params* params_f_;
296 
297  /* Pointer to the workers */
298  conv_layer_worker_specific_storage* conv_layer_worker_storage_;
299  deconv_layer_worker_specific_storage* deconv_layer_worker_storage_;
300  max_pooling_layer_worker_specific_storage* max_pooling_layer_worker_storage_;
301  std::vector<std::vector<serial_size_t>>* out2in_;
302  std::vector<serial_size_t>* in2out_;
303 
304  /* Pointers to parent class functions */
305  std::function<void(const tensor_t&)> copy_and_pad_input;
306  std::function<void(const tensor_t&)> copy_and_unpad_output;
307  std::function<void(const tensor_t&, tensor_t&)> copy_and_unpad_delta;
308  std::function<void(const tensor_t&, tensor_t&)> copy_and_pad_delta;
309  std::function<void(const tensor_t&, const tensor_t&, tensor_t&)> backward_activation;
310 };
311 
312 } // namespace core
313 } // namespace tiny_dnn
Definition: backend_avx.h:37
Definition: backend.h:68
Definition: conv_params.h:92
Definition: fully_params.h:34
virtual std::vector< shape3d > out_shape() const =0
array of output shapes (width x height x depth)
error exception class for tiny-dnn
Definition: nn_error.h:37
Definition: deconv_params.h:39