Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / mkl-dnn / tests / gtests / test_convolution_forward_common_3d.hpp
1 /*******************************************************************************
2 * Copyright 2016-2018 Intel Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *******************************************************************************/
16
17 #ifndef TEST_CONVOLUTION_FORWARD_COMMON_3D_H
18 #define TEST_CONVOLUTION_FORWARD_COMMON_3D_H
19
20 #include "mkldnn_test_common.hpp"
21 #include "gtest/gtest.h"
22
23 #include "mkldnn.hpp"
24 #include <stdint.h>
25
26 #include <math.h>
27
28 namespace mkldnn {
29
30 template <typename data_t_src, typename data_t_wei,
31           typename data_t_acc, typename data_t_dst>
32 void compute_ref_conv_fwd_3d(const test_convolution_sizes_t_3d &c,
33         const test_convolution_attr_t &attr,
34         const memory::desc &src_d,
35         const memory::desc &weights_d,
36         const memory::desc &bias_d,
37         const memory::desc &dst_d,
38         const memory &src,
39         const memory &weights,
40         const memory &bias,
41         const memory &dst)
42 {
43     const bool w_bias = bias_d.data.format != memory::format::format_undef;
44     data_t_src *src_data = (data_t_src *)src.get_data_handle();
45     data_t_wei *weights_data = (data_t_wei *)weights.get_data_handle();
46
47     data_t_dst *bias_data = w_bias ? (data_t_dst *)bias.get_data_handle() : nullptr;
48     data_t_dst *dst_data = (data_t_dst *)dst.get_data_handle();
49
50     size_t padded_ic = src_d.data.layout_desc.blocking.padding_dims[1];
51     size_t padded_oc = dst_d.data.layout_desc.blocking.padding_dims[1];
52
53     mkldnn::impl::parallel_nd(c.mb, c.ng, c.oc / c.ng, c.od, c.oh, c.ow,
54         [&](int n, int g, int oc, int od, int oh, int ow) {
55             data_t_acc a = 0;
56
57             for (int ic = 0; ic < c.ic / c.ng; ic++) {
58                 for (int kd = 0; kd < c.kh; kd++) {
59                     for (int kh = 0; kh < c.kh; kh++) {
60                         for (int kw = 0; kw < c.kw; kw++) {
61
62                             int iw = ow * c.strw
63                                      - c.padw + kw * (1 + c.dilw);
64                             int ih = oh * c.strh
65                                      - c.padh + kh * (1 + c.dilh);
66                             int id = od * c.strd
67                                      - c.padd + kd * (1 + c.dild);
68                             if (iw < 0 || iw >= c.iw) continue;
69                             if (ih < 0 || ih >= c.ih) continue;
70                             if (id < 0 || id >= c.id) continue;
71
72                             size_t iidx = n * padded_ic * c.id * c.ih * c.iw
73                                           + g * padded_ic / c.ng * c.id * c.ih * c.iw
74                                           + ic * c.id * c.ih * c.iw
75                                           + id * c.ih * c.iw
76                                           + ih * c.iw
77                                           + iw;
78                             size_t widx = g * padded_oc / c.ng * padded_ic
79                                           / c.ng * c.kd * c.kh * c.kw
80                                           + oc * padded_ic / c.ng * c.kd * c.kh * c.kw
81                                           + ic * c.kd * c.kh * c.kw
82                                           + kd * c.kh * c.kw
83                                           + kh * c.kw
84                                           + kw;
85
86                             a += ((data_t_acc)
87                                     src_data[map_index(src_d, iidx)])
88                                  * weights_data[map_index(
89                                     weights_d, widx)];
90                         }
91                     }
92                 }
93             }
94
95             float a_fp = (float) a;
96
97             a_fp += (float) (bias_data ?
98                              bias_data[map_index(bias_d,
99                                                  g * c.oc / c.ng + oc)] :
100                              0);
101
102
103             if (attr.oscale.is_def()) {
104                 const auto &s = attr.oscale;
105                 using P = test_convolution_attr_t::scale_t;
106                 if (s.policy == P::policy_t::COMMON) {
107                     a_fp *= s.scale;
108                 }
109             }
110
111             using D = memory::data_type;
112             if (data_traits<data_t_dst>::data_type != D::f32) {
113                 using R = mkldnn::round_mode;
114                 switch (attr.rmode) {
115                     case R::round_down:
116                         a_fp = floorf(a_fp);
117                         break;
118                     case R::round_nearest:
119                         a_fp = nearbyintf(a_fp);
120                         break;
121                 }
122             }
123
124             size_t oidx = n * padded_oc * c.od * c.oh * c.ow
125                           + g * padded_oc / c.ng * c.od * c.oh * c.ow
126                           + oc * c.od * c.oh * c.ow
127                           + od * c.oh * c.ow
128                           + oh * c.ow
129                           + ow;
130             dst_data[map_index(dst_d, oidx)] = (data_t_dst) a_fp;
131         }
132     );
133 }
134
135 template <typename data_t_src, typename data_t_wei,
136           typename data_t_acc, typename data_t_dst>
137 class convolution_forward_test_3d
138         : public ::testing::TestWithParam<test_convolution_params_t_3d> {
139 protected:
140     virtual void SetUp() {
141         auto p = ::testing::TestWithParam<test_convolution_params_t_3d>::GetParam();
142         catch_expected_failures([=](){Test();}, p.expect_to_fail,
143                     p.expected_status);
144     }
145
146     void Test() {
147         auto p = ::testing::TestWithParam<test_convolution_params_t_3d>::GetParam();
148         ASSERT_TRUE(p.engine_kind == engine::kind::cpu);
149         ASSERT_EQ(p.aalgorithm, algorithm::convolution_direct);
150         auto eng = engine(p.engine_kind, 0);
151
152         memory::data_type data_type_src = data_traits<data_t_src>::data_type;
153         memory::data_type data_type_dst = data_traits<data_t_dst>::data_type;
154         memory::data_type data_type_wei = data_traits<data_t_wei>::data_type;
155
156         test_convolution_sizes_t_3d cd = p.sizes;
157
158         test_convolution_attr_t attr = p.attr;
159         attr.mkldnn_attr_recreate();
160
161         auto aprop_kind = prop_kind::forward;
162         bool with_bias = p.formats.bias_format != memory::format::format_undef;
163
164         auto c_src_desc = create_md({ cd.mb, cd.ic, cd.id, cd.ih, cd.iw },
165             data_type_src, p.formats.src_format);
166         auto c_weights_desc = cd.ng > 1 ?
167                 create_md({ cd.ng, cd.oc / cd.ng, cd.ic / cd.ng, cd.kd, cd.kh, cd.kw },
168                         data_type_wei, p.formats.weights_format) :
169                 create_md({ cd.oc, cd.ic, cd.kd, cd.kh, cd.kw },
170                         data_type_wei,p.formats.weights_format);
171         auto c_dst_desc = create_md({ cd.mb, cd.oc, cd.od, cd.oh, cd.ow },
172                 data_type_dst, p.formats.dst_format);
173         auto c_bias_desc = with_bias ?
174                 create_md({ cd.oc }, data_type_dst, p.formats.bias_format) :
175                 create_md({}, data_type_dst, p.formats.bias_format);
176
177         auto c_src = test_memory(c_src_desc, eng);
178         auto c_weights = test_memory(c_weights_desc, eng);
179         auto c_bias = test_memory(c_bias_desc, eng);
180         auto c_dst = test_memory(c_dst_desc, eng);
181
182         std::shared_ptr<data_t_dst>
183             ref_dst_data(new data_t_dst[c_dst.get_size()]);
184
185         // Only true for dense format
186         fill_data<data_t_dst>(c_dst.get_size() / sizeof(data_t_dst),
187                 (data_t_dst *)c_dst.get().get_data_handle());
188         fill_data<data_t_src>(c_src.get_size() / sizeof(data_t_src),
189                 (data_t_src *)c_src.get().get_data_handle());
190         fill_data<data_t_wei>(c_weights.get_size() / sizeof(data_t_wei),
191                 (data_t_wei *)c_weights.get().get_data_handle());
192         if (with_bias) {
193             fill_data<data_t_dst>(c_bias.get_size() / sizeof(data_t_dst),
194                     (data_t_dst *)c_bias.get().get_data_handle());
195         }
196         check_zero_tail<data_t_src>(1, c_src.get());
197         check_zero_tail<data_t_wei>(1, c_weights.get());
198         check_zero_tail<data_t_dst>(1, c_dst.get());
199
200         std::vector<ptrdiff_t> padR = {
201             right_padding(cd.id, cd.od, cd.kd, cd.padd, cd.strd, cd.dild),
202             right_padding(cd.ih, cd.oh, cd.kh, cd.padh, cd.strh, cd.dilh),
203             right_padding(cd.iw, cd.ow, cd.kw, cd.padw, cd.strw, cd.dilw)
204         };
205
206         auto conv_desc = with_bias
207             ? convolution_forward::desc(aprop_kind, p.aalgorithm,
208                     c_src_desc, c_weights_desc, c_bias_desc, c_dst_desc,
209                     { cd.strd, cd.strh, cd.strw }, { cd.dild, cd.dilh, cd.dilw },
210                     { cd.padd, cd.padh, cd.padw }, padR, padding_kind::zero)
211             : convolution_forward::desc(aprop_kind, p.aalgorithm,
212                     c_src_desc, c_weights_desc, c_dst_desc,
213                     { cd.strd, cd.strh, cd.strw }, { cd.dild, cd.dilh, cd.dilw },
214                     { cd.padd, cd.padh, cd.padw }, padR, padding_kind::zero);
215
216         auto conv_primitive_desc = convolution_forward::primitive_desc(
217                 conv_desc, attr.mkl_attr, eng);
218
219         auto conv = with_bias ?
220             convolution_forward(conv_primitive_desc, c_src.get(),
221                     c_weights.get(), c_bias.get(), c_dst.get()) :
222             convolution_forward(conv_primitive_desc, c_src.get(),
223                     c_weights.get(), c_dst.get());
224
225         std::vector<primitive> pipeline;
226         pipeline.push_back(conv);
227         auto s = stream(stream::kind::lazy);
228         s.submit(pipeline).wait();
229
230         auto ref_memory = memory(memory::primitive_desc(c_dst_desc, eng),
231                 ref_dst_data.get());
232         compute_ref_conv_fwd_3d<data_t_src, data_t_wei, data_t_acc, data_t_dst>(
233                 cd, attr, c_src_desc, c_weights_desc, c_bias_desc, c_dst_desc,
234                 c_src.get(), c_weights.get(), c_bias.get(), ref_memory);
235         check_zero_tail<data_t_dst>(1, ref_memory);
236
237         compare_data<data_t_dst>(ref_memory, c_dst.get());
238         check_zero_tail<data_t_dst>(0, c_dst.get());
239     }
240 };
241
242 }
243 #endif