2 // Copyright (c) 2019 Intel Corporation
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 ///////////////////////////////////////////////////////////////////////////////////////////////////
19 #include <gtest/gtest.h>
20 #include <api/CPP/memory.hpp>
21 #include <api/CPP/input_layout.hpp>
22 #include "api/CPP/binary_convolution.hpp"
23 #include "api/CPP/reorder.hpp"
24 #include <api/CPP/topology.hpp>
25 #include <api/CPP/network.hpp>
26 #include <api/CPP/engine.hpp>
27 #include "test_utils/test_utils.h"
29 #include <api/CPP/data.hpp>
30 #include <src/include/to_string_utils.h>
32 #include "test_utils.h"
34 using namespace cldnn;
35 using namespace tests;
37 // Batch, groups, IC, IW, IH, OC, OW, OH, KH, KW, SH, SW, PH, PW
63 bool isConsistent() const
67 res &= (((iw - kw + 2*pw) / sw + 1) == ow);
68 res &= (((ih - kh + 2*ph) / sh + 1) == oh);
72 friend ::std::ostream& operator<<(::std::ostream& os, const TestParams& p) {
73 return os << "Params: [ b=" << p.b
75 << "; src=[" << p.ic << "; " << p.ih << "; " << p.iw << "]"
76 << "; dst=[" << p.oc << "; " << p.oh << "; " << p.ow << "]"
77 << "; k=[" << p.kh << "; " << p.kw << "]"
78 << "; stride=[" << p.sh << "; " << p.sw << "]"
79 << "; pad=[" << p.ph << "; " << p.pw << "]"
80 << "; pad_value=" << p.pad_value
81 << "; name=" << p.name
84 friend void PrintTo(const TestParams& p, ::std::ostream* os) {
89 static void fill(cldnn::memory& mem) {
90 auto ptr = mem.pointer<uint32_t>();
91 for (size_t i = 0; i < div_up(mem.get_layout().count(), 32); i++) {
92 ptr[i] = (uint32_t)rand() % (1 << 31);
96 template <typename data_t_src, typename data_t_wei,
97 typename data_t_acc, typename data_t_dst>
98 void compute_ref_conv_bin(const cldnn::memory &src,
99 const cldnn::memory &weights,
103 auto src_data = src.pointer<data_t_src>();
104 auto weights_data = weights.pointer<data_t_wei>();
105 auto dst_data = dst.pointer<data_t_dst>();
107 bool with_groups = p.g > 1;
108 int pack_size = sizeof(data_t_src) * 8;
130 auto extract_bit = [&](data_t_src val, data_t_src bit) -> data_t_src {
131 return (data_t_src)((val >> bit) & 0x1);
134 auto ker = [=](data_t_acc &d, int g, int mb, int oc,int oh, int ow, int& ks) {
135 for (int ic = 0; ic < IC / NG; ++ic) {
136 for (int kh = 0; kh < KH; ++kh)
137 for (int kw = 0; kw < KW; ++kw) {
138 const int ih = oh * SH - PH + kh;
139 const int iw = ow * SW - PW + kw;
141 int widx = g * OC / NG *IC / NG * KH * KW
142 + oc * IC / NG * KH * KW
147 uint8_t w = extract_bit(weights_data[widx / pack_size], widx % pack_size);
150 if ((ih < 0 || ih >= IH || iw < 0 || iw >= IW))
152 if (p.pad_value == 0.0f)
155 s = (p.pad_value == -1.0f) ? 0 : 1;
160 iidx = mb * div_up(IC, pack_size) * IH * IW
161 + g * div_up(IC, pack_size) / NG * IH * IW
162 + (ic/pack_size) * IH * IW
166 s = extract_bit(src_data[iidx], ic % pack_size);
168 d += (data_t_acc)(s ^ w);
173 for (int g = 0; g < NG; g++) {
174 for (int b = 0; b < B; b++) {
175 for (int oc = 0; oc < OC / NG; oc++) {
176 for (int oh = 0; oh < OH; oh++) {
177 for (int ow = 0; ow < OW; ow++) {
180 ker(a, g, b, oc, oh, ow, ks);
181 int dst_off = b * OC * OH* OW
182 + g * OC / NG * OH * OW
186 if (p.pad_value == 0.0f)
187 dst_data[dst_off] =(data_t_dst)(IC*ks - 2*a);
189 dst_data[dst_off] = (data_t_dst)(IC*KH*KW - 2*a);
197 class binary_convolution_test : public ::testing::TestWithParam<TestParams>
201 std::cout << GetParam() << std::endl;
202 ASSERT_TRUE(GetParam().isConsistent());
206 TEST_P(binary_convolution_test, conv)
208 const auto& engine = get_test_engine();
209 cldnn::build_options options;
210 options.set_option(cldnn::build_option::optimize_data(true));
211 topology topology_bin;
213 std::string weights_suffix = "_w_";
215 std::string input_name = "input";
216 std::string output_name = "conv";
218 TestParams p = GetParam();
220 cldnn::tensor stride = cldnn::tensor{cldnn::batch(1), cldnn::feature(1), cldnn::spatial(p.sw, p.sh)};
221 cldnn::tensor pad = cldnn::tensor{cldnn::batch(0), cldnn::feature(0), cldnn::spatial(-p.pw, -p.ph)};
222 cldnn::tensor dilation = {1,1,1,1};
224 cldnn::tensor is_size{ cldnn::batch(p.b),
225 cldnn::feature(p.ic),
226 cldnn::spatial(p.iw, p.ih) };
227 cldnn::tensor wei_size{ cldnn::batch(p.oc),
228 cldnn::feature(p.ic),
229 cldnn::spatial(p.kw, p.kh) };
230 cldnn::tensor os_size{ cldnn::batch(p.b),
231 cldnn::feature(p.oc),
232 cldnn::spatial(p.ow, p.oh)};
234 auto input = memory::allocate(engine, { cldnn::data_types::bin, cldnn::format::b_fs_yx_32fp, is_size });
235 auto weights = memory::allocate(engine, { cldnn::data_types::bin, cldnn::format::bfyx, wei_size });
236 auto output_ref = memory::allocate(engine, { cldnn::data_types::f32, cldnn::format::bfyx, os_size });
241 compute_ref_conv_bin<uint32_t, uint32_t, int32_t, float>(input, weights, output_ref, p);
243 // print_bin_blob(input,"input");
244 // print_bin_blob_packed(input,"input");
245 // print_bin_blob(weights, "weights");
246 // print_blob(output_ref, "ref_out");
248 topology_bin.add(input_layout(input_name, input.get_layout()));
249 topology_bin.add(data(output_name + weights_suffix, weights));
251 topology_bin.add(binary_convolution(output_name, input_name, {output_name + weights_suffix},
252 stride, pad, dilation, os_size, 1, p.pad_value, p.dt));
254 network network_bin(engine, topology_bin, options);
255 network_bin.set_input_data(input_name, input);
257 std::map<primitive_id, network_output> outputs = network_bin.execute();
258 auto outputMemory = outputs.at(output_name).get_memory();
261 for (size_t i = 0; i < output_ref.count(); i++) {
262 if (p.dt == data_types::f32)
264 auto ref = output_ref.pointer<float>();
265 auto opt = outputMemory.pointer<float>();
267 ASSERT_EQ(ref[i], opt[i]) << i;
269 else if (p.dt == data_types::f16)
271 auto ref = output_ref.pointer<float>();
272 auto opt = outputMemory.pointer<uint16_t>();
274 ASSERT_EQ(ref[i], float16_to_float32(opt[i])) << i;
279 // Batch, groups, IC, IW, IH, OC, OW, OH, KH, KW, SH, SW, PH, PW
280 INSTANTIATE_TEST_CASE_P(BinaryConvTest, binary_convolution_test, ::testing::Values(
281 TestParams{1, 1, 16,2,2, 4,2,2, 3,3, 1,1, 1,1, -1.0f, data_types::f32, "small"},
282 TestParams{1, 1, 17,2,2, 4,2,2, 3,3, 1,1, 1,1, -1.0f, data_types::f32, "small"},
283 TestParams{1, 1, 17,2,2, 4,2,2, 3,3, 1,1, 1,1, 0.0f, data_types::f32, "small"},
284 TestParams{1, 1, 17,2,2, 4,2,2, 3,3, 1,1, 1,1, 1.0f, data_types::f32, "small"},
285 TestParams{1, 1, 16,2,2, 16,2,2, 3,3, 1,1, 1,1, 1.0f, data_types::f32, "small"},
286 TestParams{1, 1, 32,2,2, 32,2,2, 3,3, 1,1, 1,1, 1.0f, data_types::f32, "small"},
287 TestParams{1, 1, 32,2,2, 32,2,2, 1,1, 1,1, 0,0, 1.0f, data_types::f32, "small"},
288 TestParams{1, 1, 128,2,2, 128,2,2, 1,1, 1,1, 0,0, -1.0f, data_types::f32, "small"},
289 TestParams{1, 1, 16,4,3, 4,4,3, 1,1, 1,1, 0,0, -1.0f, data_types::f32, "small"},
290 TestParams{1, 1, 16,2,2, 4,2,2, 3,3, 1,1, 1,1, -1.0f, data_types::f16, "small"},
291 TestParams{1, 1, 17,2,2, 4,2,2, 3,3, 1,1, 1,1, -1.0f, data_types::f16, "small"},
292 TestParams{1, 1, 17,2,2, 4,2,2, 3,3, 1,1, 1,1, 0.0f, data_types::f16, "small"},
293 TestParams{1, 1, 17,2,2, 4,2,2, 3,3, 1,1, 1,1, 1.0f, data_types::f16, "small"},
294 TestParams{1, 1, 16,2,2, 16,2,2, 3,3, 1,1, 1,1, 1.0f, data_types::f16, "small"},
295 TestParams{1, 1, 32,2,2, 32,2,2, 3,3, 1,1, 1,1, 1.0f, data_types::f16, "small"},
296 TestParams{1, 1, 32,2,2, 32,2,2, 1,1, 1,1, 0,0, 1.0f, data_types::f16, "small"},
297 TestParams{1, 1, 128,2,2, 128,2,2, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "small"},
298 TestParams{1, 1, 16,4,3, 4,4,3, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "small"},
299 TestParams{1, 1, 9,16,32, 17,8,16, 7,7, 2,2, 3,3, -1.0f, data_types::f16, "small"},
300 TestParams{1, 1, 9,16,32, 17,8,16, 7,7, 2,2, 3,3, 1.0f, data_types::f16, "small"},
303 TestParams{1, 1, 64,56,56, 64,56,56, 3,3, 1,1, 1,1, -1.0f, data_types::f16, "resnet18_0"},
304 TestParams{1, 1, 64,56,56, 128,28,28, 3,3, 2,2, 1,1, -1.0f, data_types::f16, "resnet18_1"},
305 TestParams{1, 1, 128,28,28, 128,28,28, 3,3, 1,1, 1,1, -1.0f, data_types::f16, "resnet18_2"},
306 TestParams{1, 1, 128,28,28, 256,14,14, 3,3, 2,2, 1,1, -1.0f, data_types::f16, "resnet18_3"},
307 TestParams{1, 1, 256,14,14, 256,14,14, 3,3, 1,1, 1,1, -1.0f, data_types::f16, "resnet18_4"},
308 TestParams{1, 1, 256,14,14, 512, 7, 7, 3,3, 2,2, 1,1, -1.0f, data_types::f16, "resnet18_5"},
309 TestParams{1, 1, 512, 7, 7, 512, 7, 7, 3,3, 1,1, 1,1, -1.0f, data_types::f16, "resnet18_6"},
311 TestParams{1, 1, 64,56,56, 64,56,56, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "resnet50_0"},
312 TestParams{1, 1, 64,56,56, 256,56,56, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "resnet50_1"},
313 TestParams{1, 1, 256,56,56, 128,28,28, 1,1, 2,2, 0,0, -1.0f, data_types::f16, "resnet50_2"},
314 TestParams{1, 1, 128,28,28, 512,28,28, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "resnet50_3"},
315 TestParams{1, 1, 512,28,28, 128,28,28, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "resnet50_4"},
316 TestParams{1, 1, 512,28,28, 256,14,14, 1,1, 2,2, 0,0, -1.0f, data_types::f16, "resnet50_5"},
317 TestParams{1, 1, 256,14,14, 1024,14,14, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "resnet50_6"},
318 TestParams{1, 1, 1024,14,14, 256,14,14, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "resnet50_7"},
319 TestParams{1, 1, 1024,14,14, 512,7,7, 1,1, 2,2, 0,0, -1.0f, data_types::f16, "resnet50_8"},
320 TestParams{1, 1, 512,7,7, 2048,7,7, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "resnet50_9"},
321 TestParams{1, 1, 2048,7,7, 512,7,7, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "resnet50_10"},
323 TestParams{1, 1, 56,96,168, 112,96,168, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "conv2_2_sep_BIN"}, // back_bone_seq_conv2_2_sep_BIN
324 TestParams{1, 1, 112,96,168, 112,96,168, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "conv3_1_sep_BIN"}, // back_bone_seq_conv3_1_sep_BIN
325 TestParams{1, 1, 112,48,84, 208,48, 84, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "conv3_2_sep_BIN"}, // back_bone_seq_conv3_2_sep_BIN
326 TestParams{1, 1, 208,48,84, 216,48, 84, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "conv4_1_sep_BIN"}, // back_bone_seq_conv4_1_sep_BIN
327 TestParams{1, 1, 216,24,42, 328,24, 42, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "conv4_2_sep_BIN"}, // back_bone_seq_conv4_2_sep_BIN
328 TestParams{1, 1, 328,24,42, 288,24, 42, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "conv5_1_sep_BIN"}, // back_bone_seq_conv5_1_sep_BIN
329 TestParams{1, 1, 288,24,42, 288,24, 42, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "conv5_2_sep_BIN"}, // back_bone_seq_conv5_2_sep_BIN
330 TestParams{1, 1, 288,24,42, 240,24, 42, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "conv5_3_sep_BIN"}, // back_bone_seq_conv5_3_sep_BIN
331 TestParams{1, 1, 240,24,42, 264,24, 42, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "conv5_4_sep_BIN"}, // back_bone_seq_conv5_4_sep_BIN
332 TestParams{1, 1, 264,24,42, 192,24, 42, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "conv5_5_sep_BIN"}, // back_bone_seq_conv5_5_sep_BIN
333 TestParams{1, 1, 192,12,21, 208,12, 21, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "conv5_6_sep_BIN"}, // back_bone_seq_conv5_6_sep_BIN
334 TestParams{1, 1, 208,12,21, 88,12, 21, 1,1, 1,1, 0,0, -1.0f, data_types::f16, "conv6_sep_BN"} // back_bone_seq_conv6_sep_BN
337 template <typename T>
338 static void set_binary_values(const cldnn::memory& mem, std::vector<T> args) {
339 auto ptr = mem.pointer<T>();
341 auto it = ptr.begin();
346 TEST(binary_convolution, basic_convolution_1x1_single_packed_channel)
348 const auto& engine = get_test_engine();
350 auto input = memory::allocate(engine, { data_types::bin, format::b_fs_yx_32fp, { 1, 16, 2, 2 } });
351 auto weights = memory::allocate(engine, { data_types::bin, format::bfyx, { 4, 16, 1, 1 } });
353 // 0 0 1 0 0 1 0 0 1 0 1 0 1 0 1 0
354 // 1 0 0 0 0 1 1 0 0 1 1 0 1 0 1 0
355 // 1 1 0 0 1 0 1 1 1 1 1 1 1 0 1 0
356 // 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
357 set_binary_values<uint32_t>(input, { 21796, 22113, 24531, 32768 });
359 // 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
360 // 0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0
361 // 1 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1
362 // 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
363 set_binary_values<uint16_t>(weights, { 65535, 21930, 43605, 0 });
365 // 16 - 2*popcount(1 1 0 1 1 0 1 1 0 1 0 1 0 1 0 1) = -4
366 // 16 - 2*popcount(0 1 1 1 1 0 0 1 1 0 0 1 0 1 0 1) = -2
367 // 16 - 2*popcount(0 0 1 1 0 1 0 0 0 0 0 0 0 1 0 1) = 6
368 // 16 - 2*popcount(1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0) = -14
370 // 16 - 2*popcount(0 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0) = 8
371 // 16 - 2*popcount(1 1 0 1 0 0 1 1 1 1 0 0 0 0 0 0) = 2
372 // 16 - 2*popcount(1 0 0 1 1 1 1 0 0 1 0 1 0 0 0 0) = 2
373 // 16 - 2*popcount(0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 1) = -2
375 // 16 - 2*popcount(1 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1) = -8
376 // 16 - 2*popcount(0 0 1 0 1 1 0 0 0 0 1 1 1 1 1 1) = -2
377 // 16 - 2*popcount(0 1 1 0 0 0 0 1 1 0 1 0 1 1 1 1) = -2
378 // 16 - 2*popcount(1 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0) = 2
380 // 16 - 2*popcount(0 0 1 0 0 1 0 0 1 0 1 0 1 0 1 0) = 4
381 // 16 - 2*popcount(1 0 0 0 0 1 1 0 0 1 1 0 1 0 1 0) = 2
382 // 16 - 2*popcount(1 1 0 0 1 0 1 1 1 1 1 1 1 0 1 0) = -6
383 // 16 - 2*popcount(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1) = 14
384 VF<float> output_vec = {
385 -4.0f, -2.0f, 6.0f, -14.0f,
386 8.0f, 2.0f, 2.0f, -2.0f,
387 -8.0f, -2.0f, -2.0f, 2.0f,
388 4.0f, 2.0f, -6.0f, 14.0f };
391 input_layout("input", input.get_layout()),
392 data("weights", weights),
393 binary_convolution("binary_conv", "input", { "weights" },
400 padding{ { 0,0,0,0 }, 0 })
403 cldnn::build_options options;
404 options.set_option(cldnn::build_option::optimize_data(true));
406 network network(engine, topology, options);
407 network.set_input_data("input", input);
409 auto outputs = network.execute();
410 EXPECT_EQ(outputs.size(), size_t(1));
411 EXPECT_EQ(outputs.begin()->first, "binary_conv");
413 auto output_memory = outputs.at("binary_conv").get_memory();
414 auto output_layout = output_memory.get_layout();
415 auto output_ptr = output_memory.pointer<float>();
418 EXPECT_EQ(output_layout.format, format::bfyx);
419 EXPECT_EQ(output_layout.data_type, data_types::f32);
420 EXPECT_EQ(output_layout.size.batch[0], 1);
421 EXPECT_EQ(output_layout.size.feature[0], 4);
422 EXPECT_EQ(output_layout.size.spatial[1], 2);
423 EXPECT_EQ(output_layout.size.spatial[0], 2);
425 for (size_t i = 0; i < output_layout.count(); i++)
427 EXPECT_EQ(output_ptr[i], output_vec[i]) << "index="<< i;
432 TEST(binary_convolution, basic_convolution_1x1_single_packed_channel_fp16) {
433 const auto& engine = get_test_engine();
435 auto input = memory::allocate(engine, { data_types::bin, format::b_fs_yx_32fp, { 1, 16, 2, 2 } });
436 auto weights = memory::allocate(engine, { data_types::bin, format::bfyx, { 4, 16, 1, 1 } });
438 // 0 0 1 0 0 1 0 0 1 0 1 0 1 0 1 0
439 // 1 0 0 0 0 1 1 0 0 1 1 0 1 0 1 0
440 // 1 1 0 0 1 0 1 1 1 1 1 1 1 0 1 0
441 // 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
442 set_binary_values<uint32_t>(input, { 21796, 22113, 24531, 32768 });
444 // 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
445 // 0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0
446 // 1 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1
447 // 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
448 set_binary_values<uint16_t>(weights, { 65535, 21930, 43605, 0 });
450 // 16 - 2*popcount(1 1 0 1 1 0 1 1 0 1 0 1 0 1 0 1) = -4
451 // 16 - 2*popcount(0 1 1 1 1 0 0 1 1 0 0 1 0 1 0 1) = -2
452 // 16 - 2*popcount(0 0 1 1 0 1 0 0 0 0 0 0 0 1 0 1) = 6
453 // 16 - 2*popcount(1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0) = -14
455 // 16 - 2*popcount(0 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0) = 8
456 // 16 - 2*popcount(1 1 0 1 0 0 1 1 1 1 0 0 0 0 0 0) = 2
457 // 16 - 2*popcount(1 0 0 1 1 1 1 0 0 1 0 1 0 0 0 0) = 2
458 // 16 - 2*popcount(0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 1) = -2
460 // 16 - 2*popcount(1 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1) = -8
461 // 16 - 2*popcount(0 0 1 0 1 1 0 0 0 0 1 1 1 1 1 1) = -2
462 // 16 - 2*popcount(0 1 1 0 0 0 0 1 1 0 1 0 1 1 1 1) = -2
463 // 16 - 2*popcount(1 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0) = 2
465 // 16 - 2*popcount(0 0 1 0 0 1 0 0 1 0 1 0 1 0 1 0) = 4
466 // 16 - 2*popcount(1 0 0 0 0 1 1 0 0 1 1 0 1 0 1 0) = 2
467 // 16 - 2*popcount(1 1 0 0 1 0 1 1 1 1 1 1 1 0 1 0) = -6
468 // 16 - 2*popcount(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1) = 14
469 VF<float> output_vec = {
470 -4.0f, -2.0f, 6.0f, -14.0f,
471 8.0f, 2.0f, 2.0f, -2.0f,
472 -8.0f, -2.0f, -2.0f, 2.0f,
473 4.0f, 2.0f, -6.0f, 14.0f };
476 input_layout("input", input.get_layout()),
477 data("weights", weights),
478 binary_convolution("binary_conv", "input", { "weights" },
485 padding{ { 0,0,0,0 }, 0 })
488 cldnn::build_options options;
489 options.set_option(cldnn::build_option::optimize_data(true));
491 network network(engine, topology, options);
492 network.set_input_data("input", input);
494 auto outputs = network.execute();
495 EXPECT_EQ(outputs.size(), size_t(1));
496 EXPECT_EQ(outputs.begin()->first, "binary_conv");
498 auto output_memory = outputs.at("binary_conv").get_memory();
499 auto output_layout = output_memory.get_layout();
500 auto output_ptr = output_memory.pointer<uint16_t>();
503 EXPECT_EQ(output_layout.format, format::bfyx);
504 EXPECT_EQ(output_layout.data_type, data_types::f16);
505 EXPECT_EQ(output_layout.size.batch[0], 1);
506 EXPECT_EQ(output_layout.size.feature[0], 4);
507 EXPECT_EQ(output_layout.size.spatial[1], 2);
508 EXPECT_EQ(output_layout.size.spatial[0], 2);
510 for (size_t i = 0; i < output_layout.count(); i++)
512 EXPECT_EQ(float16_to_float32(output_ptr[i]), output_vec[i]) << "index="<< i;