summaryrefslogtreecommitdiff
path: root/runtimes/neurun/src/kernel/cpu/PermuteLayer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtimes/neurun/src/kernel/cpu/PermuteLayer.cc')
-rw-r--r--runtimes/neurun/src/kernel/cpu/PermuteLayer.cc201
1 files changed, 201 insertions, 0 deletions
diff --git a/runtimes/neurun/src/kernel/cpu/PermuteLayer.cc b/runtimes/neurun/src/kernel/cpu/PermuteLayer.cc
new file mode 100644
index 000000000..ba8c5ab92
--- /dev/null
+++ b/runtimes/neurun/src/kernel/cpu/PermuteLayer.cc
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PermuteLayer.h"
+
+#include "util/feature/nhwc/Reader.h"
+#include "util/feature/nhwc/View.h"
+#include "util/feature/nchw/View.h"
+#include "util/feature/Coordinate4D.h"
+
+#include <misc/feature/IndexIterator.h>
+
+namespace neurun
+{
+namespace kernel
+{
+namespace cpu
+{
+
+using Type = model::operation::PermuteNode::Type;
+
+void PermuteLayer::configure(std::shared_ptr<::neurun::backend::operand::IObject> input,
+ std::shared_ptr<::neurun::backend::operand::IObject> output,
+ const model::operand::Shape &shape, Type type)
+{
+ _input = input;
+ _output = output;
+ _shape = shape;
+ _type = type;
+}
+
+void PermuteLayer::run()
+{
+ auto rank = _shape.rank();
+
+ switch (_type)
+ {
+ case Type::NHWC_TO_NCHW:
+ {
+ auto fn = [&](::neurun::backend::operand::ITensor &tensor) {
+ auto input_tensor = _input->ptr();
+
+ auto input_buffer = input_tensor->buffer();
+ auto input_size = input_tensor->total_size();
+
+ auto output_buffer = tensor.buffer();
+ auto output_size = tensor.total_size();
+ switch (rank)
+ {
+ case 0:
+ case 1:
+ {
+ memcpy(output_buffer, input_buffer, input_size);
+ break;
+ }
+ case 2:
+ {
+ auto matrix_shape = _shape.asMatrix();
+
+ for (auto h = 0; h < matrix_shape.H; ++h)
+ {
+ neurun::util::feature::Coordinate4D coord{0, h, 0, 0};
+ memcpy(output_buffer + tensor.calcOffset(coord), input_buffer + h * matrix_shape.W,
+ matrix_shape.W * sizeof(float));
+ }
+ break;
+ }
+ case 3:
+ {
+ const int32_t depth = _shape.dim(0);
+ const int32_t height = _shape.dim(1);
+ const int32_t width = _shape.dim(2);
+
+ for (auto c = 0; c < depth; ++c)
+ {
+ for (auto h = 0; h < height; ++h)
+ {
+ neurun::util::feature::Coordinate4D coord{0, h, 0, c};
+ memcpy(output_buffer + tensor.calcOffset(coord),
+ input_buffer + c * height * width + h * width, width * sizeof(float));
+ }
+ }
+ break;
+ }
+ case 4:
+ {
+ auto feature = _shape.asFeature();
+
+ const util::feature::nhwc::Reader<float> from{
+ feature, reinterpret_cast<const float *>(input_buffer), input_size};
+ util::feature::nchw::View<float> into{&tensor};
+
+ ::nnfw::misc::feature::iterate(feature)
+ << [&](uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) {
+ const auto value = from.at(batch, ch, row, col);
+ into.at(batch, ch, row, col) = value;
+ };
+ break;
+ }
+ default:
+ throw "NYI";
+ break;
+ }
+ };
+ _output->access(fn);
+ break;
+ }
+ case Type::NCHW_TO_NHWC:
+ {
+ auto fn = [&](::neurun::backend::operand::ITensor &tensor) {
+ auto input_buffer = tensor.buffer();
+ auto input_size = tensor.total_size();
+
+ auto output_tensor = _output->ptr();
+
+ auto output_buffer = output_tensor->buffer();
+ auto output_size = output_tensor->total_size();
+
+ switch (rank)
+ {
+ case 0:
+ case 1:
+ {
+ memcpy(output_buffer, input_buffer, output_size);
+ break;
+ }
+ case 2:
+ {
+ auto matrix_shape = _shape.asMatrix();
+
+ for (auto h = 0; h < matrix_shape.H; ++h)
+ {
+ neurun::util::feature::Coordinate4D coord{0, h, 0, 0};
+ memcpy(output_buffer + h * matrix_shape.W, input_buffer + tensor.calcOffset(coord),
+ matrix_shape.W * sizeof(float));
+ }
+ break;
+ }
+ case 3:
+ {
+ const int32_t depth = _shape.dim(0);
+ const int32_t height = _shape.dim(1);
+ const int32_t width = _shape.dim(2);
+
+ for (auto c = 0; c < depth; ++c)
+ {
+ for (auto h = 0; h < height; ++h)
+ {
+ neurun::util::feature::Coordinate4D coord{0, h, 0, c};
+ memcpy(output_buffer + c * height * width + h * width,
+ input_buffer + tensor.calcOffset(coord), width * sizeof(float));
+ }
+ }
+ break;
+ }
+ case 4:
+ {
+ auto feature = _shape.asFeature();
+
+ const util::feature::nchw::View<float> from{&tensor};
+ util::feature::nhwc::View<float> into{feature, reinterpret_cast<float *>(output_buffer),
+ output_size};
+
+ ::nnfw::misc::feature::iterate(feature)
+ << [&](uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) {
+ const auto value = from.at(batch, ch, row, col);
+ into.at(batch, ch, row, col) = value;
+ };
+ break;
+ }
+ default:
+ throw "NYI";
+ break;
+ }
+ };
+ _input->access(fn);
+ break;
+ }
+ case Type::COPY:
+ // If two different backends using same tensor layout, we need this.
+ throw "NYI";
+ break;
+ }
+}
+
+} // namespace cpu
+} // namespace kernel
+} // namespace neurun