Skip to content

Commit

Permalink
[onert] Implement Floor kernel for cpu backend (Samsung#4809)
Browse files Browse the repository at this point in the history
This commit implements Floor kernel for cpu backend

ONE-DCO-1.0-Signed-off-by: hansolu <[email protected]>
  • Loading branch information
hasw7569 authored Oct 29, 2020
1 parent a2d600d commit 7f806ca
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 0 deletions.
11 changes: 11 additions & 0 deletions compute/cker/include/cker/operation/Elementwise.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,17 @@ inline void Log(const Shape &input_shape, const float *input_data, const Shape &
}
}

inline void Floor(const Shape &input_shape, const float *input_data, const Shape &output_shape,
float *output_data)
{
const int flat_size = MatchingFlatSize(input_shape, output_shape);

for (int i = 0; i < flat_size; i++)
{
output_data[i] = std::floor(input_data[i]);
}
}

} // namespace cker
} // namespace nnfw

Expand Down
2 changes: 2 additions & 0 deletions runtime/onert/backend/cpu/KernelGenerator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ ops::ElementwiseUnaryType convertElementwiseUnaryType(ir::operation::Elementwise
return ops::ElementwiseUnaryType::kErf;
case ir::operation::ElementwiseUnary::Type::EXP:
return ops::ElementwiseUnaryType::kExp;
case ir::operation::ElementwiseUnary::Type::FLOOR:
return ops::ElementwiseUnaryType::kFloor;
case ir::operation::ElementwiseUnary::Type::LOG:
return ops::ElementwiseUnaryType::kLog;
case ir::operation::ElementwiseUnary::Type::LOGICAL_NOT:
Expand Down
16 changes: 16 additions & 0 deletions runtime/onert/backend/cpu/ops/ElementwiseUnaryLayer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,12 @@ void erfFloat32(const IPortableTensor *input, IPortableTensor *output)
getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
}

void floorFloat32(const IPortableTensor *input, IPortableTensor *output)
{
nnfw::cker::Floor(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
}

void logFloat32(const IPortableTensor *input, IPortableTensor *output)
{
nnfw::cker::Log(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
Expand Down Expand Up @@ -269,6 +275,16 @@ void ElementwiseUnaryLayer::configure(const IPortableTensor *input, IPortableTen
throw std::runtime_error{"Exp: Unsupported data type"};
}
break;
case ElementwiseUnaryType::kFloor:
if ((input->data_type() == OperandType::FLOAT32))
{
_kernel = floorFloat32;
}
else
{
throw std::runtime_error{"Floor: Unsupported data type"};
}
break;
case ElementwiseUnaryType::kLog:
if ((input->data_type() == OperandType::FLOAT32))
{
Expand Down
1 change: 1 addition & 0 deletions runtime/onert/backend/cpu/ops/ElementwiseUnaryLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ enum class ElementwiseUnaryType
kDequantize,
kErf,
kExp,
kFloor,
kLog,
kLogicalNot,
kNeg,
Expand Down
5 changes: 5 additions & 0 deletions runtime/onert/core/src/ir/OperationValidator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@ void OperationValidator::visit(const operation::ElementwiseUnary &node)
OP_REQUIRES(isValidType(input_index, DataType::FLOAT32));
OP_REQUIRES(isValidType(output_index, DataType::QUANT_UINT8_ASYMM));
}
else if (node.param().op_type == operation::ElementwiseUnary::Type::FLOOR)
{
OP_REQUIRES(isValidType(input_index, DataType::FLOAT32));
OP_REQUIRES(isSameType(output_index, input_index));
}
else if (node.param().op_type != operation::ElementwiseUnary::Type::CAST)
{
OP_REQUIRES(isSameType(output_index, input_index));
Expand Down
3 changes: 3 additions & 0 deletions runtime/onert/frontend/base_loader/include/base_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -1332,6 +1332,9 @@ void BaseLoader<LoaderDomain>::loadOperation(const Operator *op, ir::Graph &subg
case BuiltinOperator::BuiltinOperator_CONCATENATION:
loadConcatenation(op, subg);
return;
case BuiltinOperator::BuiltinOperator_FLOOR:
loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::FLOOR);
return;
case BuiltinOperator::BuiltinOperator_FULLY_CONNECTED:
loadFC(op, subg);
return;
Expand Down
6 changes: 6 additions & 0 deletions tests/nnfw_api/src/CircleGen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,12 @@ uint32_t CircleGen::addOperatorFill(const OperatorParams &params)
circle::BuiltinOptions_FillOptions, options);
}

uint32_t CircleGen::addOperatorFloor(const OperatorParams &params)
{
return addOperatorWithOptions(params, circle::BuiltinOperator_FLOOR, circle::BuiltinOptions_NONE,
0);
}

uint32_t CircleGen::addOperatorL2Normalization(const OperatorParams &params)
{
auto options = circle::CreateL2NormOptions(_fbb).Union();
Expand Down
1 change: 1 addition & 0 deletions tests/nnfw_api/src/CircleGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ class CircleGen
uint32_t addOperatorCos(const OperatorParams &params);
uint32_t addOperatorEqual(const OperatorParams &params);
uint32_t addOperatorFill(const OperatorParams &params);
uint32_t addOperatorFloor(const OperatorParams &params);
uint32_t addOperatorFullyConnected(const OperatorParams &params);
uint32_t addOperatorIf(const OperatorParams &params, uint32_t then_subg, uint32_t else_subg);
uint32_t addOperatorInstanceNorm(const OperatorParams &params, float epsilon,
Expand Down
53 changes: 53 additions & 0 deletions tests/nnfw_api/src/one_op_tests/Floor.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2020 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 "GenModelTest.h"

#include <memory>

TEST_F(GenModelTest, OneOp_Floor_4D)
{
CircleGen cgen;

int in = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});

cgen.addOperatorFloor({{in}, {out}});
cgen.setInputsAndOutputs({in}, {out});

_context = std::make_unique<GenModelTestContext>(cgen.finish());
_context->addTestCase(uniformTCD<float>({{1.2, -1.2, 2.6, -2.6}}, {{1.0, -2.0, 2.0, -3.0}}));
_context->setBackends({"cpu"});

SUCCEED();
}

TEST_F(GenModelTest, neg_OneOp_Floor_InvalidType)
{
CircleGen cgen;

int in = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT32});
int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT32});

cgen.addOperatorFloor({{in}, {out}});
cgen.setInputsAndOutputs({in}, {out});

_context = std::make_unique<GenModelTestContext>(cgen.finish());
_context->setBackends({"cpu"});
_context->expectFailModelLoad();

SUCCEED();
}

0 comments on commit 7f806ca

Please sign in to comment.