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 *ker, const float *expected_ofm, const Shape &ifm_shape,
39 const Shape ker_shape, const Shape ofm_shape, const uint32_t stride_v,
40 const uint32_t stride_h, const uint32_t pad_top = 0, const uint32_t pad_bottom = 0,
41 const uint32_t pad_left = 0, const uint32_t pad_right = 0)
43 auto g = loco::make_graph();
45 // Fill output data of FeatureEncode from ifm
46 auto ifm_enc = g->nodes()->create<loco::FeatureEncode>();
48 auto ifm_enc_buf = make_buffer<float, LexicalLayout>(ifm_shape);
49 auto ifm_overlay = make_overlay<float, LexicalLayout>(ifm_shape, const_cast<float *>(ifm));
50 for (nncc::core::ADT::tensor::IndexEnumerator e{ifm_shape}; e.valid(); e.advance())
52 const auto &ind = e.current();
53 ifm_enc_buf.at(ind) = ifm_overlay.at(ind);
56 auto enc_data = locomotiv::make_data(ifm_enc_buf);
57 locomotiv::annot_data(ifm_enc, std::move(enc_data));
58 locomotiv::annot_domain(ifm_enc, loco::Domain::Feature);
61 // Fill output data of FilterEncode from ker
62 auto ker_enc = g->nodes()->create<loco::FilterEncode>();
64 auto ker_enc_buf = make_buffer<float, LexicalLayout>(ker_shape);
65 auto ker_overlay = make_overlay<float, LexicalLayout>(ker_shape, const_cast<float *>(ker));
66 for (nncc::core::ADT::tensor::IndexEnumerator e{ker_shape}; e.valid(); e.advance())
68 const auto &ind = e.current();
69 ker_enc_buf.at(ind) = ker_overlay.at(ind);
72 auto enc_data = locomotiv::make_data(ker_enc_buf);
73 locomotiv::annot_data(ker_enc, std::move(enc_data));
74 locomotiv::annot_domain(ker_enc, loco::Domain::Filter);
77 // build TransposedConv2D
78 auto tr_conv2d = g->nodes()->create<loco::TransposedConv2D>();
79 tr_conv2d->ifm(ifm_enc);
80 tr_conv2d->ker(ker_enc);
81 tr_conv2d->stride()->vertical(stride_v);
82 tr_conv2d->stride()->horizontal(stride_h);
83 tr_conv2d->pad()->top(pad_top);
84 tr_conv2d->pad()->bottom(pad_bottom);
85 tr_conv2d->pad()->left(pad_left);
86 tr_conv2d->pad()->right(pad_right);
89 locomotiv::NodeExecution::get().run(tr_conv2d);
91 // get result of calculation
92 auto conv2d_result = locomotiv::annot_data(tr_conv2d);
95 ASSERT_NE(conv2d_result, nullptr);
96 ASSERT_TRUE(conv2d_result->dtype() == loco::DataType::FLOAT32);
97 ASSERT_TRUE(*(conv2d_result->shape()) == ofm_shape);
100 make_overlay<float, LexicalLayout>(ofm_shape, const_cast<float *>(expected_ofm));
101 for (nncc::core::ADT::tensor::IndexEnumerator e{ofm_shape}; e.valid(); e.advance())
103 const auto &ind = e.current();
104 ASSERT_FLOAT_EQ(ofm_overlay.at(ind), conv2d_result->as_f32_bufptr()->at(ind));
107 ASSERT_EQ(loco::Domain::Feature, locomotiv::annot_domain(tr_conv2d));
114 ifm = tf.constant(1.1, shape = [1, 2, 2, 4])
115 ker = tf.constant(2.2, shape = [3, 3, 2, 4])
116 tr_conv = tf.nn.conv2d_transpose(ifm, ker, output_shape = (1, 5, 5, 2), strides = [1, 2, 2, 1], padding = "VALID")
118 with tf.Session() as session:
119 tr_conv_data = session.run(tr_conv)
121 TEST(NodeExecution_TransposedConv2D, f32)
123 using nncc::core::ADT::tensor::Shape;
125 float ifm[1 * 2 * 2 * 4];
126 for (int n = 0; n < 1 * 2 * 2 * 4; n++)
129 float ker[2 * 3 * 3 * 4]; // NHWC
130 for (int n = 0; n < 2 * 3 * 3 * 4; n++)
133 float ofm[1 * 5 * 5 * 2] = {9.68, 9.68, 9.68, 9.68, 19.36, 19.36, 9.68, 9.68, 9.68, 9.68,
134 9.68, 9.68, 9.68, 9.68, 19.36, 19.36, 9.68, 9.68, 9.68, 9.68,
135 19.36, 19.36, 19.36, 19.36, 38.72, 38.72, 19.36, 19.36, 19.36, 19.36,
136 9.68, 9.68, 9.68, 9.68, 19.36, 19.36, 9.68, 9.68, 9.68, 9.68,
137 9.68, 9.68, 9.68, 9.68, 19.36, 19.36, 9.68, 9.68, 9.68, 9.68};
139 run_test(ifm, ker, ofm,
140 Shape{1, 2, 2, 4}, Shape{2, 3, 3, 4}, Shape{1, 5, 5, 2}, // shapes of ifm, ker, ofm