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"});
42 TEST_F(GenModelTest, OneOp_DepthwiseConv2D_Dilation)
45 std::vector<float> weight_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
46 uint32_t weight_buf = cgen.addBuffer(weight_data);
47 std::vector<float> bias_data{0, 0, 0, 0};
48 uint32_t bias_buf = cgen.addBuffer(bias_data);
49 int in = cgen.addTensor({{1, 4, 4, 2}, circle::TensorType::TensorType_FLOAT32});
50 int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
51 int bias = cgen.addTensor({{1, 1, 1, 4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
52 int out = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32});
53 cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1, 2,
54 circle::ActivationFunctionType_NONE, 2, 2);
55 cgen.setInputsAndOutputs({in}, {out});
57 _context = std::make_unique<GenModelTestContext>(cgen.finish());
58 _context->addTestCase(uniformTCD<float>({{
59 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
60 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62 {{13, 14, 0, 0, 0, 0, 11, 12, 5, 6, 0, 0, 0, 0, 3, 4}}));
63 _context->setBackends({"acl_cl", "acl_neon", "cpu"});
68 TEST_F(GenModelTest, OneOp_DepthwiseConv2D_Dilation_N_Stride)
71 std::vector<float> weight_data{1, 2, 3, 4};
72 uint32_t weight_buf = cgen.addBuffer(weight_data);
73 std::vector<float> bias_data{0, 0, 0, 0};
74 uint32_t bias_buf = cgen.addBuffer(bias_data);
75 int in = cgen.addTensor({{1, 6, 6, 1}, circle::TensorType::TensorType_FLOAT32});
76 int weight = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
77 int bias = cgen.addTensor({{1, 1, 1, 1}, circle::TensorType::TensorType_FLOAT32, bias_buf});
78 int out = cgen.addTensor({{1, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32});
79 cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 2, 2, 1,
80 circle::ActivationFunctionType_NONE, 3, 3);
81 cgen.setInputsAndOutputs({in}, {out});
83 _context = std::make_unique<GenModelTestContext>(cgen.finish());
84 _context->addTestCase(uniformTCD<float>({{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
85 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
86 {{4, 0, 3, 0, 0, 0, 2, 0, 1}}));
87 _context->setBackends({"acl_cl", "acl_neon", "cpu"});
92 TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_Stride)
95 std::vector<float> weight_data{1, 2, 3, 4, -9, 10, -11, 12, 5, 6, 7, 8, 13, -14, 15, -16};
96 uint32_t weight_buf = cgen.addBuffer(weight_data);
97 std::vector<float> bias_data{1, 2, 3, 4};
98 uint32_t bias_buf = cgen.addBuffer(bias_data);
99 int in = cgen.addTensor({{1, 3, 2, 2}, circle::TensorType::TensorType_FLOAT32});
100 int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
101 int bias = cgen.addTensor({{1, 1, 1, 4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
102 int out = cgen.addTensor({{1, 2, 1, 4}, circle::TensorType::TensorType_FLOAT32});
103 cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 0, 0, 2,
104 circle::ActivationFunctionType_NONE);
105 cgen.setInputsAndOutputs({in}, {out});
107 _context = std::make_unique<GenModelTestContext>(cgen.finish());
108 _context->expectFailModelLoad();
113 TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_Dilation)
116 std::vector<float> weight_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
117 uint32_t weight_buf = cgen.addBuffer(weight_data);
118 std::vector<float> bias_data{0, 0, 0, 0};
119 uint32_t bias_buf = cgen.addBuffer(bias_data);
120 int in = cgen.addTensor({{1, 4, 4, 2}, circle::TensorType::TensorType_FLOAT32});
121 int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
122 int bias = cgen.addTensor({{1, 1, 1, 4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
123 int out = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32});
124 cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1, 2,
125 circle::ActivationFunctionType_NONE, 0, 0);
126 cgen.setInputsAndOutputs({in}, {out});
128 _context = std::make_unique<GenModelTestContext>(cgen.finish());
129 _context->expectFailModelLoad();
134 TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_Type)
137 std::vector<float> weight_data{1, 2, 3, 4, -9, 10, -11, 12, 5, 6, 7, 8, 13, -14, 15, -16};
138 uint32_t weight_buf = cgen.addBuffer(weight_data);
139 std::vector<float> bias_data{1, 2, 3, 4};
140 uint32_t bias_buf = cgen.addBuffer(bias_data);
141 int in = cgen.addTensor({{1, 3, 2, 2}, circle::TensorType::TensorType_FLOAT32});
142 int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
143 int bias = cgen.addTensor({{1, 1, 1, 4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
144 int out = cgen.addTensor({{1, 2, 1, 4}, circle::TensorType::TensorType_UINT8});
145 cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1, 2,
146 circle::ActivationFunctionType_NONE);
147 cgen.setInputsAndOutputs({in}, {out});
149 _context = std::make_unique<GenModelTestContext>(cgen.finish());
150 _context->expectFailModelLoad();
155 // Generate a model for negative test cases
156 CircleBuffer genNegTestDepthwiseConv2DModel(circle::Padding padding, int stride_w, int stride_h,
157 int depth_multiplier,
158 circle::ActivationFunctionType actfn)
161 uint32_t ker_buf = cgen.addBuffer(std::vector<uint8_t>{0, 1, 2, 3, 0, 1, 2, 3});
162 uint32_t bias_buf = cgen.addBuffer(std::vector<int32_t>{0, 0});
163 int in = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType_UINT8}, 0.5, 0);
164 int ker = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType_UINT8, ker_buf}, 0.5, 0);
165 int bias = cgen.addTensor({{2}, circle::TensorType_INT32, bias_buf}, 0.25, 0);
166 int out = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType_UINT8}, 1, 0);
167 cgen.addOperatorDepthwiseConv2D({{in, ker, bias}, {out}}, padding, stride_w, stride_h,
168 depth_multiplier, actfn, 0, 0);
169 cgen.setInputsAndOutputs({in}, {out});
170 return cgen.finish();
173 CircleBuffer genSimpleDepthwiseConv2DQuantizedModel(int stride, int input_depth,
174 int depth_multiplier)
176 assert(1 <= stride && stride <= 2);
177 assert(1 <= input_depth && input_depth <= 16);
178 assert(1 <= depth_multiplier && depth_multiplier <= 32);
180 const int output_depth = input_depth * depth_multiplier;
181 assert(1 <= output_depth && output_depth <= 32);
184 uint32_t ker_buf = cgen.addBuffer(std::vector<uint8_t>{
185 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,
186 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,
187 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,
188 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,
189 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3});
190 uint32_t bias_buf = cgen.addBuffer(std::vector<int32_t>(output_depth, 0));
191 int in = cgen.addTensor({{1, 2, 2, input_depth}, circle::TensorType_UINT8}, 0.5, 0);
192 int ker = cgen.addTensor({{1, 2, 2, output_depth}, circle::TensorType_UINT8, ker_buf}, 0.5, 0);
193 int bias = cgen.addTensor({{output_depth}, circle::TensorType_INT32, bias_buf}, 0.25, 0);
194 int out = cgen.addTensor({{1, 1, 1, output_depth}, circle::TensorType_UINT8}, 1, 0);
195 cgen.addOperatorDepthwiseConv2D({{in, ker, bias}, {out}}, circle::Padding::Padding_VALID, stride,
196 stride, depth_multiplier, circle::ActivationFunctionType_NONE);
197 cgen.setInputsAndOutputs({in}, {out});
198 return cgen.finish();
201 struct DepthwiseConv2DVariationParam
203 int stride = 1; // Used for both height and width
205 int depth_multiplier = 1;
206 std::vector<uint8_t> ref_output;
209 class DepthwiseConv2DVariation : public GenModelTest,
210 public ::testing::WithParamInterface<DepthwiseConv2DVariationParam>
214 TEST_P(DepthwiseConv2DVariation, Test)
216 // Same input is used for all tests but output differs
217 static const std::vector<uint8_t> input64{0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
218 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2,
219 2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8,
220 2, 3, 5, 8, 8, 5, 3, 2, 1, 2, 3, 4, 5, 4, 3, 2};
222 auto ¶m = GetParam();
223 _context = std::make_unique<GenModelTestContext>(genSimpleDepthwiseConv2DQuantizedModel(
224 param.stride, param.input_depth, param.depth_multiplier));
225 std::vector<uint8_t> ref_input(input64.begin(), input64.begin() + param.input_depth * 4);
226 _context->addTestCase(uniformTCD<uint8_t>({ref_input}, {param.ref_output}));
227 _context->setBackends({"acl_cl", "acl_neon", "cpu"});
232 // Test with different InputDepth and DepthMultiplier. The values are intended to test optimized CPU
234 INSTANTIATE_TEST_CASE_P(
235 GenModelTest, DepthwiseConv2DVariation,
238 DepthwiseConv2DVariationParam{1, 8, 1, std::vector<uint8_t>{0, 3, 5, 8, 0, 3, 5, 8}},
239 DepthwiseConv2DVariationParam{1, 4, 2, std::vector<uint8_t>{0, 0, 2, 3, 0, 2, 6, 9}},
240 DepthwiseConv2DVariationParam{
241 1, 2, 8, std::vector<uint8_t>{0, 1, 2, 3, 0, 1, 2, 3, 0, 2, 4, 6, 0, 2, 4, 6}},
242 DepthwiseConv2DVariationParam{1, 2, 2, std::vector<uint8_t>{0, 1, 4, 6}},
243 DepthwiseConv2DVariationParam{1, 2, 1, std::vector<uint8_t>{2, 5}},
244 DepthwiseConv2DVariationParam{1, 1, 2, std::vector<uint8_t>{2, 4}},
245 DepthwiseConv2DVariationParam{1, 1, 4, std::vector<uint8_t>{0, 2, 3, 5}},
246 DepthwiseConv2DVariationParam{1, 4, 1, std::vector<uint8_t>{0, 1, 4, 9}},
247 DepthwiseConv2DVariationParam{
248 1, 4, 4, std::vector<uint8_t>{0, 0, 0, 0, 0, 1, 2, 3, 0, 2, 4, 6, 0, 3, 6, 9}},
249 DepthwiseConv2DVariationParam{1, 12, 1,
250 std::vector<uint8_t>{0, 3, 7, 12, 0, 4, 7, 12, 0, 4, 9, 16}},
252 DepthwiseConv2DVariationParam{2, 4, 1, std::vector<uint8_t>{0, 1, 4, 9}},
253 DepthwiseConv2DVariationParam{2, 2, 1, std::vector<uint8_t>{2, 5}},
254 DepthwiseConv2DVariationParam{2, 1, 8, std::vector<uint8_t>{0, 2, 3, 5, 0, 2, 3, 5}},
255 DepthwiseConv2DVariationParam{
256 2, 1, 32, std::vector<uint8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5,
257 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
258 DepthwiseConv2DVariationParam{2, 1, 20, std::vector<uint8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2,
259 3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
260 DepthwiseConv2DVariationParam{
261 2, 1, 16, std::vector<uint8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
262 DepthwiseConv2DVariationParam{2, 8, 1, std::vector<uint8_t>{0, 3, 5, 8, 0, 3, 5, 8}},
263 DepthwiseConv2DVariationParam{
264 2, 8, 2, std::vector<uint8_t>{0, 3, 5, 8, 0, 3, 5, 8, 0, 3, 5, 8, 0, 3, 5, 8}},
265 DepthwiseConv2DVariationParam{
266 2, 16, 1, std::vector<uint8_t>{0, 3, 8, 16, 0, 4, 7, 12, 0, 3, 7, 13, 0, 4, 7, 12}}));
268 TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_InvalidPaddingType)
270 _context = std::make_unique<GenModelTestContext>(genNegTestDepthwiseConv2DModel(
271 static_cast<circle::Padding>(99), 1, 1, 1, circle::ActivationFunctionType_NONE));
272 _context->expectFailModelLoad();
273 _context->setBackends({"acl_cl", "acl_neon", "cpu"});
278 // TODO add other invalid operation tests like above