29 #include "tiny_dnn/core/params/deconv_params.h"
30 #include "tiny_dnn/core/kernels/tiny_quantization_kernel.h"
36 inline void tiny_quantized_deconv2d_kernel(
const deconv_params& params,
41 const bool layer_parallelize) {
43 float_t min_input(in[0]);
44 float_t max_input(in[0]);
45 for (serial_size_t inc = 0; inc < params.in.depth_; inc++) {
46 for (serial_size_t ins = 0; ins < params.in.height_*params.in.height_; ins++) {
47 serial_size_t idx = params.in.get_index(0, 0, inc);
48 min_input = std::min(min_input, (&in[idx])[ins]);
49 max_input = std::max(max_input, (&in[idx])[ins]);
52 std::vector<uint8_t> in_quantized =
53 float_tensor_to_quantized<uint8_t>(in, min_input, max_input);
55 float_t min_filter(W[0]);
56 float_t max_filter(W[0]);
57 for (serial_size_t inc = 0; inc < params.in.depth_; inc++) {
58 for (serial_size_t ins = 0; ins < params.weight.height_*params.weight.height_; ins++) {
59 serial_size_t idx = params.in.get_index(0, 0, inc);
60 min_filter = std::min(min_filter, (&W[idx])[ins]);
61 max_filter = std::max(max_filter, (&W[idx])[ins]);
64 if (min_filter == max_filter) {
65 max_filter = W[0] + 1e-3f;
66 min_filter = W[0] - 1e-3f;
68 std::vector<uint8_t> W_quantized =
69 float_tensor_to_quantized<uint8_t>(W, min_filter, max_filter);
73 std::vector<uint8_t> bias_quantized;
74 if (params.has_bias) {
75 for (serial_size_t inc = 0; inc < params.out.depth_; inc++) {
76 min_bias = std::min(min_bias, bias[inc]);
77 max_bias = std::max(max_bias, bias[inc]);
79 if (min_bias == max_bias) {
80 max_bias = bias[0] + 1e-3f;
81 min_bias = bias[0] - 1e-3f;
84 float_tensor_to_quantized<uint8_t>(bias, min_bias, max_bias);
88 float_t min_output_value;
89 float_t max_output_value;
90 quantization_range_for_multiplication<uint8_t, uint8_t, int32_t>(
91 min_input, max_input, min_filter, max_filter, &min_output_value,
94 std::vector<int32_t> a_quantized(a.size(),
static_cast<int32_t
>(0));
97 const int32_t offset_input =
98 int64_to_int32(float_to_quantized_unclamped<uint8_t>(0.0f, min_input, max_input));
99 const int32_t offset_filter =
100 int64_to_int32(float_to_quantized_unclamped<uint8_t>(0.0f, min_filter, max_filter));
101 const int32_t zero_in_total_space =
102 int64_to_int32(float_to_quantized<int32_t>(0.0f, min_output_value, max_output_value));
104 for_i(layer_parallelize, params.out.depth_, [&](
int o) {
105 for (serial_size_t inc = 0; inc < params.in.depth_; inc++) {
106 if (!params.tbl.is_connected(o, inc)) continue;
108 serial_size_t idx = 0;
109 idx = params.in.depth_ * o + inc;
110 idx = params.weight.get_index(0, 0, idx);
111 const uint8_t *pw = &W_quantized[idx];
113 idx = params.in.get_index(0, 0, inc);
114 const uint8_t *pi = &in_quantized[idx];
116 idx = params.out.get_index(0, 0, o);
117 int32_t *pa_quantized = &a_quantized[idx];
119 for (serial_size_t y = 0; y < params.in.height_; y++) {
120 for (serial_size_t x = 0; x < params.in.width_; x++) {
121 const uint8_t * ppw = pw;
122 const uint8_t * ppi = pi + y * params.in.width_ + x;
124 for (serial_size_t wy = 0; wy < params.weight.height_; wy++) {
125 for (serial_size_t wx = 0; wx < params.weight.width_; wx++) {
126 pa_quantized[(y * params.h_stride + wy) *
127 params.out.width_ + (x *
128 params.w_stride + wx)] += static_cast<int32_t>(ppw[wy *
129 params.weight.width_ + wx] - offset_filter) *
130 static_cast<int32_t>(*ppi - offset_input);
136 if (params.has_bias) {
137 int32_t * pa_quantized = &a_quantized[params.out.get_index(0, 0, o)];
138 int32_t * paa_quantized = pa_quantized + params.out.width_ * params.out.height_;
139 std::for_each(pa_quantized, paa_quantized, [&](int32_t& f) {
140 f += (bias_quantized[o] - zero_in_total_space);
145 float_t min_output_requantized;
146 float_t max_output_requantized;
147 std::vector<uint8_t> a_requantized(a_quantized.size(),
static_cast<uint8_t
>(0));
150 quantize_down_and_shrink_range<int32_t, uint8_t>(a_quantized, min_output_value, max_output_value,
151 &min_output_requantized, &max_output_requantized, &a_requantized);
154 a = quantized_tensor_to_float<uint8_t>(a_requantized, min_output_requantized, max_output_requantized);
157 inline void tiny_quantized_deconv2d_back_kernel(
const deconv_params& params,
158 const vec_t& prev_out,
165 float_t min_prev_out(prev_out[0]);
166 float_t max_prev_out(prev_out[0]);
167 for (serial_size_t inc = 0; inc < params.in.depth_; inc++) {
168 for (serial_size_t ins = 0; ins < params.in.height_*params.in.height_; ins++) {
169 serial_size_t idx = params.in.get_index(0, 0, inc);
170 min_prev_out = std::min(min_prev_out, (&prev_out[idx])[ins]);
171 max_prev_out = std::max(min_prev_out, (&prev_out[idx])[ins]);
174 std::vector<uint8_t> prev_out_quantized =
175 float_tensor_to_quantized<uint8_t>(prev_out, min_prev_out, max_prev_out);
178 float_t min_filter(W[0]);
179 float_t max_filter(W[0]);
180 for (serial_size_t inc = 0; inc < params.in.depth_; inc++) {
181 for (serial_size_t ins = 0; ins < params.weight.height_*params.weight.height_; ins++) {
182 serial_size_t idx = params.in.get_index(0, 0, inc);
183 min_filter = std::min(min_filter, (&W[idx])[ins]);
184 max_filter = std::max(max_filter, (&W[idx])[ins]);
187 if (min_filter == max_filter) {
188 max_filter = W[0] + 1e-3f;
189 min_filter = W[0] - 1e-3f;
191 std::vector<uint8_t> W_quantized =
192 float_tensor_to_quantized<uint8_t>(W, min_filter, max_filter);
195 float_t min_curr_delta(curr_delta[0]);
196 float_t max_curr_delta(curr_delta[0]);
197 for (serial_size_t inc = 0; inc < params.out.depth_; inc++) {
198 for (serial_size_t ins = 0; ins < params.out.height_*params.out.height_; ins++) {
199 serial_size_t idx = params.out.get_index(0, 0, inc);
200 min_curr_delta = std::min(min_curr_delta, (&curr_delta[idx])[ins]);
201 max_curr_delta = std::max(max_curr_delta, (&curr_delta[idx])[ins]);
204 std::vector<uint8_t> curr_delta_quantized =
205 float_tensor_to_quantized<uint8_t>(curr_delta, min_curr_delta, max_curr_delta);
208 float_t min_prev_delta_value;
209 float_t max_prev_delta_value;
210 quantization_range_for_multiplication<uint8_t, uint8_t, int32_t>(
211 min_curr_delta, max_curr_delta, min_filter, max_filter, &min_prev_delta_value,
212 &max_prev_delta_value);
214 std::vector<int32_t> prev_delta_quantized(prev_delta->size(),
static_cast<int32_t
>(0));
217 float_t min_dW_value;
218 float_t max_dW_value;
219 quantization_range_for_multiplication<uint8_t, uint8_t, int32_t>(
220 min_curr_delta, max_curr_delta, min_prev_out, max_prev_out, &min_dW_value,
223 std::vector<int32_t> dW_quantized(dW.size(),
static_cast<int32_t
>(0));
227 const int32_t offset_prev_out =
228 int64_to_int32(float_to_quantized_unclamped<uint8_t>(0.0f, min_prev_out, max_prev_out));
229 const int32_t offset_filter =
230 int64_to_int32(float_to_quantized_unclamped<uint8_t>(0.0f, min_filter, max_filter));
231 const int32_t offset_curr_delta =
232 int64_to_int32(float_to_quantized_unclamped<uint8_t>(0.0f, min_curr_delta, max_curr_delta));
237 for_i(params.in.depth_, [&](
int inc) {
238 for (serial_size_t outc = 0; outc < params.out.depth_; outc++) {
239 if (!params.tbl.is_connected(outc, inc)) continue;
241 serial_size_t idx = 0;
242 idx = params.in.depth_ * outc + inc;
243 idx = params.weight.get_index(0, 0, idx);
244 const uint8_t *pw = &W_quantized[idx];
246 idx = params.out_unpadded.get_index(0, 0, outc);
247 const uint8_t *pdelta_src = &curr_delta_quantized[idx];
249 idx = params.in.get_index(0, 0, inc);
250 int32_t *pdelta_quantized_dst = &(prev_delta_quantized)[idx];
252 for (serial_size_t y = 0; y < params.in.height_; y++) {
253 for (serial_size_t x = 0; x < params.in.width_; x++) {
254 const uint8_t * ppw = pw;
255 int32_t * ppdelta_quantized_dst = pdelta_quantized_dst + y * params.in.width_ + x;
256 int32_t sum = int32_t(0);
258 for (serial_size_t wy = 0; wy < params.weight.height_; wy++) {
259 for (serial_size_t wx = 0; wx < params.weight.width_; wx++) {
260 sum += static_cast<int32_t>(ppw[wy * params.weight.width_ + wx] - offset_filter) *
261 static_cast<int32_t>(pdelta_src[(y * params.h_stride + wy) *
262 params.out.width_ + (x *
263 params.w_stride + wx)] -
267 *ppdelta_quantized_dst += sum;
273 float_t min_prev_delta_requantized;
274 float_t max_prev_delta_requantized;
275 std::vector<uint8_t> prev_delta_requantized(prev_delta_quantized.size(),
static_cast<uint8_t
>(0));
278 quantize_down_and_shrink_range<int32_t, uint8_t>(prev_delta_quantized, min_prev_delta_value, max_prev_delta_value,
279 &min_prev_delta_requantized, &max_prev_delta_requantized, &prev_delta_requantized);
282 vec_t prev_delta_vec = quantized_tensor_to_float<uint8_t>(prev_delta_requantized, min_prev_delta_requantized, max_prev_delta_requantized);
283 prev_delta = &prev_delta_vec;
286 for_i(params.in.depth_, [&](
int inc) {
287 for (serial_size_t outc = 0; outc < params.out.depth_; outc++) {
288 if (!params.tbl.is_connected(outc, inc)) continue;
290 for (serial_size_t wy = 0; wy < params.weight.height_; wy++) {
291 for (serial_size_t wx = 0; wx < params.weight.width_; wx++) {
292 int32_t dst = int32_t(0);
294 serial_size_t idx = 0;
295 idx = params.in.get_index(0, 0, inc);
296 const uint8_t * prevo = &prev_out_quantized[idx];
298 idx = params.out.get_index(wx, wy, outc);
299 const uint8_t * delta = &curr_delta_quantized[idx];
301 for (serial_size_t y = 0; y < params.in.height_; y++) {
302 for (serial_size_t x = 0; x < params.in.width_; x++) {
303 dst += (static_cast<int32_t>(*(prevo + y * params.in.width_ + x)) - offset_prev_out) *
304 (static_cast<int32_t>(*(delta + y * params.out.width_ + x)) - offset_curr_delta);
308 idx = params.in.depth_ * outc + inc;
309 dW_quantized[params.weight.get_index(wx, wy, idx)] += dst;
315 float_t min_dW_requantized;
316 float_t max_dW_requantized;
317 std::vector<uint8_t> dW_requantized(dW_quantized.size(),
static_cast<uint8_t
>(0));
320 quantize_down_and_shrink_range<int32_t, uint8_t>(dW_quantized, min_dW_value, max_dW_value,
321 &min_dW_requantized, &max_dW_requantized, &dW_requantized);
324 dW = quantized_tensor_to_float<uint8_t>(dW_requantized, min_dW_requantized, max_dW_requantized);
327 if (params.has_bias) {
330 for (serial_size_t outc = 0; outc < params.out.depth_; outc++) {
331 serial_size_t idx = params.out.get_index(0, 0, outc);
332 const float_t * delta = &curr_delta[idx];
333 const float_t * deltaa = delta + params.out.width_ *
335 db[outc] += std::accumulate(delta, deltaa, float_t(0));
340 inline void tiny_quantized_deconv2d_kernel(
const deconv_params& params,
349 const bool layer_parallelize) {
351 float_t min_filter(W_r[0]);
352 float_t max_filter(W_r[1]);
353 if (W_r[0] == W_r[1]) {
354 max_filter = W_r[1] + 1e-3f;
355 min_filter = W_r[0] - 1e-3f;
358 float_t min_bias(b_r[0]);
359 float_t max_bias(b_r[1]);
360 if (params.has_bias) {
361 if (min_bias == max_bias) {
362 max_bias = b_r[1] + 1e-3f;
363 min_bias = b_r[0] - 1e-3f;
367 float_t min_output_value;
368 float_t max_output_value;
369 quantization_range_for_multiplication<uint8_t, uint8_t, int32_t>(
370 in_r[0], in_r[1], min_filter, max_filter, &min_output_value,
373 std::vector<uint8_t> in_quantized, W_quantized, bias_quantized;
374 for (
size_t i = 0; i < in.size(); i++) {
375 in_quantized.push_back(
static_cast<uint8_t
>(in[i]));
377 for (
size_t i = 0; i < W.size(); i++) {
378 W_quantized.push_back(
static_cast<uint8_t
>(W[i]));
380 for (
size_t i = 0; i < bias.size(); i++) {
381 bias_quantized.push_back(
static_cast<uint8_t
>(bias[i]));
384 std::vector<int32_t> a_quantized(a.size(),
static_cast<int32_t
>(0));
387 const int32_t offset_input =
388 int64_to_int32(float_to_quantized_unclamped<uint8_t>(0.0f, in_r[0], in_r[1]));
389 const int32_t offset_filter =
390 int64_to_int32(float_to_quantized_unclamped<uint8_t>(0.0f, min_filter, max_filter));
391 const int32_t zero_in_total_space =
392 int64_to_int32(float_to_quantized<int32_t>(0.0f, min_output_value, max_output_value));
394 for_i(layer_parallelize, params.out.depth_, [&](
int o) {
395 for (serial_size_t inc = 0; inc < params.in.depth_; inc++) {
396 if (!params.tbl.is_connected(o, inc)) continue;
398 serial_size_t idx = 0;
399 idx = params.in.depth_ * o + inc;
400 idx = params.weight.get_index(0, 0, idx);
401 const uint8_t *pw = &W_quantized[idx];
403 idx = params.in.get_index(0, 0, inc);
404 const uint8_t *pi = &in_quantized[idx];
406 idx = params.out.get_index(0, 0, o);
407 int32_t *pa_quantized = &a_quantized[idx];
409 for (serial_size_t y = 0; y < params.in.height_; y++) {
410 for (serial_size_t x = 0; x < params.in.width_; x++) {
411 const uint8_t * ppw = pw;
412 const uint8_t * ppi = pi + y * params.in.width_ + x;
414 for (serial_size_t wy = 0; wy < params.weight.height_; wy++) {
415 for (serial_size_t wx = 0; wx < params.weight.width_; wx++) {
416 pa_quantized[(y * params.h_stride + wy) *
417 params.out.width_ + (x *
418 params.w_stride + wx)] += static_cast<int32_t>(ppw[wy *
419 params.weight.width_ + wx] - offset_filter) *
420 static_cast<int32_t>(*ppi - offset_input);
426 if (params.has_bias) {
427 int32_t * pa_quantized = &a_quantized[params.out.get_index(0, 0, o)];
428 int32_t * paa_quantized = pa_quantized + params.out.width_ * params.out.height_;
429 std::for_each(pa_quantized, paa_quantized, [&](int32_t& f) {
430 f += static_cast<int32_t>((bias[o] - zero_in_total_space));
435 float_t min_output_requantized;
436 float_t max_output_requantized;
437 std::vector<uint8_t> a_requantized(a_quantized.size(),
static_cast<uint8_t
>(0));
440 quantize_down_and_shrink_range<int32_t, uint8_t>(a_quantized, min_output_value, max_output_value,
441 &min_output_requantized, &max_output_requantized, &a_requantized);
443 for (
size_t i = 0; i < a_requantized.size(); i++) {
444 a[i] =
static_cast<float>(a_requantized[i]);
446 a_r[0] = min_output_requantized;
447 a_r[1] = max_output_requantized;