2 // Copyright (c) 2017 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 ///////////////////////////////////////////////////////////////////////////////////////////////////
18 #include <gtest/gtest.h>
19 #include <api/CPP/topology.hpp>
20 #include <api/CPP/network.hpp>
21 #include <api/CPP/engine.hpp>
23 #include <api/CPP/data.hpp>
24 #include <api/CPP/reshape.hpp>
25 #include <api/CPP/input_layout.hpp>
27 #include "test_utils/test_utils.h"
29 using namespace cldnn;
30 using namespace tests;
31 using namespace testing;
33 void verify_float(const float &output_value, const float &value)
35 EXPECT_FLOAT_EQ(output_value, value);
38 void verify_int(const int32_t &output_value, const int32_t &value)
40 EXPECT_EQ(output_value, value);
43 template <class ElemType>
44 void generic_reshape_test(format fmt, tensor const& input_size, tensor const& reshape_size, bool in_place, padding const& input_padd = padding(), padding const& output_padd = padding())
46 const auto& engine = get_test_engine();
48 //allocate input memory
49 auto data_type = data_types::f32;
50 if (std::is_same<ElemType, FLOAT16>::value)
51 data_type = data_types::f16;
52 else if (std::is_same<ElemType, int8_t>::value)
53 data_type = data_types::i8;
54 else if (std::is_same<ElemType, int32_t>::value)
55 data_type = data_types::i32;
56 else if (std::is_same<ElemType, int64_t>::value)
57 data_type = data_types::i64;
59 auto input = memory::allocate(engine, { data_type, fmt, input_size });
62 auto input_ptr = input.cldnn::memory::pointer<ElemType>();
63 auto input_itr = input_ptr.begin();
65 auto elements = input_size.count();
68 for (size_t i = 0; i < elements; ++i)
69 *input_itr++ = (ElemType)value++;
73 std::string reshape_input = "input";
75 tpl.add(input_layout("input", input.get_layout()));
78 auto padded_input_layout = input.get_layout();
79 padded_input_layout.data_padding = input_padd;
80 tpl.add(reorder("reorder", "input", padded_input_layout));
81 reshape_input = "reorder";
83 tpl.add(reshape("reshape", reshape_input, reshape_size, output_padd));
86 bo.set_option(build_option::outputs({ reshape_input, "reshape" }));
88 network net(engine, tpl, bo);
89 net.set_input_data("input", input);
90 auto outputs = net.execute();
92 ASSERT_TRUE(outputs.size() == 2 && outputs.count("reshape") == 1 && outputs.count(reshape_input) == 1);
93 auto net_input = outputs.at(reshape_input).get_memory();
94 auto output = outputs.at("reshape").get_memory();
96 EXPECT_TRUE(output.get_layout().data_type == input.get_layout().data_type); //reshape should not change data_type
97 EXPECT_TRUE(output.get_layout().format == input.get_layout().format); //reshape should not change format
99 //output size should be equal to requested plus output padding
100 ASSERT_TRUE(output.get_layout().size == reshape_size);
101 ASSERT_TRUE(output.get_layout().get_buffer_size() == reshape_size.add(output_padd.lower_size()).add(output_padd.upper_size()));
104 auto output_ptr = output.pointer<const ElemType>();
105 auto output_itr = output_ptr.begin();
107 auto sizes = reshape_size.sizes(fmt);
108 auto lower = output_padd.lower_size().sizes(fmt);
109 auto upper = output_padd.upper_size().sizes(fmt);
110 auto buffer_sizes = sizes;
112 for (size_t i = 1; i <= sizes.size(); ++i)
114 buffer_sizes[sizes.size() - i] = accum;
115 accum *= lower[sizes.size() - i] + sizes[sizes.size() - i] + upper[sizes.size() - i];
120 output_itr += lower[0] * buffer_sizes[0];
121 for (int d1 = 0; d1 < sizes[0]; ++d1)
123 output_itr += lower[1] * buffer_sizes[1];
124 for (int d2 = 0; d2 < sizes[1]; ++d2)
126 output_itr += lower[2] * buffer_sizes[2];
127 for (int d3 = 0; d3 < sizes[2]; ++d3)
129 output_itr += lower[3] * buffer_sizes[3];
130 for (int d4 = 0; d4 < sizes[3]; ++d4)
132 auto& output_value = *output_itr;
134 if (data_type == data_types::f16 || data_type == data_types::f32)
135 verify_float(static_cast<float>(output_value), static_cast<float>((ElemType)value));
137 verify_int(static_cast<int32_t>(output_value), static_cast<int32_t>(value));
141 output_itr += upper[3] * buffer_sizes[3];
144 output_itr += upper[2] * buffer_sizes[2];
147 output_itr += upper[1] * buffer_sizes[1];
152 TEST(reshape_gpu_f32, basic_2dim_in_place)
154 generic_reshape_test<float>(
161 TEST(reshape_gpu_f16, basic_2dim_in_place)
163 generic_reshape_test<FLOAT16>(
170 TEST(reshape_gpu_i8, basic_2dim_in_place)
172 generic_reshape_test<int8_t>(
179 TEST(reshape_gpu_i32, basic_2dim_in_place)
181 generic_reshape_test<int32_t>(
188 TEST(reshape_gpu_i64, basic_2dim_in_place)
190 generic_reshape_test<int64_t>(
197 TEST(reshape_gpu_f32, basic_4dim_in_place)
199 generic_reshape_test<float>(
206 TEST(reshape_gpu_f16, basic_4dim_in_place)
208 generic_reshape_test<FLOAT16>(
215 TEST(reshape_gpu_i32, basic_4dim_in_place)
217 generic_reshape_test<int32_t>(
224 TEST(reshape_gpu_i64, basic_4dim_in_place)
226 generic_reshape_test<int64_t>(
233 TEST(reshpape_gpu_f32, basic_2dim_output_padd)
235 generic_reshape_test<float>(
241 padding(std::vector<int>{ 0,0,1,1 })
245 TEST(reshape_gpu_f16, basic_2dim_output_padd)
247 generic_reshape_test<FLOAT16>(
253 padding(std::vector<int>{ 0,0,2,2 })
257 TEST(reshape_gpu_i8, basic_2dim_output_padd)
259 generic_reshape_test<int8_t>(
265 padding(std::vector<int>{ 0, 0, 2, 2 })
269 TEST(reshape_gpu_i32, basic_2dim_output_padd)
271 generic_reshape_test<int32_t>(
277 padding(std::vector<int>{ 0, 0, 2, 2 })
281 TEST(reshape_gpu_i64, basic_2dim_output_padd)
283 generic_reshape_test<int64_t>(
289 padding(std::vector<int>{ 0, 0, 2, 2 })
293 TEST(reshape_gpu_f32, basic_2dim_input_padd)
295 generic_reshape_test<float>(
300 padding({ 0,0,3,2 }, { 0,0,1,4 })
304 TEST(reshape_gpu_f16, basic_2dim_input_padd)
306 generic_reshape_test<FLOAT16>(
311 padding({ 0,0,4,1 }, { 0,0,2,3 })
315 TEST(reshape_gpu_i8, basic_2dim_input_padd)
317 generic_reshape_test<int8_t>(
322 padding({ 0,0,4,1 }, { 0,0,2,3 })
326 TEST(reshape_gpu_i32, basic_2dim_input_padd)
328 generic_reshape_test<int32_t>(
333 padding({ 0,0,4,1 }, { 0,0,2,3 })
337 TEST(reshape_gpu_i64, basic_2dim_input_padd)
339 generic_reshape_test<int64_t>(
344 padding({ 0,0,4,1 }, { 0,0,2,3 })
348 TEST(reshape_gpu_f32, basic_2dim_input_output_padd)
350 generic_reshape_test<float>(
355 padding({ 0,0,4,4 }, { 0,0,1,1 }),
356 padding({ 0,0,0,0 }, { 0,0,3,0 })
360 TEST(reshape_gpu_f16, basic_2dim_input_output_padd)
362 generic_reshape_test<FLOAT16>(
367 padding({ 0,0,1,1 }, { 0,0,0,0 }),
368 padding({ 0,0,2,1 }, { 0,0,1,2 })
372 TEST(reshape_gpu_i8, basic_2dim_input_output_padd)
374 generic_reshape_test<int8_t>(
379 padding({ 0,0,4,4 }, { 0,0,1,1 }),
380 padding({ 0,0,0,0 }, { 0,0,3,0 })
384 TEST(reshape_gpu_i32, basic_2dim_input_output_padd)
386 generic_reshape_test<int32_t>(
391 padding({ 0,0,4,4 }, { 0,0,1,1 }),
392 padding({ 0,0,0,0 }, { 0,0,3,0 })
396 TEST(reshape_gpu_i64, basic_2dim_input_output_padd)
398 generic_reshape_test<int64_t>(
403 padding({ 0,0,4,4 }, { 0,0,1,1 }),
404 padding({ 0,0,0,0 }, { 0,0,3,0 })
408 TEST(reshpape_gpu_f32, basic_4dim_output_padd)
410 generic_reshape_test<float>(
413 tensor(1, 14, 15, 1),
416 padding({ 1,0,0,1 },{ 0,2,3,0 })
420 TEST(reshape_gpu_f16, basic_4dim_output_padd)
422 generic_reshape_test<FLOAT16>(
428 padding({ 0,2,0,1 },{ 0,2,3,0 })
432 TEST(reshape_gpu_f32, basic_4dim_input_padd)
434 generic_reshape_test<float>(
436 tensor(8, 128, 3, 3),
439 padding({ 0,1,3,3}, { 0,1,1,1 })
443 TEST(reshape_gpu_f16, basic_4dim_input_padd)
445 generic_reshape_test<FLOAT16>(
448 tensor(8, 128, 1, 4),
450 padding({ 2,2,1,0 }, { 1,2,2,0 })
454 TEST(reshape_gpu_f32, basic_4dim_input_output_padd)
456 generic_reshape_test<float>(
458 tensor(8, 1024, 25, 25),
459 tensor(8, 64, 100, 100),
461 padding({ 2,0,2,1 }, { 0,1,4,0 }),
462 padding({ 1,2,3,4 }, { 0,4,1,1 })
466 TEST(reshape_gpu_f16, basic_4dim_input_output_padd)
468 generic_reshape_test<FLOAT16>(
470 tensor(32, 3, 227, 227),
471 tensor(8, 12, 227, 227),
473 padding({ 0,1,4,4 }, { 0,1,1,1 }),
474 padding({ 0,29,29,0 }, { 0,0,0,0 })
478 TEST(reshape_gpu_f32, multiple_users_with_reorder) {
479 // Tests split with crop implementation
480 // _ REORDER(yxfb) --> RELU(yxfb)
482 // INPUT(bfyx,2x2x1x1)--RELU(bfyx)--RESHAPE(4x1x1x1)
504 const auto& engine = get_test_engine();
506 auto feature_num = 2;
509 auto input = memory::allocate(engine, { data_types::f32, format::bfyx,{ tensor(spatial(x_size, y_size), feature(feature_num), batch(batch_num)) } });
512 topology.add(input_layout("input", input.get_layout()));
513 topology.add(activation("relu", "input", activation_relu));
514 topology.add(reshape("reshape", "relu", tensor(batch(4))));
515 topology.add(reorder("reorder1", "reshape", format::yxfb, data_types::f32));
516 topology.add(activation("relu1", "reorder1", activation_relu));
517 topology.add(activation("relu2", "reshape", activation_relu));
519 std::vector<float> input_vec = { -1.f, 2.f, -3.f, 4.f };
520 std::vector<float> out1 = { 0.f, 0.f, 2.f, 4.0f };
521 std::vector<float> out2 = { 0.f, 2.f, 0.f, 4.0f };
522 set_values(input, input_vec);
524 network network(engine, topology);
525 network.set_input_data("input", input);
526 auto outputs = network.execute();
528 auto output = outputs.at("relu1").get_memory();
529 auto output_ptr = output.pointer<float>();
531 for (size_t i = 0; i < out1.size(); i++)
532 EXPECT_EQ(output_ptr[i], out1[i]);
534 auto output_2 = outputs.at("relu2").get_memory();
535 auto output_ptr_2 = output_2.pointer<float>();
537 for (size_t i = 0; i < out2.size(); i++)
538 EXPECT_EQ(output_ptr_2[i], out2[i]);
541 TEST(reshape_gpu_f32, calc_output_shape) {
543 // INPUT(bfyx,2x2x1x1) -- RESHAPE(1, 1, 0, -1)
551 // output_shape (1, 1, 1, 4)
553 const auto& engine = get_test_engine();
555 auto input = memory::allocate(engine, { data_types::f32, format::bfyx,{ 2, 2, 1, 1 } });
558 topology.add(input_layout("input", input.get_layout()));
559 topology.add(reshape("reshape", "input", tensor(1, 1, 0, -1)));
561 set_values(input, { -1.f, 2.f, -3.f, 4.f });
563 network network(engine, topology);
564 network.set_input_data("input", input);
565 auto outputs = network.execute();
567 EXPECT_EQ(outputs.size(), size_t(1));
568 EXPECT_EQ(outputs.begin()->first, "reshape");
570 auto output = outputs.at("reshape").get_memory();
572 EXPECT_TRUE(output.get_layout().data_type == input.get_layout().data_type);
573 EXPECT_TRUE(output.get_layout().format == input.get_layout().format);
575 ASSERT_TRUE(output.get_layout().size == tensor(1, 1, 1, 4));
577 float answers[4] = { -1.f, 2.f, -3.f, 4.f };
579 auto output_ptr = output.pointer<float>();
580 for (int i = 0; i < 4; i++)
582 EXPECT_TRUE(are_equal(answers[i], output_ptr[i]));