Add a section of how to link IE with CMake project (#99)
[platform/upstream/dldt.git] / inference-engine / thirdparty / mkl-dnn / tests / gtests / test_convolution_relu_forward_common.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 #include "mkldnn_test_common.hpp"
18 #include "gtest/gtest.h"
19
20 #include "mkldnn.hpp"
21
22 namespace mkldnn {
23
24 template <typename data_t_src, typename data_t_wei,
25           typename data_t_acc, typename data_t_dst>
26 void compute_ref_conv_relu_fwd(const test_convolution_sizes_t &c,
27         const memory &src, const memory &weights, const memory &bias,
28         const memory &dst, bool w_bias, float negative_slope)
29 {
30     data_t_src *src_data = (data_t_src *)src.get_data_handle();
31     data_t_wei *weights_data = (data_t_wei *)weights.get_data_handle();
32     data_t_dst *bias_data
33             = (data_t_dst *)(w_bias ? bias.get_data_handle() : nullptr);
34     data_t_dst *dst_data = (data_t_dst *)dst.get_data_handle();
35
36     const memory::desc src_d = src.get_primitive_desc().desc();
37     const memory::desc weights_d = weights.get_primitive_desc().desc();
38     const memory::desc dst_d = dst.get_primitive_desc().desc();
39
40     size_t padded_ic = src_d.data.layout_desc.blocking.padding_dims[1];
41     size_t padded_oc = dst_d.data.layout_desc.blocking.padding_dims[1];
42
43     mkldnn::impl::parallel_nd(c.mb, c.ng, c.oc / c.ng, c.oh, c.ow,
44         [&](int n, int g, int oc, int oh, int ow) {
45             size_t oidx = n * padded_oc * c.oh * c.ow
46                     + g * padded_oc / c.ng * c.oh * c.ow
47                     + oc * c.oh * c.ow + oh * c.ow + ow;
48             dst_data[map_index(dst_d, oidx)] = bias_data ?
49                     bias_data[map_index(
50                             bias.get_primitive_desc().desc(),
51                             g * padded_oc / c.ng + oc)] :
52                     data_t_dst{0};
53             for (int ic = 0; ic < c.ic / c.ng; ic++) {
54                 for (int kh = 0; kh < c.kh; kh++) {
55                     for (int kw = 0; kw < c.kw; kw++) {
56                         int iw = ow * c.strw
57                               - c.padw + kw * (1 + c.dilw);
58                         int ih = oh * c.strh
59                               - c.padh + kh * (1 + c.dilh);
60                         if (iw < 0 || iw >= c.iw) continue;
61                         if (ih < 0 || ih >= c.ih) continue;
62                         size_t iidx = n * padded_ic * c.ih * c.iw
63                                 + g * padded_ic / c.ng * c.ih * c.iw
64                                 + ic * c.ih * c.iw + ih * c.iw + iw;
65                         size_t widx = g * padded_oc / c.ng * padded_ic
66                                         / c.ng * c.kh * c.kw
67                             + oc * padded_ic / c.ng * c.kh * c.kw
68                             + ic * c.kh * c.kw + kh * c.kw + kw;
69
70                         dst_data[map_index(dst_d, oidx)]
71                                 += src_data[map_index(src_d, iidx)]
72                                 * weights_data[map_index(
73                                           weights_d, widx)];
74                     }
75                 }
76             }
77
78             if (dst_data[map_index(dst_d, oidx)] < 0) {
79                 dst_data[map_index(dst_d, oidx)] =
80                     static_cast<data_t_dst>( negative_slope
81                     * dst_data[map_index(dst_d, oidx)] );
82             }
83         }
84     );
85 }
86
87 template <typename data_t_src, typename data_t_wei,
88           typename data_t_acc, typename data_t_dst>
89 class convolution_relu_test
90     : public ::testing::TestWithParam<test_convolution_params_t> {
91 protected:
92     virtual void SetUp() {
93         auto p = ::testing::TestWithParam<test_convolution_params_t>::GetParam();
94         catch_expected_failures([=](){Test();}, p.expect_to_fail,
95                     p.expected_status);
96     }
97
98     void Test() {
99         auto p = ::testing::TestWithParam<test_convolution_params_t>::GetParam();
100         ASSERT_TRUE(p.engine_kind == engine::kind::cpu);
101         ASSERT_EQ(p.aalgorithm, convolution_direct);
102         auto eng = engine(p.engine_kind, 0);
103         float negative_slope = p.relu_negative_slope;
104
105         memory::data_type data_type_src = data_traits<data_t_src>::data_type;
106         memory::data_type data_type_dst = data_traits<data_t_dst>::data_type;
107         memory::data_type data_type_wei = data_traits<data_t_wei>::data_type;
108
109         test_convolution_sizes_t cd = p.sizes;
110
111         auto c_src_desc = create_md({ cd.mb, cd.ic, cd.ih, cd.iw },
112                 data_type_src, p.formats.src_format);
113         auto c_weights_desc = cd.ng > 1 ?
114                 create_md({ cd.ng, cd.oc / cd.ng, cd.ic / cd.ng, cd.kh, cd.kw },
115                         data_type_wei, p.formats.weights_format) :
116                 create_md({ cd.oc, cd.ic, cd.kh, cd.kw },
117                         data_type_wei, p.formats.weights_format);
118         auto c_dst_desc = create_md({ cd.mb, cd.oc, cd.oh, cd.ow },
119                 data_type_dst, p.formats.dst_format);
120
121         auto c_src = memory({c_src_desc, eng});
122         auto c_weights = memory({c_weights_desc, eng});
123         auto c_dst = memory({c_dst_desc, eng});
124
125         auto dst_ref = memory({c_dst_desc, eng});
126
127         fill_data<data_t_src>(c_src.get_primitive_desc().get_size()
128                 / sizeof(data_t_src), (data_t_src *)c_src.get_data_handle());
129         // TODO: Temporary workaround for testing of convolution + relu
130         if (cd.mb) {
131             data_t_src *src_data = (data_t_src *)c_src.get_data_handle();
132             const int mb_chunk = static_cast<int>(
133                 (c_src.get_primitive_desc().get_size() / sizeof(data_t_src))
134                 / cd.mb );
135             for (int i = 0; i < cd.mb * mb_chunk; ++i) {
136                 if ((i / mb_chunk) % 2) src_data[i] *= (data_t_src)-1.;
137             }
138         }
139
140         fill_data<data_t_wei>(
141                 c_weights.get_primitive_desc().get_size()
142                 / sizeof(data_t_wei),(data_t_wei *)c_weights.get_data_handle());
143         fill_data<data_t_dst>(
144                 c_dst.get_primitive_desc().get_size()
145                 / sizeof(data_t_dst),(data_t_dst *)c_dst.get_data_handle());
146
147         bool with_bias = p.formats.bias_format != memory::format::format_undef;
148         auto c_bias_desc = with_bias ?
149                 create_md({ cd.oc }, data_type_dst, p.formats.bias_format) :
150                 create_md({}, data_type_dst, p.formats.bias_format);
151         auto c_bias = memory({c_bias_desc, eng});
152         if (with_bias) {
153             fill_data<data_t_dst>(
154                     c_bias.get_primitive_desc().get_size() / sizeof(data_t_dst),
155                     (data_t_dst *)c_bias.get_data_handle(), 1., true);
156         }
157         check_zero_tail<data_t_src>(1, c_src);
158         check_zero_tail<data_t_wei>(1, c_weights);
159         check_zero_tail<data_t_dst>(1, c_dst);
160
161         std::vector<int> padR = {
162             right_padding(cd.ih, cd.oh, cd.kh, cd.padh, cd.strh, cd.dilh),
163             right_padding(cd.iw, cd.ow, cd.kw, cd.padw, cd.strw, cd.dilw)
164         };
165
166         auto conv_desc = with_bias
167             ? convolution_forward::desc(prop_kind::forward_scoring,
168                     p.aalgorithm, c_src_desc, c_weights_desc, c_bias_desc,
169                     c_dst_desc, { cd.strh, cd.strw }, { cd.dilh, cd.dilw },
170                     { cd.padh, cd.padw }, padR, padding_kind::zero)
171         : convolution_forward::desc(prop_kind::forward_scoring,
172                 p.aalgorithm, c_src_desc, c_weights_desc, c_dst_desc,
173                 { cd.strh, cd.strw }, { cd.dilh, cd.dilw },
174                 { cd.padh, cd.padw }, padR, padding_kind::zero);
175
176         auto conv_relu_desc =
177             convolution_relu_forward::desc(conv_desc, negative_slope);
178         auto conv_primitive_desc =
179             convolution_relu_forward::primitive_desc(conv_relu_desc, eng);
180
181         auto conv = with_bias
182             ? convolution_relu_forward(conv_primitive_desc,
183                     c_src, c_weights, c_bias, c_dst)
184             : convolution_relu_forward(conv_primitive_desc,
185                     c_src, c_weights, c_dst);
186         std::vector<primitive> pipeline;
187         pipeline.push_back(conv);
188
189         stream(stream::kind::lazy).submit(pipeline).wait();
190
191         compute_ref_conv_relu_fwd<data_t_src, data_t_wei, data_t_wei,
192             data_t_dst>(cd, c_src, c_weights, c_bias, dst_ref, with_bias,
193                     negative_slope);
194         check_zero_tail<data_t_dst>(1, dst_ref);
195         compare_data<data_t_dst>(dst_ref, c_dst);
196         check_zero_tail<data_t_dst>(0, c_dst);
197
198     }
199 };
200
201 }