Imported Upstream version 1.25.0
[platform/core/ml/nnfw.git] / tests / nnfw_api / src / one_op_tests / Conv2D.test.cc
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
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 "GenModelTest.h"
18
19 TEST_F(GenModelTest, OneOp_Conv2D)
20 {
21   CircleGen cgen;
22   std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
23   uint32_t weight_buf = cgen.addBuffer(weight_data);
24   std::vector<float> bias_data{2, 3};
25   uint32_t bias_buf = cgen.addBuffer(bias_data);
26   int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
27   int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
28   int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
29   int out = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
30   cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
31                          circle::ActivationFunctionType_NONE, 1, 1);
32   cgen.setInputsAndOutputs({in}, {out});
33
34   _context = std::make_unique<GenModelTestContext>(cgen.finish());
35   _context->addTestCase(uniformTCD<float>(
36     {{4, 0, -5, 1, 0, 4, -1, 1, -1, -3, 3, -2, -4, 1, -2, 2, 4, -4, 2, 2, 0, 4, -1, -2, 4}},
37     {{47, -4, -25, 9, 10, 10, -13, 11, -14, -26, -12, 26, 20, 40, 1, 3, 11, 4}}));
38   _context->setBackends({"acl_cl", "acl_neon", "cpu", "ruy", "xnnpack", "gpu_cl"});
39
40   SUCCEED();
41 }
42
43 TEST_F(GenModelTest, OneOp_Conv2D_Stride)
44 {
45   CircleGen cgen;
46   std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
47   uint32_t weight_buf = cgen.addBuffer(weight_data);
48   std::vector<float> bias_data{2, 3};
49   uint32_t bias_buf = cgen.addBuffer(bias_data);
50   int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
51   int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
52   int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
53   int out = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
54   cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 2, 2,
55                          circle::ActivationFunctionType_NONE, 1, 1);
56   cgen.setInputsAndOutputs({in}, {out});
57
58   _context = std::make_unique<GenModelTestContext>(cgen.finish());
59   _context->addTestCase(uniformTCD<float>(
60     {{4, 0, -5, 1, 0, 4, -1, 1, -1, -3, 3, -2, -4, 1, -2, 2, 4, -4, 2, 2, 0, 4, -1, -2, 4}},
61     {{22, 27, -10, -2, 5, -8, 7, 3, -14, -26, -10, 18, 4, -13, -28, 9, 14, 1}}));
62   _context->setBackends({"acl_cl", "acl_neon", "cpu", "ruy", "xnnpack"});
63
64   SUCCEED();
65 }
66
67 TEST_F(GenModelTest, OneOp_Conv2D_Dilation)
68 {
69   CircleGen cgen;
70   std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
71   uint32_t weight_buf = cgen.addBuffer(weight_data);
72   std::vector<float> bias_data{2, 3};
73   uint32_t bias_buf = cgen.addBuffer(bias_data);
74   int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
75   int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
76   int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
77   int out = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32});
78   cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
79                          circle::ActivationFunctionType_NONE, 2, 2);
80   cgen.setInputsAndOutputs({in}, {out});
81
82   _context = std::make_unique<GenModelTestContext>(cgen.finish());
83   _context->addTestCase(uniformTCD<float>(
84     {{4, 0, -5, 1, 0, 4, -1, 1, -1, -3, 3, -2, -4, 1, -2, 2, 4, -4, 2, 2, 0, 4, -1, -2, 4}},
85     {{-52, 7}}));
86   _context->setBackends({"cpu", "ruy", "xnnpack"});
87
88   SUCCEED();
89 }
90
91 TEST_F(GenModelTest, OneOp_Conv2D_I8)
92 {
93   CircleGen cgen;
94   std::vector<int8_t> weight_data{1, 2, 3, 4, 5, 6, 7, 8, 9};
95   uint32_t weight_buf = cgen.addBuffer(weight_data);
96   std::vector<int32_t> bias_data{0, 2, 4};
97   uint32_t bias_buf = cgen.addBuffer(bias_data);
98   int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 0.5, 0);
99   int weight =
100     cgen.addTensor({{3, 1, 1, 3}, circle::TensorType::TensorType_INT8, weight_buf}, 0.5, 0);
101   int bias = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT32, bias_buf}, 1.0, 0);
102   int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 1.0, 0);
103   cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
104                          circle::ActivationFunctionType_NONE);
105   cgen.setInputsAndOutputs({in}, {out});
106
107   _context = std::make_unique<GenModelTestContext>(cgen.finish());
108   _context->addTestCase(uniformTCD<int8_t>({{10, 10, 10}}, {{15, 38, 61}}));
109   _context->setBackends({"cpu"});
110
111   SUCCEED();
112 }
113
114 TEST_F(GenModelTest, OneOp_Conv2D_I8_PerChannel)
115 {
116   CircleGen cgen;
117   std::vector<int8_t> weight_data{1, 2, 3, 1, 2, 3, 7, 8, 9};
118   uint32_t weight_buf = cgen.addBuffer(weight_data);
119   std::vector<int32_t> bias_data{0, 0, 0};
120   uint32_t bias_buf = cgen.addBuffer(bias_data);
121   int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 0.5, 0);
122   std::vector<float> weight_scales = {0.5, 1, 0.5};
123   std::vector<int64_t> weight_zeropoints = {0, 0, 0};
124   int weight = cgen.addTensor({{3, 1, 1, 3}, circle::TensorType::TensorType_INT8, weight_buf},
125                               weight_scales, weight_zeropoints);
126   int bias = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT32, bias_buf}, 1.0, 0);
127   int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 1.0, 0);
128   cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
129                          circle::ActivationFunctionType_NONE);
130   cgen.setInputsAndOutputs({in}, {out});
131
132   _context = std::make_unique<GenModelTestContext>(cgen.finish());
133   _context->addTestCase(uniformTCD<int8_t>({{10, 10, 10}}, {{15, 30, 60}}));
134   _context->setBackends({"cpu"});
135
136   SUCCEED();
137 }
138
139 TEST_F(GenModelTest, OneOp_Conv2D_U8_PerChannel)
140 {
141   CircleGen cgen;
142   // weight
143   std::vector<uint8_t> weight_data{2, 6, 2, 1, 2, 3, 2, 3, 4};
144   uint32_t weight_buf = cgen.addBuffer(weight_data);
145   std::vector<float> weight_scales = {.5, 1, 2};
146   std::vector<int64_t> weight_zeropoints = {2, 0, 1};
147   int weight = cgen.addTensor({{3, 1, 1, 3}, circle::TensorType::TensorType_UINT8, weight_buf},
148                               weight_scales, weight_zeropoints);
149   // bias
150   std::vector<int32_t> bias_data{4, -8, -4};
151   uint32_t bias_buf = cgen.addBuffer(bias_data);
152   int bias = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT32, bias_buf}, 1., 0);
153
154   // in and out
155   int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_UINT8}, 2., 1);
156   int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_UINT8}, 4., 2);
157
158   cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
159                          circle::ActivationFunctionType_NONE);
160   cgen.setInputsAndOutputs({in}, {out});
161
162   _context = std::make_unique<GenModelTestContext>(cgen.finish());
163   _context->addTestCase(uniformTCD<uint8_t>({{5, 3, 7}}, {{5, 11, 24}}));
164   _context->setBackends({"cpu"});
165
166   SUCCEED();
167 }
168
169 TEST_F(GenModelTest, OneOp_Conv2D_I8_Hybrid_PerChannel)
170 {
171   CircleGen cgen;
172   std::vector<int8_t> weight_data{1, 2, 3, 1, 2, 3, 7, 8, 9};
173   uint32_t weight_buf = cgen.addBuffer(weight_data);
174   std::vector<float> bias_data{0, 0, 0};
175   uint32_t bias_buf = cgen.addBuffer(bias_data);
176   int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32});
177   std::vector<float> weight_scales = {0.5, 1, 0.5};
178   std::vector<int64_t> weight_zeropoints = {0, 0, 0};
179   int weight = cgen.addTensor({{3, 1, 1, 3}, circle::TensorType::TensorType_INT8, weight_buf},
180                               weight_scales, weight_zeropoints);
181   int bias = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32, bias_buf});
182   int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32});
183   cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
184                          circle::ActivationFunctionType_NONE);
185   cgen.setInputsAndOutputs({in}, {out});
186
187   _context = std::make_unique<GenModelTestContext>(cgen.finish());
188   _context->addTestCase(uniformTCD<float>({{5, 5, 5}}, {{15, 30, 60}}));
189   _context->setBackends({"cpu"});
190
191   SUCCEED();
192 }
193
194 TEST_F(GenModelTest, neg_OneOp_Conv2D_Type)
195 {
196   CircleGen cgen;
197   std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
198   uint32_t weight_buf = cgen.addBuffer(weight_data);
199   std::vector<float> bias_data{2, 3};
200   uint32_t bias_buf = cgen.addBuffer(bias_data);
201   int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
202   int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
203   int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
204   int out = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT16});
205   cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
206                          circle::ActivationFunctionType_NONE, 1, 1);
207   cgen.setInputsAndOutputs({in}, {out});
208
209   _context = std::make_unique<GenModelTestContext>(cgen.finish());
210   _context->expectFailModelLoad();
211
212   SUCCEED();
213 }
214
215 TEST_F(GenModelTest, neg_OneOp_Conv2D_Stride)
216 {
217   CircleGen cgen;
218   std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
219   uint32_t weight_buf = cgen.addBuffer(weight_data);
220   std::vector<float> bias_data{2, 3};
221   uint32_t bias_buf = cgen.addBuffer(bias_data);
222   int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
223   int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
224   int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
225   int out = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
226   cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 0, 0,
227                          circle::ActivationFunctionType_NONE, 1, 1);
228   cgen.setInputsAndOutputs({in}, {out});
229
230   _context = std::make_unique<GenModelTestContext>(cgen.finish());
231   _context->expectFailModelLoad();
232
233   SUCCEED();
234 }
235
236 TEST_F(GenModelTest, neg_OneOp_Conv2D_Dilation)
237 {
238   CircleGen cgen;
239   std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
240   uint32_t weight_buf = cgen.addBuffer(weight_data);
241   std::vector<float> bias_data{2, 3};
242   uint32_t bias_buf = cgen.addBuffer(bias_data);
243   int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
244   int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
245   int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
246   int out = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32});
247   cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
248                          circle::ActivationFunctionType_NONE, 0, 0);
249   cgen.setInputsAndOutputs({in}, {out});
250
251   _context = std::make_unique<GenModelTestContext>(cgen.finish());
252   _context->expectFailModelLoad();
253
254   SUCCEED();
255 }
256
257 TEST_F(GenModelTest, neg_OneOp_Conv2D_I8_NonZero_ZeroPoint)
258 {
259   CircleGen cgen;
260   std::vector<int8_t> weight_data{1, 2, 3, 4, 5, 6, 7, 8, 9};
261   uint32_t weight_buf = cgen.addBuffer(weight_data);
262   std::vector<int32_t> bias_data{0, 2, 4};
263   uint32_t bias_buf = cgen.addBuffer(bias_data);
264   int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 0.5, 0);
265   int weight =
266     cgen.addTensor({{3, 1, 1, 3}, circle::TensorType::TensorType_INT8, weight_buf}, 0.5, 17);
267   int bias = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT32, bias_buf}, 1.0, 0);
268   int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 1.0, 0);
269   cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
270                          circle::ActivationFunctionType_NONE);
271   cgen.setInputsAndOutputs({in}, {out});
272
273   _context = std::make_unique<GenModelTestContext>(cgen.finish());
274   _context->setBackends({"cpu"});
275   _context->expectFailModelLoad();
276
277   SUCCEED();
278 }
279
280 TEST_F(GenModelTest, neg_OneOp_Conv2D_I8_NonZero_ZeroPoints)
281 {
282   CircleGen cgen;
283   std::vector<int8_t> weight_data{1, 2, 3, 4, 5, 6, 7, 8, 9};
284   uint32_t weight_buf = cgen.addBuffer(weight_data);
285   std::vector<int32_t> bias_data{0, 2, 4};
286   uint32_t bias_buf = cgen.addBuffer(bias_data);
287   int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 0.5, 0);
288   std::vector<float> weight_scales = {0.5, 1, 0.5};
289   std::vector<int64_t> weight_zeropoints = {0, 0, 10};
290   int weight = cgen.addTensor({{3, 1, 1, 3}, circle::TensorType::TensorType_INT8, weight_buf},
291                               weight_scales, weight_zeropoints);
292   int bias = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT32, bias_buf}, 1.0, 0);
293   int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32}, 1.0, 0);
294   cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
295                          circle::ActivationFunctionType_NONE);
296   cgen.setInputsAndOutputs({in}, {out});
297
298   _context = std::make_unique<GenModelTestContext>(cgen.finish());
299   _context->setBackends({"cpu"});
300   _context->expectFailModelLoad();
301
302   SUCCEED();
303 }
304
305 TEST_F(GenModelTest, neg_OneOp_Conv2D_I8_Hybrid_PerTensor)
306 {
307   CircleGen cgen;
308   std::vector<int8_t> weight_data{1, 2, 3, 4, 5, 6, 7, 8, 9};
309   uint32_t weight_buf = cgen.addBuffer(weight_data);
310   std::vector<float> bias_data{0, 2, 4};
311   uint32_t bias_buf = cgen.addBuffer(bias_data);
312   int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32});
313   // Hybrid does not support per-tensor.
314   std::vector<float> weight_scales = {0.5};
315   std::vector<int64_t> weight_zeropoints = {0};
316   int weight = cgen.addTensor({{3, 1, 1, 3}, circle::TensorType::TensorType_INT8, weight_buf},
317                               weight_scales, weight_zeropoints);
318   int bias = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32, bias_buf});
319   int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32});
320   cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
321                          circle::ActivationFunctionType_NONE);
322   cgen.setInputsAndOutputs({in}, {out});
323
324   _context = std::make_unique<GenModelTestContext>(cgen.finish());
325   _context->setBackends({"cpu"});
326   _context->expectFailCompile();
327
328   SUCCEED();
329 }