2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "GenModelTest.h"
19 TEST_F(GenModelTest, OneOp_DepthwiseConv2D)
22 std::vector<float> weight_data{1, 2, 3, 4, -9, 10, -11, 12, 5, 6, 7, 8, 13, -14, 15, -16};
23 uint32_t weight_buf = cgen.addBuffer(weight_data);
24 std::vector<float> bias_data{1, 2, 3, 4};
25 uint32_t bias_buf = cgen.addBuffer(bias_data);
26 int in = cgen.addTensor({{1, 3, 2, 2}, circle::TensorType::TensorType_FLOAT32});
27 int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
28 int bias = cgen.addTensor({{1, 1, 1, 4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
29 int out = cgen.addTensor({{1, 2, 1, 4}, circle::TensorType::TensorType_FLOAT32});
30 cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1, 2,
31 circle::ActivationFunctionType_NONE);
32 cgen.setInputsAndOutputs({in}, {out});
34 _context = std::make_unique<GenModelTestContext>(cgen.finish());
35 _context->addTestCase(uniformTCD<float>({{1, 2, 7, 8, 3, 4, 9, 10, 5, 6, 11, 12}},
36 {{71, -34, 99, -20, 91, -26, 127, -4}}));
37 _context->setBackends({"acl_cl", "acl_neon", "cpu", "xnnpack"});
42 TEST_F(GenModelTest, OneOp_DepthwiseConv2D_No_Multiplier)
45 std::vector<float> weight_data{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
46 uint32_t weight_buf = cgen.addBuffer(weight_data);
47 std::vector<float> bias_data{0.5f, -0.5f};
48 uint32_t bias_buf = cgen.addBuffer(bias_data);
49 int in = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
50 int weight = cgen.addTensor({{1, 3, 1, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
51 int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
52 int out = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
53 cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 1, 1, 1,
54 circle::ActivationFunctionType_NONE);
55 cgen.setInputsAndOutputs({in}, {out});
57 _context = std::make_unique<GenModelTestContext>(cgen.finish());
58 _context->addTestCase(
59 uniformTCD<float>({{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}},
60 {{16.5f, 27.5f, 28.5f, 43.5f, 8.5f, 15.5f, 12.5f, 23.5f}}));
61 _context->setBackends({"acl_cl", "acl_neon", "cpu", "gpu_cl"});
65 TEST_F(GenModelTest, OneOp_DepthwiseConv2D_No_Multiplier_RELU6)
68 std::vector<float> weight_data{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
69 uint32_t weight_buf = cgen.addBuffer(weight_data);
70 std::vector<float> bias_data{0.5f, -0.5f};
71 uint32_t bias_buf = cgen.addBuffer(bias_data);
72 int in = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
73 int weight = cgen.addTensor({{1, 3, 1, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
74 int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
75 int out = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
76 cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 1, 1, 1,
77 circle::ActivationFunctionType_RELU6);
78 cgen.setInputsAndOutputs({in}, {out});
80 _context = std::make_unique<GenModelTestContext>(cgen.finish());
81 _context->addTestCase(uniformTCD<float>({{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}},
82 {{6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f}}));
83 _context->setBackends({"acl_cl", "acl_neon", "cpu", "gpu_cl"});
87 TEST_F(GenModelTest, OneOp_DepthwiseConv2D_3x3)
90 std::vector<float> weight_data{0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
91 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f};
92 uint32_t weight_buf = cgen.addBuffer(weight_data);
93 std::vector<float> bias_data{0.0f, 0.0f};
94 uint32_t bias_buf = cgen.addBuffer(bias_data);
95 int in = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
96 int weight = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
97 int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
98 int out = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
99 cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 1, 1, 1,
100 circle::ActivationFunctionType_NONE);
101 cgen.setInputsAndOutputs({in}, {out});
103 _context = std::make_unique<GenModelTestContext>(cgen.finish());
104 _context->addTestCase(
105 uniformTCD<float>({{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}},
106 {{6.0f, 16.0f, 8.0f, 16.0f, 10.0f, 16.0f, 12.0f, 16.0f}}));
107 _context->setBackends({"acl_cl", "acl_neon", "cpu", "gpu_cl"});
111 TEST_F(GenModelTest, OneOp_DepthwiseConv2D_Dilation)
114 std::vector<float> weight_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
115 uint32_t weight_buf = cgen.addBuffer(weight_data);
116 std::vector<float> bias_data{0, 0, 0, 0};
117 uint32_t bias_buf = cgen.addBuffer(bias_data);
118 int in = cgen.addTensor({{1, 4, 4, 2}, circle::TensorType::TensorType_FLOAT32});
119 int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
120 int bias = cgen.addTensor({{1, 1, 1, 4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
121 int out = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32});
122 cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1, 2,
123 circle::ActivationFunctionType_NONE, 2, 2);
124 cgen.setInputsAndOutputs({in}, {out});
126 _context = std::make_unique<GenModelTestContext>(cgen.finish());
127 _context->addTestCase(uniformTCD<float>({{
128 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
129 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
131 {{13, 14, 0, 0, 0, 0, 11, 12, 5, 6, 0, 0, 0, 0, 3, 4}}));
132 _context->setBackends({"acl_cl", "acl_neon", "cpu", "xnnpack"});
137 TEST_F(GenModelTest, OneOp_DepthwiseConv2D_Dilation_N_Stride)
140 std::vector<float> weight_data{1, 2, 3, 4};
141 uint32_t weight_buf = cgen.addBuffer(weight_data);
142 std::vector<float> bias_data{0, 0, 0, 0};
143 uint32_t bias_buf = cgen.addBuffer(bias_data);
144 int in = cgen.addTensor({{1, 6, 6, 1}, circle::TensorType::TensorType_FLOAT32});
145 int weight = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
146 int bias = cgen.addTensor({{1, 1, 1, 1}, circle::TensorType::TensorType_FLOAT32, bias_buf});
147 int out = cgen.addTensor({{1, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32});
148 cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 2, 2, 1,
149 circle::ActivationFunctionType_NONE, 3, 3);
150 cgen.setInputsAndOutputs({in}, {out});
152 _context = std::make_unique<GenModelTestContext>(cgen.finish());
153 _context->addTestCase(uniformTCD<float>({{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
154 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
155 {{4, 0, 3, 0, 0, 0, 2, 0, 1}}));
156 _context->setBackends({"acl_cl", "acl_neon", "cpu", "xnnpack", "gpu_cl"});
161 TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_Stride)
164 std::vector<float> weight_data{1, 2, 3, 4, -9, 10, -11, 12, 5, 6, 7, 8, 13, -14, 15, -16};
165 uint32_t weight_buf = cgen.addBuffer(weight_data);
166 std::vector<float> bias_data{1, 2, 3, 4};
167 uint32_t bias_buf = cgen.addBuffer(bias_data);
168 int in = cgen.addTensor({{1, 3, 2, 2}, circle::TensorType::TensorType_FLOAT32});
169 int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
170 int bias = cgen.addTensor({{1, 1, 1, 4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
171 int out = cgen.addTensor({{1, 2, 1, 4}, circle::TensorType::TensorType_FLOAT32});
172 cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 0, 0, 2,
173 circle::ActivationFunctionType_NONE);
174 cgen.setInputsAndOutputs({in}, {out});
176 _context = std::make_unique<GenModelTestContext>(cgen.finish());
177 _context->expectFailModelLoad();
182 TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_Dilation)
185 std::vector<float> weight_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
186 uint32_t weight_buf = cgen.addBuffer(weight_data);
187 std::vector<float> bias_data{0, 0, 0, 0};
188 uint32_t bias_buf = cgen.addBuffer(bias_data);
189 int in = cgen.addTensor({{1, 4, 4, 2}, circle::TensorType::TensorType_FLOAT32});
190 int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
191 int bias = cgen.addTensor({{1, 1, 1, 4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
192 int out = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32});
193 cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1, 2,
194 circle::ActivationFunctionType_NONE, 0, 0);
195 cgen.setInputsAndOutputs({in}, {out});
197 _context = std::make_unique<GenModelTestContext>(cgen.finish());
198 _context->expectFailModelLoad();
203 TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_Type)
206 std::vector<float> weight_data{1, 2, 3, 4, -9, 10, -11, 12, 5, 6, 7, 8, 13, -14, 15, -16};
207 uint32_t weight_buf = cgen.addBuffer(weight_data);
208 std::vector<float> bias_data{1, 2, 3, 4};
209 uint32_t bias_buf = cgen.addBuffer(bias_data);
210 int in = cgen.addTensor({{1, 3, 2, 2}, circle::TensorType::TensorType_FLOAT32});
211 int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
212 int bias = cgen.addTensor({{1, 1, 1, 4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
213 int out = cgen.addTensor({{1, 2, 1, 4}, circle::TensorType::TensorType_UINT8});
214 cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1, 2,
215 circle::ActivationFunctionType_NONE);
216 cgen.setInputsAndOutputs({in}, {out});
218 _context = std::make_unique<GenModelTestContext>(cgen.finish());
219 _context->expectFailModelLoad();
224 // Generate a model for negative test cases
225 CircleBuffer genNegTestDepthwiseConv2DModel(circle::Padding padding, int stride_w, int stride_h,
226 int depth_multiplier,
227 circle::ActivationFunctionType actfn)
230 uint32_t ker_buf = cgen.addBuffer(std::vector<uint8_t>{0, 1, 2, 3, 0, 1, 2, 3});
231 uint32_t bias_buf = cgen.addBuffer(std::vector<int32_t>{0, 0});
232 int in = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType_UINT8}, 0.5, 0);
233 int ker = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType_UINT8, ker_buf}, 0.5, 0);
234 int bias = cgen.addTensor({{2}, circle::TensorType_INT32, bias_buf}, 0.25, 0);
235 int out = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType_UINT8}, 1, 0);
236 cgen.addOperatorDepthwiseConv2D({{in, ker, bias}, {out}}, padding, stride_w, stride_h,
237 depth_multiplier, actfn, 0, 0);
238 cgen.setInputsAndOutputs({in}, {out});
239 return cgen.finish();
242 template <typename T> struct DepthwiseConv2DQuantTestParam
244 int stride = 1; // Used for both height and width
246 int depth_multiplier = 1;
247 std::vector<T> ref_output;
250 template <typename T>
251 class DepthwiseConv2DQuantTest
252 : public GenModelTest,
253 public ::testing::WithParamInterface<DepthwiseConv2DQuantTestParam<T>>
257 using DepthwiseConv2DQuantTestParamU8 = DepthwiseConv2DQuantTestParam<uint8_t>;
258 using DepthwiseConv2DQuantTestU8 = DepthwiseConv2DQuantTest<uint8_t>;
260 // Test with different InputDepth and DepthMultiplier. The values are intended to test optimized CPU
262 INSTANTIATE_TEST_CASE_P(
263 GenModelTest, DepthwiseConv2DQuantTestU8,
266 DepthwiseConv2DQuantTestParamU8{1, 8, 1, std::vector<uint8_t>{0, 3, 5, 8, 0, 3, 5, 8}},
267 DepthwiseConv2DQuantTestParamU8{1, 4, 2, std::vector<uint8_t>{0, 0, 2, 3, 0, 2, 6, 9}},
268 DepthwiseConv2DQuantTestParamU8{
269 1, 2, 8, std::vector<uint8_t>{0, 1, 2, 3, 0, 1, 2, 3, 0, 2, 4, 6, 0, 2, 4, 6}},
270 DepthwiseConv2DQuantTestParamU8{1, 2, 2, std::vector<uint8_t>{0, 1, 4, 6}},
271 DepthwiseConv2DQuantTestParamU8{1, 2, 1, std::vector<uint8_t>{2, 5}},
272 DepthwiseConv2DQuantTestParamU8{1, 1, 2, std::vector<uint8_t>{2, 4}},
273 DepthwiseConv2DQuantTestParamU8{1, 1, 4, std::vector<uint8_t>{0, 2, 3, 5}},
274 DepthwiseConv2DQuantTestParamU8{1, 4, 1, std::vector<uint8_t>{0, 1, 4, 9}},
275 DepthwiseConv2DQuantTestParamU8{
276 1, 4, 4, std::vector<uint8_t>{0, 0, 0, 0, 0, 1, 2, 3, 0, 2, 4, 6, 0, 3, 6, 9}},
277 DepthwiseConv2DQuantTestParamU8{1, 12, 1,
278 std::vector<uint8_t>{0, 3, 7, 12, 0, 4, 7, 12, 0, 4, 9, 16}},
280 DepthwiseConv2DQuantTestParamU8{2, 4, 1, std::vector<uint8_t>{0, 1, 4, 9}},
281 DepthwiseConv2DQuantTestParamU8{2, 2, 1, std::vector<uint8_t>{2, 5}},
282 DepthwiseConv2DQuantTestParamU8{2, 1, 8, std::vector<uint8_t>{0, 2, 3, 5, 0, 2, 3, 5}},
283 DepthwiseConv2DQuantTestParamU8{2, 1, 32, std::vector<uint8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3,
284 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2,
285 3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
286 DepthwiseConv2DQuantTestParamU8{
287 2, 1, 20, std::vector<uint8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
288 DepthwiseConv2DQuantTestParamU8{
289 2, 1, 16, std::vector<uint8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
290 DepthwiseConv2DQuantTestParamU8{2, 8, 1, std::vector<uint8_t>{0, 3, 5, 8, 0, 3, 5, 8}},
291 DepthwiseConv2DQuantTestParamU8{
292 2, 8, 2, std::vector<uint8_t>{0, 3, 5, 8, 0, 3, 5, 8, 0, 3, 5, 8, 0, 3, 5, 8}},
293 DepthwiseConv2DQuantTestParamU8{
294 2, 16, 1, std::vector<uint8_t>{0, 3, 8, 16, 0, 4, 7, 12, 0, 3, 7, 13, 0, 4, 7, 12}}));
296 CircleBuffer genDepthwiseConv2DQuantU8Model(int stride, int input_depth, int depth_multiplier)
298 assert(1 <= stride && stride <= 2);
299 assert(1 <= input_depth && input_depth <= 16);
300 assert(1 <= depth_multiplier && depth_multiplier <= 32);
302 const int output_depth = input_depth * depth_multiplier;
303 assert(1 <= output_depth && output_depth <= 32);
306 uint32_t ker_buf = cgen.addBuffer(std::vector<uint8_t>{
307 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1,
308 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
309 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1,
310 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
311 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3});
312 uint32_t bias_buf = cgen.addBuffer(std::vector<int32_t>(output_depth, 0));
313 int in = cgen.addTensor({{1, 2, 2, input_depth}, circle::TensorType_UINT8}, 0.5, 0);
314 int ker = cgen.addTensor({{1, 2, 2, output_depth}, circle::TensorType_UINT8, ker_buf}, 0.5, 0);
315 int bias = cgen.addTensor({{output_depth}, circle::TensorType_INT32, bias_buf}, 0.25, 0);
316 int out = cgen.addTensor({{1, 1, 1, output_depth}, circle::TensorType_UINT8}, 1, 0);
317 cgen.addOperatorDepthwiseConv2D({{in, ker, bias}, {out}}, circle::Padding::Padding_VALID, stride,
318 stride, depth_multiplier, circle::ActivationFunctionType_NONE);
319 cgen.setInputsAndOutputs({in}, {out});
320 return cgen.finish();
323 TEST_P(DepthwiseConv2DQuantTestU8, Test)
325 // Same input is used for all tests but output differs
326 static const std::vector<uint8_t> input64{
327 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2,
328 2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8, 2, 3, 5, 8, 8, 5, 3, 2, 1, 2, 3, 4, 5, 4, 3, 2};
330 auto ¶m = GetParam();
331 _context = std::make_unique<GenModelTestContext>(
332 genDepthwiseConv2DQuantU8Model(param.stride, param.input_depth, param.depth_multiplier));
333 std::vector<uint8_t> ref_input(input64.begin(), input64.begin() + param.input_depth * 4);
334 _context->addTestCase(uniformTCD<uint8_t>({ref_input}, {param.ref_output}));
335 _context->setBackends({"acl_cl", "acl_neon", "cpu"});
340 using DepthwiseConv2DQuantTestParamI8 = DepthwiseConv2DQuantTestParam<int8_t>;
341 using DepthwiseConv2DQuantTestI8 = DepthwiseConv2DQuantTest<int8_t>;
343 // Test with different InputDepth and DepthMultiplier. The values are intended to test optimized CPU
345 INSTANTIATE_TEST_CASE_P(
346 GenModelTest, DepthwiseConv2DQuantTestI8,
349 DepthwiseConv2DQuantTestParamI8{1, 8, 1, std::vector<int8_t>{0, 3, 5, 8, 0, 3, 5, 8}},
350 DepthwiseConv2DQuantTestParamI8{1, 4, 2, std::vector<int8_t>{0, 0, 2, 3, 0, 2, 6, 9}},
351 DepthwiseConv2DQuantTestParamI8{
352 1, 2, 8, std::vector<int8_t>{0, 1, 2, 3, 0, 1, 2, 3, 0, 2, 4, 6, 0, 2, 4, 6}},
353 DepthwiseConv2DQuantTestParamI8{1, 2, 2, std::vector<int8_t>{0, 1, 4, 6}},
354 DepthwiseConv2DQuantTestParamI8{1, 2, 1, std::vector<int8_t>{2, 5}},
355 DepthwiseConv2DQuantTestParamI8{1, 1, 2, std::vector<int8_t>{2, 4}},
356 DepthwiseConv2DQuantTestParamI8{1, 1, 4, std::vector<int8_t>{0, 2, 3, 5}},
357 DepthwiseConv2DQuantTestParamI8{1, 4, 1, std::vector<int8_t>{0, 1, 4, 9}},
358 DepthwiseConv2DQuantTestParamI8{
359 1, 4, 4, std::vector<int8_t>{0, 0, 0, 0, 0, 1, 2, 3, 0, 2, 4, 6, 0, 3, 6, 9}},
360 DepthwiseConv2DQuantTestParamI8{1, 12, 1,
361 std::vector<int8_t>{0, 3, 7, 12, 0, 4, 7, 12, 0, 4, 9, 16}},
363 DepthwiseConv2DQuantTestParamI8{2, 4, 1, std::vector<int8_t>{0, 1, 4, 9}},
364 DepthwiseConv2DQuantTestParamI8{2, 2, 1, std::vector<int8_t>{2, 5}},
365 DepthwiseConv2DQuantTestParamI8{2, 1, 8, std::vector<int8_t>{0, 2, 3, 5, 0, 2, 3, 5}},
366 DepthwiseConv2DQuantTestParamI8{2, 1, 32, std::vector<int8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3,
367 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2,
368 3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
369 DepthwiseConv2DQuantTestParamI8{
370 2, 1, 20, std::vector<int8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
371 DepthwiseConv2DQuantTestParamI8{
372 2, 1, 16, std::vector<int8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
373 DepthwiseConv2DQuantTestParamI8{2, 8, 1, std::vector<int8_t>{0, 3, 5, 8, 0, 3, 5, 8}},
374 DepthwiseConv2DQuantTestParamI8{
375 2, 8, 2, std::vector<int8_t>{0, 3, 5, 8, 0, 3, 5, 8, 0, 3, 5, 8, 0, 3, 5, 8}},
376 DepthwiseConv2DQuantTestParamI8{
377 2, 16, 1, std::vector<int8_t>{0, 3, 8, 16, 0, 4, 7, 12, 0, 3, 7, 13, 0, 4, 7, 12}}));
379 CircleBuffer genDepthwiseConv2DQuantI8Model(int stride, int input_depth, int depth_multiplier)
381 assert(1 <= stride && stride <= 2);
382 assert(1 <= input_depth && input_depth <= 16);
383 assert(1 <= depth_multiplier && depth_multiplier <= 32);
385 const int output_depth = input_depth * depth_multiplier;
386 assert(1 <= output_depth && output_depth <= 32);
389 uint32_t ker_buf = cgen.addBuffer(std::vector<int8_t>{
390 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1,
391 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
392 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1,
393 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
394 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3});
395 uint32_t bias_buf = cgen.addBuffer(std::vector<int32_t>(output_depth, 0));
396 int in = cgen.addTensor({{1, 2, 2, input_depth}, circle::TensorType_INT8}, 0.5, 0);
397 int ker = cgen.addTensor({{1, 2, 2, output_depth}, circle::TensorType_INT8, ker_buf}, 0.5, 0);
398 int bias = cgen.addTensor({{output_depth}, circle::TensorType_INT32, bias_buf}, 0.25, 0);
399 int out = cgen.addTensor({{1, 1, 1, output_depth}, circle::TensorType_INT8}, 1, 0);
400 cgen.addOperatorDepthwiseConv2D({{in, ker, bias}, {out}}, circle::Padding::Padding_VALID, stride,
401 stride, depth_multiplier, circle::ActivationFunctionType_NONE);
402 cgen.setInputsAndOutputs({in}, {out});
403 return cgen.finish();
406 TEST_P(DepthwiseConv2DQuantTestI8, Test)
408 // Same input is used for all tests but output differs
409 static const std::vector<int8_t> input64{
410 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2,
411 2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8, 2, 3, 5, 8, 8, 5, 3, 2, 1, 2, 3, 4, 5, 4, 3, 2};
413 auto ¶m = GetParam();
414 _context = std::make_unique<GenModelTestContext>(
415 genDepthwiseConv2DQuantI8Model(param.stride, param.input_depth, param.depth_multiplier));
416 std::vector<int8_t> ref_input(input64.begin(), input64.begin() + param.input_depth * 4);
417 _context->addTestCase(uniformTCD<int8_t>({ref_input}, {param.ref_output}));
418 _context->setBackends({"acl_cl", "acl_neon", "cpu"});
423 TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_InvalidPaddingType)
425 _context = std::make_unique<GenModelTestContext>(genNegTestDepthwiseConv2DModel(
426 static_cast<circle::Padding>(99), 1, 1, 1, circle::ActivationFunctionType_NONE));
427 _context->expectFailModelLoad();
428 _context->setBackends({"acl_cl", "acl_neon", "cpu", "xnnpack"});
433 // TODO add other invalid operation tests like above
435 TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_I8_NonZero_ZeroPoints)
438 std::vector<int8_t> weight_data{1, 2, 3, 4, 5, 6, 7, 8};
439 uint32_t weight_buf = cgen.addBuffer(weight_data);
440 std::vector<int32_t> bias_data{0, 2};
441 uint32_t bias_buf = cgen.addBuffer(bias_data);
442 int in = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_INT8}, 0.5, 0);
443 std::vector<float> weight_scales = {0.5, 1};
444 std::vector<int64_t> weight_zeropoints = {0, 10};
445 int weight = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_INT8, weight_buf},
446 weight_scales, weight_zeropoints);
447 int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_INT32, bias_buf});
448 int out = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32}, 1.0, 0);
449 cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1, 2,
450 circle::ActivationFunctionType_NONE);
451 cgen.setInputsAndOutputs({in}, {out});
452 _context = std::make_unique<GenModelTestContext>(cgen.finish());
453 _context->setBackends({"cpu"});
454 _context->expectFailModelLoad();