2 * Copyright (c) 2019 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 "NodeExecution.h"
19 #include "locomotiv/NodeData.h"
20 #include "NodeDataImpl.h"
21 #include "NodeDomain.h"
23 #include <nncc/core/ADT/tensor/Shape.h>
24 #include <nncc/core/ADT/tensor/Buffer.h>
25 #include <nncc/core/ADT/tensor/Overlay.h>
26 #include <nncc/core/ADT/tensor/LexicalLayout.h>
27 #include "nncc/core/ADT/tensor/IndexEnumerator.h"
29 #include <gtest/gtest.h>
33 using nncc::core::ADT::tensor::Shape;
34 using nncc::core::ADT::tensor::LexicalLayout;
35 using nncc::core::ADT::tensor::make_buffer;
36 using nncc::core::ADT::tensor::make_overlay;
38 void run_test(const float *ifm, const float *expected_ofm, const Shape &ifm_shape,
39 const Shape &ofm_shape, const uint32_t window_v, const uint32_t window_h,
40 const uint32_t stride_v, const uint32_t stride_h, const uint32_t pad_top,
41 const uint32_t pad_bottom, const uint32_t pad_left, const uint32_t pad_right)
43 // Let's make FeatureEncode-MaxPool2D graph
44 auto g = loco::make_graph();
45 auto enc = g->nodes()->create<loco::FeatureEncode>();
47 // Fill output data of FeatureEncode from ifm
48 auto enc_buf = make_buffer<float, LexicalLayout>(ifm_shape);
50 auto ifm_overlay = make_overlay<float, LexicalLayout>(ifm_shape, const_cast<float *>(ifm));
51 for (nncc::core::ADT::tensor::IndexEnumerator e{ifm_shape}; e.valid(); e.advance())
53 const auto &ind = e.current();
54 enc_buf.at(ind) = ifm_overlay.at(ind);
57 auto enc_data = locomotiv::make_data(enc_buf);
58 locomotiv::annot_data(enc, std::move(enc_data));
59 locomotiv::annot_domain(enc, loco::Domain::Feature);
62 auto maxpool2d = g->nodes()->create<loco::MaxPool2D>();
64 maxpool2d->window()->vertical(window_v);
65 maxpool2d->window()->horizontal(window_h);
66 maxpool2d->stride()->vertical(stride_v);
67 maxpool2d->stride()->horizontal(stride_h);
68 maxpool2d->pad()->top(pad_top);
69 maxpool2d->pad()->bottom(pad_bottom);
70 maxpool2d->pad()->left(pad_left);
71 maxpool2d->pad()->right(pad_right);
74 locomotiv::NodeExecution::get().run(maxpool2d);
76 // get result of calculation
77 auto maxpool2d_data = locomotiv::annot_data(maxpool2d);
80 ASSERT_NE(maxpool2d_data, nullptr);
81 ASSERT_TRUE(maxpool2d_data->dtype() == loco::DataType::FLOAT32);
82 ASSERT_TRUE(*(maxpool2d_data->shape()) == ofm_shape);
85 make_overlay<float, LexicalLayout>(ofm_shape, const_cast<float *>(expected_ofm));
86 for (nncc::core::ADT::tensor::IndexEnumerator e{ofm_shape}; e.valid(); e.advance())
88 const auto &ind = e.current();
89 ASSERT_FLOAT_EQ(ofm_overlay.at(ind), maxpool2d_data->as_f32_bufptr()->at(ind));
92 ASSERT_EQ(loco::Domain::Feature, locomotiv::annot_domain(maxpool2d));
98 /* ifm and ofm are from the code below:
100 value = tf.random_normal([1, 3, 3, 1], stddev=1)
101 maxpool = tf.nn.max_pool(value, ksize = [1, 2, 2, 1], strides = [1, 1, 1, 1], padding= 'VALID',
103 with tf.Session() as sess:
104 print(sess.run(maxpool))
107 TEST(NodeExecution_MaxPool2D, f32_1x3x3x1_calculation)
109 using nncc::core::ADT::tensor::Shape;
113 -1.5510627, 0.3653609, 1.9002001,
114 -0.15861237, -0.32944828, 1.2053918,
115 0.50054574, -0.8533826, 0.131492,
120 0.3653609, 1.9002001,
121 0.50054574, 1.2053918
125 Shape{1, 3, 3, 1}, Shape{1, 2, 2, 1}, // input shape , output shape
128 0, 0, 0, 0 // padding
132 TEST(NodeExecution_MaxPool2D, with_padding)
134 using nncc::core::ADT::tensor::Shape;
153 Shape{1, 5, 5, 1}, Shape{1, 3, 3, 1}, // input shape , output shape
156 1, 1, 1, 1 // padding - this mimics SAME padding