diff options
Diffstat (limited to 'runtimes/neurun/src/kernel/cpu/PermuteLayer.cc')
-rw-r--r-- | runtimes/neurun/src/kernel/cpu/PermuteLayer.cc | 201 |
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 |