+++ /dev/null
-/*
- * 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 "backend/acl_cl/InitializerGenerator.h"
-
-#include <arm_compute/core/Coordinates.h>
-
-#include "backend/acl_cl/kernel/View.h"
-#include "internal/nnapi/kernel/Reader.h"
-#include "util/kernel/IndexIterator.h"
-
-namespace neurun
-{
-namespace backend
-{
-namespace acl_cl
-{
-
-InitializerGenerator::InitializerGenerator(const neurun::graph::operand::Set &ctx) : _ctx(ctx)
-{
- // DO NOTHING
-}
-
-Initializer InitializerGenerator::generate(const graph::operation::Conv2DNode &node)
-{
- using graph::operation::Conv2DNode;
-
- Initializer ret;
- ret.push_back({node.getInputs().at(Conv2DNode::Input::KERNEL), generateWeight(node)});
- ret.push_back({node.getInputs().at(Conv2DNode::Input::BIAS), generateBias(node)});
- return ret;
-}
-
-Initializer InitializerGenerator::generate(const graph::operation::FullyConnectedNode &node)
-{
- using graph::operation::FullyConnectedNode;
-
- Initializer ret;
- ret.push_back({node.getInputs().at(FullyConnectedNode::Input::WEIGHT), generateWeight(node)});
- ret.push_back({node.getInputs().at(FullyConnectedNode::Input::BIAS), generateBias(node)});
- return ret;
-}
-
-InitializerFn InitializerGenerator::generateWeight(const graph::operation::Conv2DNode &node)
-{
- const auto ker_index{node.getInputs().at(1)};
-
- const auto ker_shape = _ctx.at(ker_index).shape().asKernel();
- auto ker_base = _ctx.at(ker_index).data().base();
- auto ker_size = _ctx.at(ker_index).data().size();
-
- return [ker_shape, ker_base, ker_size](::arm_compute::ITensor &tensor) {
- const ::internal::nnapi::kernel::Reader<float> from{ker_shape, ker_base, ker_size};
- ::internal::arm_compute::kernel::View<float> into{&tensor};
-
- ::nnfw::util::kernel::iterate(ker_shape)
- << [&](uint32_t nth, uint32_t ch, uint32_t row, uint32_t col) {
- const auto value = from.at(nth, ch, row, col);
- into.at(nth, ch, row, col) = value;
- };
- };
-}
-
-InitializerFn InitializerGenerator::generateWeight(const graph::operation::FullyConnectedNode &node)
-{
- const auto weight_index{node.getInputs().at(1)};
- const auto input_index{node.getInputs().at(0)};
-
- const auto num_output = _ctx.at(weight_index).shape().dim(0);
- auto weight_base = _ctx.at(weight_index).data().base();
- auto weight_size = _ctx.at(weight_index).data().size();
-
- // NOTE We assume that input is a feature map
- // TODO Remove this restriction!
- const auto ifm_shape = _ctx.at(input_index).shape().asFeature();
-
- return [num_output, ifm_shape, weight_base, weight_size](::arm_compute::ITensor &tensor) {
- const ::nnfw::util::kernel::Shape ker_shape{num_output, ifm_shape.C, ifm_shape.H, ifm_shape.W};
- const ::internal::nnapi::kernel::Reader<float> from{ker_shape, weight_base, weight_size};
-
- ::nnfw::util::kernel::iterate(ker_shape)
- << [&](uint32_t nth, uint32_t ch, uint32_t row, uint32_t col) {
- const auto value = from.at(nth, ch, row, col);
-
- uint32_t offset = 0;
-
- // ARM Compute Library uses 'NCHW' ordering
- offset += nth * ifm_shape.C * ifm_shape.H * ifm_shape.W;
- offset += ch * ifm_shape.H * ifm_shape.W;
- offset += row * ifm_shape.W;
- offset += col;
-
- const ::arm_compute::Coordinates coordinate{offset};
-
- auto into = reinterpret_cast<float *>(tensor.ptr_to_element(coordinate));
-
- *into = value;
- };
- };
-}
-
-InitializerFn InitializerGenerator::generateBias(const graph::operation::Conv2DNode &node)
-{
- // TODO Refactor so we can reuse the common code
-
- const auto bias_index{node.getInputs().at(2)};
-
- auto bias_base = _ctx.at(bias_index).data().base();
- const auto bias_size = _ctx.at(bias_index).shape().asVector();
-
- return [bias_base, bias_size](::arm_compute::ITensor &tensor) {
- for (int32_t n = 0; n < bias_size; ++n)
- {
- const ::arm_compute::Coordinates coordinate{n};
-
- float *into = reinterpret_cast<float *>(tensor.ptr_to_element(coordinate));
-
- const float *from = reinterpret_cast<const float *>(bias_base) + n;
- const auto value = *from;
-
- *into = value;
- }
- };
-}
-
-InitializerFn InitializerGenerator::generateBias(const graph::operation::FullyConnectedNode &node)
-{
- const auto bias_index{node.getInputs().at(2)};
-
- auto bias_base = _ctx.at(bias_index).data().base();
- const auto bias_size = _ctx.at(bias_index).shape().asVector();
-
- return [bias_base, bias_size](::arm_compute::ITensor &tensor) {
- for (int32_t n = 0; n < bias_size; ++n)
- {
- const ::arm_compute::Coordinates coordinate{n};
-
- float *into = reinterpret_cast<float *>(tensor.ptr_to_element(coordinate));
-
- const float *from = reinterpret_cast<const float *>(bias_base) + n;
- const auto value = *from;
-
- *into = value;
- }
- };
-}
-
-} // namespace acl_cl
-} // namespace backend
-} // namespace neurun
+++ /dev/null
-/*
- * 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.
- */
-
-#ifndef __NEURUN_BACKEND_ACL_CL_INITIALIZER_GENERATOR_H__
-#define __NEURUN_BACKEND_ACL_CL_INITIALIZER_GENERATOR_H__
-
-#include "backend/interface/IInitializerGenerator.h"
-
-#include "graph/operand/Set.h"
-
-namespace neurun
-{
-namespace backend
-{
-namespace acl_cl
-{
-
-class InitializerGenerator : public IInitializerGenerator
-{
-public:
- InitializerGenerator(const neurun::graph::operand::Set &ctx);
-
-public:
- Initializer generate(const graph::operation::Conv2DNode &node) override;
- Initializer generate(const graph::operation::FullyConnectedNode &node) override;
-
-private:
- InitializerFn generateWeight(const graph::operation::Conv2DNode &node);
- InitializerFn generateWeight(const graph::operation::FullyConnectedNode &node);
-
- InitializerFn generateBias(const graph::operation::Conv2DNode &node);
- InitializerFn generateBias(const graph::operation::FullyConnectedNode &node);
-
-private:
- const neurun::graph::operand::Set &_ctx;
-};
-
-} // namespace acl_cl
-} // namespace backend
-} // namespace neurun
-
-#endif // __NEURUN_BACKEND_ACL_CL_INITIALIZER_GENERATOR_H__
+++ /dev/null
-/*
- * 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 "InitializerGenerator.h"
-
-#include "internal/nnapi/kernel/Reader.h"
-#include "internal/nnapi/kernel/View.h"
-#include "util/kernel/IndexIterator.h"
-
-#include "NeuralNetworks.h"
-
-namespace neurun
-{
-namespace backend
-{
-namespace cpu
-{
-
-InitializerGenerator::InitializerGenerator(const neurun::graph::operand::Set &ctx) : _ctx(ctx)
-{
- // DO NOTHING
-}
-
-Initializer InitializerGenerator::generate(const graph::operation::Conv2DNode &node)
-{
- using graph::operation::Conv2DNode;
-
- Initializer ret;
- ret.push_back({node.getInputs().at(Conv2DNode::Input::KERNEL), generateWeight(node)});
- ret.push_back({node.getInputs().at(Conv2DNode::Input::BIAS), generateBias(node)});
- return ret;
-}
-
-Initializer InitializerGenerator::generate(const graph::operation::FullyConnectedNode &node)
-{
- using graph::operation::FullyConnectedNode;
-
- Initializer ret;
- ret.push_back({node.getInputs().at(FullyConnectedNode::Input::WEIGHT), generateWeight(node)});
- ret.push_back({node.getInputs().at(FullyConnectedNode::Input::BIAS), generateBias(node)});
- return ret;
-}
-
-InitializerFn InitializerGenerator::generateWeight(const graph::operation::Conv2DNode &node)
-{
- const auto ker_index{node.getInputs().at(1)};
-
- const auto ker_shape = _ctx.at(ker_index).shape().asKernel();
- auto ker_base = _ctx.at(ker_index).data().base();
- auto ker_size = _ctx.at(ker_index).data().size();
-
- return [ker_shape, ker_base, ker_size](::arm_compute::ITensor &tensor) {
- const ::internal::nnapi::kernel::Reader<float> from{ker_shape, ker_base, ker_size};
- ::internal::nnapi::kernel::View<float> into{&tensor};
-
- ::nnfw::util::kernel::iterate(ker_shape)
- << [&](uint32_t nth, uint32_t ch, uint32_t row, uint32_t col) {
- const auto value = from.at(nth, ch, row, col);
- into.at(nth, row, col, ch) = value;
- };
- };
-}
-
-InitializerFn InitializerGenerator::generateWeight(const graph::operation::FullyConnectedNode &node)
-{
- const auto weight_index{node.getInputs().at(1)};
- const auto input_index{node.getInputs().at(0)};
-
- const auto num_output = _ctx.at(weight_index).shape().dim(0);
- auto weight_base = _ctx.at(weight_index).data().base();
- auto weight_size = _ctx.at(weight_index).data().size();
- auto weight_type = _ctx.at(weight_index).typeInfo().type();
-
- // NOTE We assume that input is a feature map
- // TODO Remove this restriction!
- const auto ifm_shape = _ctx.at(input_index).shape().asFeature();
-
- switch (weight_type)
- {
- case ::neurun::graph::operand::DataType::TENSOR_FLOAT32:
- {
- return [num_output, ifm_shape, weight_base, weight_size](::arm_compute::ITensor &tensor) {
- const ::nnfw::util::kernel::Shape ker_shape{num_output, ifm_shape.C, ifm_shape.H,
- ifm_shape.W};
- const ::internal::nnapi::kernel::Reader<float> from{ker_shape, weight_base, weight_size};
-
- ::nnfw::util::kernel::iterate(ker_shape)
- << [&](uint32_t nth, uint32_t ch, uint32_t row, uint32_t col) {
- const auto value = from.at(nth, ch, row, col);
-
- uint32_t offset = 0;
-
- // NNAPI uses NHWC ordering
- offset += nth * ifm_shape.H * ifm_shape.W * ifm_shape.C;
- offset += row * ifm_shape.W * ifm_shape.C;
- offset += col * ifm_shape.C;
- offset += ch;
-
- const ::arm_compute::Coordinates coordinate{offset};
-
- auto into = reinterpret_cast<float *>(tensor.ptr_to_element(coordinate));
-
- *into = value;
- };
- };
- }
- case ::neurun::graph::operand::DataType::TENSOR_QUANT8_ASYMM:
- {
- return [num_output, ifm_shape, weight_base, weight_size](::arm_compute::ITensor &tensor) {
- const ::nnfw::util::kernel::Shape ker_shape{num_output, ifm_shape.C, ifm_shape.H,
- ifm_shape.W};
- const ::internal::nnapi::kernel::Reader<uint8_t> from{ker_shape, weight_base, weight_size};
- ::nnfw::util::kernel::iterate(ker_shape)
- << [&](uint32_t nth, uint32_t ch, uint32_t row, uint32_t col) {
- const auto value = from.at(nth, ch, row, col);
- uint32_t offset = 0;
-
- // NNAPI uses NHWC ordering
- offset += nth * ifm_shape.H * ifm_shape.W * ifm_shape.C;
- offset += row * ifm_shape.W * ifm_shape.C;
- offset += col * ifm_shape.C;
- offset += ch;
-
- const ::arm_compute::Coordinates coordinate{offset};
-
- auto into = reinterpret_cast<uint8_t *>(tensor.ptr_to_element(coordinate));
-
- *into = value;
- };
- };
- }
- default:
- {
- throw std::runtime_error("Not supported weight type");
- }
- }
-}
-
-InitializerFn InitializerGenerator::generateBias(const graph::operation::Conv2DNode &node)
-{
- // TODO Refactor so we can reuse the common code
-
- const auto bias_index{node.getInputs().at(2)};
-
- auto bias_base = _ctx.at(bias_index).data().base();
- const auto bias_size = _ctx.at(bias_index).shape().asVector();
-
- return [bias_base, bias_size](::arm_compute::ITensor &tensor) {
- for (int32_t n = 0; n < bias_size; ++n)
- {
- const ::arm_compute::Coordinates coordinate{n};
-
- float *into = reinterpret_cast<float *>(tensor.ptr_to_element(coordinate));
-
- const float *from = reinterpret_cast<const float *>(bias_base) + n;
- const auto value = *from;
-
- *into = value;
- }
- };
-}
-
-InitializerFn InitializerGenerator::generateBias(const graph::operation::FullyConnectedNode &node)
-{
- const auto bias_index{node.getInputs().at(2)};
-
- auto bias_base = _ctx.at(bias_index).data().base();
- auto bias_type = _ctx.at(bias_index).typeInfo().type();
- const auto bias_size = _ctx.at(bias_index).shape().asVector();
-
- switch (bias_type)
- {
- case ::neurun::graph::operand::DataType::TENSOR_FLOAT32:
- {
- return [bias_base, bias_size](::arm_compute::ITensor &tensor) {
- for (int32_t n = 0; n < bias_size; ++n)
- {
- const ::arm_compute::Coordinates coordinate{n};
-
- float *into = reinterpret_cast<float *>(tensor.ptr_to_element(coordinate));
-
- const float *from = reinterpret_cast<const float *>(bias_base) + n;
- const auto value = *from;
-
- *into = value;
- }
- };
- }
- case ::neurun::graph::operand::DataType::TENSOR_QUANT8_ASYMM:
- {
- return [bias_base, bias_size](::arm_compute::ITensor &tensor) {
- for (int32_t n = 0; n < bias_size; ++n)
- {
- const ::arm_compute::Coordinates coordinate{n};
-
- uint8_t *into = reinterpret_cast<uint8_t *>(tensor.ptr_to_element(coordinate));
-
- const uint8_t *from = reinterpret_cast<const uint8_t *>(bias_base) + n;
- const auto value = *from;
-
- *into = value;
- }
- };
- }
- default:
- {
- throw std::runtime_error("Not supported bias type");
- }
- }
-}
-
-} // namespace cpu
-} // namespace backend
-} // namespace neurun
+++ /dev/null
-/*
- * 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.
- */
-
-#ifndef __NEURUN_BACKEND_CPU_INITIALIZER_GENERATOR_H__
-#define __NEURUN_BACKEND_CPU_INITIALIZER_GENERATOR_H__
-
-#include "backend/interface/IInitializerGenerator.h"
-
-#include "graph/operand/Set.h"
-
-namespace neurun
-{
-namespace backend
-{
-namespace cpu
-{
-
-class InitializerGenerator : public IInitializerGenerator
-{
-public:
- InitializerGenerator(const neurun::graph::operand::Set &ctx);
-
-public:
- Initializer generate(const graph::operation::Conv2DNode &node) override;
- Initializer generate(const graph::operation::FullyConnectedNode &node) override;
-
-private:
- InitializerFn generateWeight(const graph::operation::Conv2DNode &node);
- InitializerFn generateWeight(const graph::operation::FullyConnectedNode &node);
-
- InitializerFn generateBias(const graph::operation::Conv2DNode &node);
- InitializerFn generateBias(const graph::operation::FullyConnectedNode &node);
-
-private:
- const neurun::graph::operand::Set &_ctx;
-};
-
-} // namespace cpu
-} // namespace backend
-} // namespace neurun
-
-#endif // __NEURUN_BACKEND_CPU_INITIALIZER_GENERATOR_H__
+++ /dev/null
-/*
- * 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.
- */
-
-#ifndef __NEURUN_BACKEND_IINITIALIZER_GENERATOR_H__
-#define __NEURUN_BACKEND_IINITIALIZER_GENERATOR_H__
-
-#include <list>
-
-#include "arm_compute/core/ITensor.h"
-
-#include "graph/operand/Index.h"
-#include "graph/operation/Conv2D.h"
-#include "graph/operation/MaxPool2D.h"
-#include "graph/operation/AvgPool2D.h"
-#include "graph/operation/Concat.h"
-#include "graph/operation/FullyConnected.h"
-#include "graph/operation/Reshape.h"
-#include "graph/operation/Softmax.h"
-#include "graph/operation/NOP.h"
-#include "graph/operation/Permute.h"
-#include "graph/operation/Add.h"
-
-using InitializerFn = std::function<void(::arm_compute::ITensor &)>;
-
-struct InitializerEntry
-{
- neurun::graph::operand::Index index;
- InitializerFn fn;
-};
-
-using Initializer = std::list<InitializerEntry>;
-
-namespace neurun
-{
-namespace backend
-{
-
-struct IInitializerGenerator
-{
- virtual ~IInitializerGenerator() = default;
-
- virtual Initializer generate(const graph::operation::Conv2DNode &) { return Initializer{}; }
- virtual Initializer generate(const graph::operation::MaxPool2DNode &) { return Initializer{}; }
- virtual Initializer generate(const graph::operation::AvgPool2DNode &) { return Initializer{}; }
- virtual Initializer generate(const graph::operation::ConcatNode &) { return Initializer{}; }
- virtual Initializer generate(const graph::operation::FullyConnectedNode &)
- {
- return Initializer{};
- }
- virtual Initializer generate(const graph::operation::ReshapeNode &) { return Initializer{}; }
- virtual Initializer generate(const graph::operation::SoftmaxNode &) { return Initializer{}; }
- virtual Initializer generate(const graph::operation::NOPNode &) { return Initializer{}; }
- virtual Initializer generate(const graph::operation::PermuteNode &) { return Initializer{}; }
- virtual Initializer generate(const graph::operation::AddNode &) { return Initializer{}; }
-};
-
-} // namespace backend
-} // namespace neurun
-#endif // __NEURUN_BACKEND_IINITIALIZER_GENERATOR_H__
#include "arm_compute/core/TensorInfo.h"
#include "backend/interface/IStageGenerator.h"
-#include "backend/interface/IInitializerGenerator.h"
namespace neurun
{
virtual void addShapeConstr(const ::neurun::graph::operand::Index &ind,
const ::arm_compute::TensorInfo &info) = 0;
- virtual void addInitializer(const Initializer &initializer) = 0;
virtual void addStage(const Stage &) = 0;
};
_tensor_info_ctx[ind.asInt()] = info;
}
-void PlanBuilder::addInitializer(const Initializer &initializer)
-{
- for (auto &entry : initializer)
- {
- _initializer_ctx[entry.index.asInt()] = entry.fn;
- }
-}
-
void PlanBuilder::addStage(const Stage &stage) { _stages.emplace_back(stage); }
void PlanBuilder::finalize(const backend::TensorBuilderSet &tensor_builders)
const ::arm_compute::TensorInfo &info) override;
public:
- void addInitializer(const Initializer &initializer) override;
-
-public:
void addStage(const Stage &stage) override;
public:
private:
std::map<int, ::arm_compute::TensorInfo> _tensor_info_ctx;
- std::map<int, InitializerFn> _initializer_ctx;
std::vector<Stage> _stages;
};