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/memory.hpp"
20 #include <api/CPP/input_layout.hpp>
21 #include "api/CPP/crop.hpp"
22 #include <api/CPP/topology.hpp>
23 #include <api/CPP/network.hpp>
24 #include <api/CPP/engine.hpp>
25 #include "test_utils/test_utils.h"
27 using namespace cldnn;
28 using namespace tests;
31 std::vector<T> generate_random_input(size_t b, size_t f, size_t y, size_t x, int min, int max) {
32 static std::default_random_engine generator(random_seed);
33 int k = 8; // 1/k is the resolution of the floating point numbers
34 std::uniform_int_distribution<int> distribution(k * min, k * max);
35 std::vector<T> v(b*f*x*y);
36 for (size_t i = 0; i < b*f*x*y; ++i) {
37 v[i] = (T)distribution(generator);
43 TEST(crop_gpu, basic_in2x3x2x2_crop_all) {
44 // Reference : 1x2x2x2
48 const auto& engine = get_test_engine();
55 auto crop_batch_num = batch_num - 1;
56 auto crop_feature_num = feature_num - 1;
57 auto crop_x_size = x_size - 2;
58 auto crop_y_size = y_size - 2;
60 auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ batch_num, feature_num, x_size, y_size } });
63 topology.add(input_layout("input", input.get_layout()));
64 topology.add(crop("crop", "input", { crop_batch_num, crop_feature_num, crop_x_size, crop_y_size }, { 0, 0, 0, 0 }));
66 std::vector<float> input_vec = generate_random_input<float>(batch_num, feature_num, y_size, x_size, -10, 10);
67 set_values(input, input_vec);
69 network network(engine, topology);
71 network.set_input_data("input", input);
73 auto outputs = network.execute();
75 auto output = outputs.at("crop").get_memory();
76 auto output_ptr = output.pointer<float>();
78 for (int b = 0; b < crop_batch_num; ++b) { //B
79 for (int f = 0; f < crop_feature_num; ++f) { //F
80 for (int y = 0; y < crop_y_size; ++y) { //Y
81 for (int x = 0; x < crop_x_size; ++x) { //X
82 int linear_id = b + batch_num * (f + feature_num * (x + x_size * y));
83 int output_linear_id = b + crop_batch_num * (f + crop_feature_num * (x + crop_x_size * y));
84 EXPECT_EQ(output_ptr[output_linear_id], input_vec[linear_id]);
91 TEST(crop_gpu, basic_int_in2x3x2x2_crop_all) {
92 // Reference : 1x2x2x2
96 const auto& engine = get_test_engine();
103 auto crop_batch_num = batch_num - 1;
104 auto crop_feature_num = feature_num - 1;
105 auto crop_x_size = x_size - 2;
106 auto crop_y_size = y_size - 2;
108 auto input = memory::allocate(engine, { data_types::i32, format::yxfb,{ batch_num, feature_num, x_size, y_size } });
111 topology.add(input_layout("input", input.get_layout()));
112 topology.add(crop("crop", "input", { crop_batch_num, crop_feature_num, crop_x_size, crop_y_size }, { 0, 0, 0, 0 }));
114 std::vector<int32_t> input_vec = generate_random_input<int32_t>(batch_num, feature_num, y_size, x_size, -10, 10);
115 set_values(input, input_vec);
117 network network(engine, topology);
119 network.set_input_data("input", input);
121 auto outputs = network.execute();
123 auto output = outputs.at("crop").get_memory();
124 auto output_ptr = output.pointer<int32_t>();
126 for (int b = 0; b < crop_batch_num; ++b) { //B
127 for (int f = 0; f < crop_feature_num; ++f) { //F
128 for (int y = 0; y < crop_y_size; ++y) { //Y
129 for (int x = 0; x < crop_x_size; ++x) { //X
130 int linear_id = b + batch_num * (f + feature_num * (x + x_size * y));
131 int output_linear_id = b + crop_batch_num * (f + crop_feature_num * (x + crop_x_size * y));
132 EXPECT_EQ(output_ptr[output_linear_id], input_vec[linear_id]);
139 TEST(crop_gpu, basic_in2x3x2x2_crop_all_bfyx) {
140 // Reference : 3x1x2x2
144 const auto& engine = get_test_engine();
147 auto feature_num = 2;
151 auto crop_batch_num = batch_num - 3;
152 auto crop_feature_num = feature_num - 1;
153 auto crop_x_size = x_size - 2;
154 auto crop_y_size = y_size - 1;
156 auto input = memory::allocate(engine, { data_types::f32,format::bfyx,{ batch_num, feature_num, x_size, y_size } });
159 topology.add(input_layout("input", input.get_layout()));
160 topology.add(crop("crop", "input", { crop_batch_num, crop_feature_num, crop_x_size, crop_y_size }, {0, 0, 0, 0} ));
162 std::vector<float> input_vec = generate_random_input<float>(batch_num, feature_num, y_size, x_size, -10, 10);
163 set_values(input, input_vec);
165 network network(engine, topology);
167 network.set_input_data("input", input);
169 auto outputs = network.execute();
171 auto output = outputs.at("crop").get_memory();
172 auto output_ptr = output.pointer<float>();
173 std::vector<float> a;
174 for (int b = 0; b < crop_batch_num; ++b) { //B
175 for (int f = 0; f < crop_feature_num; ++f) { //F
176 for (int y = 0; y < crop_y_size; ++y) { //Y
177 for (int x = 0; x < crop_x_size; ++x) { //X
178 int linear_id = x + x_size * (y + y_size * (f + feature_num * b));
179 int output_linear_id = x + crop_x_size * (y + crop_y_size * (f + crop_feature_num * b));
180 a.push_back(output_ptr[output_linear_id]);
181 EXPECT_EQ(output_ptr[output_linear_id], input_vec[linear_id]);
188 TEST(crop_gpu, basic_int_in2x3x2x2_crop_all_bfyx) {
189 // Reference : 3x1x2x2
193 const auto& engine = get_test_engine();
196 auto feature_num = 2;
200 auto crop_batch_num = batch_num - 3;
201 auto crop_feature_num = feature_num - 1;
202 auto crop_x_size = x_size - 2;
203 auto crop_y_size = y_size - 1;
205 auto input = memory::allocate(engine, { data_types::i32,format::bfyx,{ batch_num, feature_num, x_size, y_size } });
208 topology.add(input_layout("input", input.get_layout()));
209 topology.add(crop("crop", "input", { crop_batch_num, crop_feature_num, crop_x_size, crop_y_size }, { 0, 0, 0, 0 }));
211 std::vector<int32_t> input_vec = generate_random_input<int32_t>(batch_num, feature_num, y_size, x_size, -10, 10);
212 set_values(input, input_vec);
214 network network(engine, topology);
216 network.set_input_data("input", input);
218 auto outputs = network.execute();
220 auto output = outputs.at("crop").get_memory();
221 auto output_ptr = output.pointer<int32_t>();
222 std::vector<int32_t> a;
223 for (int b = 0; b < crop_batch_num; ++b) { //B
224 for (int f = 0; f < crop_feature_num; ++f) { //F
225 for (int y = 0; y < crop_y_size; ++y) { //Y
226 for (int x = 0; x < crop_x_size; ++x) { //X
227 int linear_id = x + x_size * (y + y_size * (f + feature_num * b));
228 int output_linear_id = x + crop_x_size * (y + crop_y_size * (f + crop_feature_num * b));
229 a.push_back(output_ptr[output_linear_id]);
230 EXPECT_EQ(output_ptr[output_linear_id], input_vec[linear_id]);
237 TEST(crop_gpu, basic_in2x3x2x2_crop_all_fyxb) {
238 // Reference : 3x1x2x2
242 const auto& engine = get_test_engine();
245 auto feature_num = 2;
249 auto crop_batch_num = batch_num - 3;
250 auto crop_feature_num = feature_num - 1;
251 auto crop_x_size = x_size - 2;
252 auto crop_y_size = y_size - 1;
254 auto input = memory::allocate(engine, { data_types::f32,format::fyxb,{ batch_num, feature_num, x_size, y_size } });
257 topology.add(input_layout("input", input.get_layout()));
258 topology.add(crop("crop", "input", { crop_batch_num, crop_feature_num, crop_x_size, crop_y_size }, {0, 0, 0, 0} ));
260 std::vector<float> input_vec = generate_random_input<float>(batch_num, feature_num, y_size, x_size, -10, 10);
261 set_values(input, input_vec);
263 network network(engine, topology);
265 network.set_input_data("input", input);
267 auto outputs = network.execute();
269 auto output = outputs.at("crop").get_memory();
270 auto output_ptr = output.pointer<float>();
271 for (int b = 0; b < crop_batch_num; ++b) { //B
272 for (int f = 0; f < crop_feature_num; ++f) { //F
273 for (int y = 0; y < crop_y_size; ++y) { //Y
274 for (int x = 0; x < crop_x_size; ++x) { //X
275 int linear_id = b + batch_num * (x + x_size * (y + y_size * f));
276 int output_linear_id = b + crop_batch_num * (x + crop_x_size * (y + crop_y_size * f));
277 EXPECT_EQ(output_ptr[output_linear_id], input_vec[linear_id]);
284 TEST(crop_gpu, basic_int_in2x3x2x2_crop_all_fyxb) {
285 // Reference : 3x1x2x2
289 const auto& engine = get_test_engine();
292 auto feature_num = 2;
296 auto crop_batch_num = batch_num - 3;
297 auto crop_feature_num = feature_num - 1;
298 auto crop_x_size = x_size - 2;
299 auto crop_y_size = y_size - 1;
301 auto input = memory::allocate(engine, { data_types::i32,format::fyxb,{ batch_num, feature_num, x_size, y_size } });
304 topology.add(input_layout("input", input.get_layout()));
305 topology.add(crop("crop", "input", { crop_batch_num, crop_feature_num, crop_x_size, crop_y_size }, { 0, 0, 0, 0 }));
307 std::vector<int32_t> input_vec = generate_random_input<int32_t>(batch_num, feature_num, y_size, x_size, -10, 10);
308 set_values(input, input_vec);
310 network network(engine, topology);
312 network.set_input_data("input", input);
314 auto outputs = network.execute();
316 auto output = outputs.at("crop").get_memory();
317 auto output_ptr = output.pointer<int32_t>();
318 for (int b = 0; b < crop_batch_num; ++b) { //B
319 for (int f = 0; f < crop_feature_num; ++f) { //F
320 for (int y = 0; y < crop_y_size; ++y) { //Y
321 for (int x = 0; x < crop_x_size; ++x) { //X
322 int linear_id = b + batch_num * (x + x_size * (y + y_size * f));
323 int output_linear_id = b + crop_batch_num * (x + crop_x_size * (y + crop_y_size * f));
324 EXPECT_EQ(output_ptr[output_linear_id], input_vec[linear_id]);
331 TEST(crop_gpu, basic_in2x3x2x2_crop_offsets) {
332 // Reference : 1x2x2x1
338 // f0: b0: 1 2 -10 b1: 0 0 -11
339 // f0: b0: 3 4 -14 b1: 0.5 -0.5 -15
340 // f1: b0: 5 6 -12 b1: 1.5 5.2 -13
341 // f1: b0: 7 8 -16 b1: 12 8 -17
343 const auto& engine = get_test_engine();
346 auto feature_num = 2;
350 auto crop_batch_num = batch_num - 1;
351 auto crop_feature_num = feature_num;
352 auto crop_x_size = x_size - 1;
353 auto crop_y_size = y_size - 1;
355 auto batch_offset = 1;
356 auto feature_offset = 0;
360 auto input = memory::allocate(engine, { data_types::f32, format::yxfb, { tensor(spatial(x_size, y_size), feature(feature_num), batch(batch_num)) } });
363 topology.add(input_layout("input", input.get_layout()));
364 topology.add(crop("crop", "input", tensor(batch(crop_batch_num), spatial(crop_x_size, crop_y_size), feature(crop_feature_num)), { tensor(feature(0)) }));
366 std::vector<float> input_vec = { 1.f, 0.f, 5.f, 1.5f,
368 -10.f, -11.f, -12.f, -13.f,
369 3.f, 0.5f, 7.f, 12.f,
370 4.f, -0.5f, 8.f, 8.f,
371 -14.f, -15.f, -16.f, -17.f };
372 set_values(input, input_vec);
374 network network(engine, topology);
376 network.set_input_data("input", input);
378 auto outputs = network.execute();
380 auto output = outputs.at("crop").get_memory();
381 auto output_ptr = output.pointer<float>();
383 for (int b = 0; b < crop_batch_num; ++b) { //B
384 for (int f = 0; f < crop_feature_num; ++f) { //F
385 for (int y = 0; y < crop_y_size; ++y) { //Y
386 for (int x = 0; x < crop_x_size; ++x) { //X
387 int linear_id = (b + batch_offset) + batch_num * ((f + feature_offset) + feature_num * ((x + x_offset) + x_size * (y + y_offset)));
388 int output_linear_id = b + crop_batch_num * (f + crop_feature_num * (x + crop_x_size * y));
389 EXPECT_EQ(output_ptr[output_linear_id], input_vec[linear_id]);
396 TEST(crop_gpu, basic_int_in2x3x2x2_crop_offsets) {
397 // Reference : 1x2x2x1
403 // f0: b0: 1 2 -10 b1: 0 0 -11
404 // f0: b0: 3 4 -14 b1: 50 -5 -15
405 // f1: b0: 5 6 -12 b1: 15 52 -13
406 // f1: b0: 7 8 -16 b1: 12 8 -17
408 const auto& engine = get_test_engine();
411 auto feature_num = 2;
415 auto crop_batch_num = batch_num - 1;
416 auto crop_feature_num = feature_num;
417 auto crop_x_size = x_size - 1;
418 auto crop_y_size = y_size - 1;
420 auto batch_offset = 1;
421 auto feature_offset = 0;
425 auto input = memory::allocate(engine, { data_types::i32, format::yxfb,{ tensor(spatial(x_size, y_size), feature(feature_num), batch(batch_num)) } });
428 topology.add(input_layout("input", input.get_layout()));
429 topology.add(crop("crop", "input", tensor(batch(crop_batch_num), spatial(crop_x_size, crop_y_size), feature(crop_feature_num)), { tensor(feature(0)) }));
431 std::vector<int32_t> input_vec = { 1, 0, 5, 15,
436 -14, -15, -16, -17 };
437 set_values(input, input_vec);
439 network network(engine, topology);
441 network.set_input_data("input", input);
443 auto outputs = network.execute();
445 auto output = outputs.at("crop").get_memory();
446 auto output_ptr = output.pointer<int32_t>();
448 for (int b = 0; b < crop_batch_num; ++b) { //B
449 for (int f = 0; f < crop_feature_num; ++f) { //F
450 for (int y = 0; y < crop_y_size; ++y) { //Y
451 for (int x = 0; x < crop_x_size; ++x) { //X
452 int linear_id = (b + batch_offset) + batch_num * ((f + feature_offset) + feature_num * ((x + x_offset) + x_size * (y + y_offset)));
453 int output_linear_id = b + crop_batch_num * (f + crop_feature_num * (x + crop_x_size * y));
454 EXPECT_EQ(output_ptr[output_linear_id], input_vec[linear_id]);
461 TEST(crop_gpu, basic_in1x4x1x1_split) {
462 // Tests split with crop implementation
463 // _CROP_1(1x3x1x1,offset(0x0x0x0))
467 // CROP_2(1x1x1x1,offset(0x3x0x0))
469 // Reference1 : 1x3x1x1
470 // Offsets1 : 0x0x0x0
471 // Reference2 : 1x1x1x1
472 // Offsets2 : 0x3x0x0
490 const auto& engine = get_test_engine();
493 auto feature_num = 4;
497 auto crop_batch_num = 1;
498 auto crop_feature_num_1 = 3;
499 auto crop_feature_num_2 = 1;
500 auto crop_x_size = 1;
501 auto crop_y_size = 1;
502 auto feature_offset_1 = 0;
503 auto feature_offset_2 = 3;
504 auto input = memory::allocate(engine, { data_types::f32, format::bfyx,{ tensor(spatial(x_size, y_size), feature(feature_num), batch(batch_num)) } });
507 topology.add(input_layout("input", input.get_layout()));
508 topology.add(crop("crop1", "input", tensor(batch(crop_batch_num), spatial(crop_x_size, crop_y_size), feature(crop_feature_num_1)), { tensor(feature(feature_offset_1), spatial(0,0),batch(0)) }));
509 topology.add(crop("crop2", "input", tensor(batch(crop_batch_num), spatial(crop_x_size, crop_y_size), feature(crop_feature_num_2)), { tensor(feature(feature_offset_2), spatial(0,0),batch(0)) }));
511 std::vector<float> input_vec = { -1.f, 2.f, -3.f, 4.f };
512 std::vector<float> out1 = { -1.f, 2.f,-3.f };
513 std::vector<float> out2 = { 4.f, };
514 set_values(input, input_vec);
516 bo.set_option(build_option::optimize_data(true));
517 bo.set_option(build_option::outputs(topology.get_primitive_ids()));
519 network network(engine, topology, bo);
520 network.set_input_data("input", input);
521 auto outputs = network.execute();
523 auto output = outputs.at("crop1").get_memory();
524 auto output_ptr = output.pointer<float>();
526 for (size_t i = 0; i < out1.size();i++)
527 EXPECT_EQ(output_ptr[i], out1[i]);
529 std::cout << std::endl;
530 auto output_2 = outputs.at("crop2").get_memory();
531 auto output_ptr_2 = output_2.pointer<float>();
533 for (size_t i = 0; i < out2.size();i++)
534 EXPECT_EQ(output_ptr_2[i], out2[i]);
537 TEST(crop_gpu, basic_int_in1x4x1x1_split) {
538 // Tests split with crop implementation
539 // _CROP_1(1x3x1x1,offset(0x0x0x0))
543 // CROP_2(1x1x1x1,offset(0x3x0x0))
545 // Reference1 : 1x3x1x1
546 // Offsets1 : 0x0x0x0
547 // Reference2 : 1x1x1x1
548 // Offsets2 : 0x3x0x0
566 const auto& engine = get_test_engine();
569 auto feature_num = 4;
573 auto crop_batch_num = 1;
574 auto crop_feature_num_1 = 3;
575 auto crop_feature_num_2 = 1;
576 auto crop_x_size = 1;
577 auto crop_y_size = 1;
578 auto feature_offset_1 = 0;
579 auto feature_offset_2 = 3;
580 auto input = memory::allocate(engine, { data_types::i32, format::bfyx,{ tensor(spatial(x_size, y_size), feature(feature_num), batch(batch_num)) } });
583 topology.add(input_layout("input", input.get_layout()));
584 topology.add(crop("crop1", "input", tensor(batch(crop_batch_num), spatial(crop_x_size, crop_y_size), feature(crop_feature_num_1)), { tensor(feature(feature_offset_1), spatial(0,0),batch(0)) }));
585 topology.add(crop("crop2", "input", tensor(batch(crop_batch_num), spatial(crop_x_size, crop_y_size), feature(crop_feature_num_2)), { tensor(feature(feature_offset_2), spatial(0,0),batch(0)) }));
587 std::vector<int32_t> input_vec = { -1, 2, -3, 4 };
588 std::vector<int32_t> out1 = { -1, 2,-3 };
589 std::vector<int32_t> out2 = { 4, };
590 set_values(input, input_vec);
592 bo.set_option(build_option::optimize_data(true));
593 bo.set_option(build_option::outputs(topology.get_primitive_ids()));
595 network network(engine, topology, bo);
596 network.set_input_data("input", input);
597 auto outputs = network.execute();
599 auto output = outputs.at("crop1").get_memory();
600 auto output_ptr = output.pointer<int32_t>();
602 for (size_t i = 0; i < out1.size(); i++)
603 EXPECT_EQ(output_ptr[i], out1[i]);
605 std::cout << std::endl;
606 auto output_2 = outputs.at("crop2").get_memory();
607 auto output_ptr_2 = output_2.pointer<int32_t>();
609 for (size_t i = 0; i < out2.size(); i++)
610 EXPECT_EQ(output_ptr_2[i], out2[i]);
613 TEST(crop_gpu, basic_in1x4x1x1_split_w_relu) {
614 // Tests split with crop implementation
615 // _ CROP_1(1x3x1x1,offset(0x0x0x0)) --> RELU
617 // INPUT(1x4x1x1)--RELU
619 // CROP_2(1x1x1x1,offset(0x3x0x0)) --> RELU
621 // Reference1 : 1x3x1x1
622 // Offsets1 : 0x0x0x0
623 // Reference2 : 1x1x1x1
624 // Offsets2 : 0x3x0x0
642 // disable memory pool when we want to check optimized out internal results
643 engine_configuration cfg{ false, false, false, std::string(), std::string(), true /*oooq*/, std::string(),std::string(), priority_mode_types::disabled, throttle_mode_types::disabled, false /*mem_pool*/ };
644 engine engine{ cfg };
646 auto feature_num = 4;
649 auto crop_batch_num = 1;
650 auto crop_feature_num_1 = 3;
651 auto crop_feature_num_2 = 1;
652 auto crop_x_size = 1;
653 auto crop_y_size = 1;
654 auto feature_offset_1 = 0;
655 auto feature_offset_2 = 3;
656 auto input = memory::allocate(engine, { data_types::f32, format::bfyx,{ tensor(spatial(x_size, y_size), feature(feature_num), batch(batch_num)) } });
659 topology.add(input_layout("input", input.get_layout()));
660 topology.add(activation("relu", "input", activation_relu));
661 topology.add(crop("crop1", "relu", tensor(batch(crop_batch_num), spatial(crop_x_size, crop_y_size), feature(crop_feature_num_1)), { tensor(feature(feature_offset_1), spatial(0,0),batch(0)) }));
662 topology.add(crop("crop2", "relu", tensor(batch(crop_batch_num), spatial(crop_x_size, crop_y_size), feature(crop_feature_num_2)), { tensor(feature(feature_offset_2), spatial(0,0),batch(0)) }));
663 topology.add(activation("relu1", "crop1", activation_relu));
664 topology.add(activation("relu2", "crop2", activation_relu));
666 std::vector<float> input_vec = { -1.f, 2.f, -3.f, 4.f };
667 std::vector<float> out1 = { 0.f, 2.f,0.f };
668 std::vector<float> out2 = { 4.f, };
669 set_values(input, input_vec);
671 bo.set_option(build_option::optimize_data(true));
672 bo.set_option(build_option::debug(true)); //required to have optimized crop despite the fact that it's specified as an output
674 network network(engine, topology, bo);
675 network.set_input_data("input", input);
676 auto outputs = network.execute();
678 auto output = outputs.at("relu1").get_memory();
679 auto output_ptr = output.pointer<float>();
681 // check if crop has been executed in place
682 auto in_place = outputs.at("crop1").get_memory().is_the_same_buffer(outputs.at("relu").get_memory());
683 EXPECT_TRUE(in_place);
685 for (size_t i = 0; i < out1.size();i++)
686 EXPECT_EQ(output_ptr[i], out1[i]);
688 auto output_2 = outputs.at("relu2").get_memory();
689 auto output_ptr_2 = output_2.pointer<float>();
691 for (size_t i = 0; i < out2.size();i++)
692 EXPECT_EQ(output_ptr_2[i], out2[i]);