Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NNAdapter] Add fill_range fuse pass、eliminate range op、move scale and expand_v2 op #7200

Merged
merged 23 commits into from
Oct 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d84e65d
fix fill and range
shentanyue Sep 27, 2021
ad94f90
[NNAdapter] add fill_range and range pass rule, fix expand_v2 and scale
shentanyue Oct 12, 2021
5b5ee4e
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle-Lite…
shentanyue Oct 12, 2021
1c0725e
[NNAdapter] add fill_range and range pass rule, fix expand_v2 and scale
shentanyue Oct 12, 2021
85b1467
[NNAdapter] add fill_range and range pass rule, fix expand_v2 and scale
shentanyue Oct 12, 2021
9a68eff
[NNAdapter] add fill_range and range pass rule, fix expand_v2 and scale
shentanyue Oct 12, 2021
24404bc
delete range op
shentanyue Oct 12, 2021
ec46ff7
test=huawei_ascend_npu
shentanyue Oct 12, 2021
3f59de1
test=huawei_ascend_npu
shentanyue Oct 12, 2021
319ee4f
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle-Lite…
shentanyue Oct 12, 2021
77907e6
add scene of the input as an intermediate tensor
shentanyue Oct 13, 2021
5078b09
test=huawei_ascend_npu
shentanyue Oct 13, 2021
ebaac47
test=huawei_ascend_npu
shentanyue Oct 14, 2021
26c7b73
test=huawei_ascend_npu
shentanyue Oct 19, 2021
92cd7b7
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle-Lite…
shentanyue Oct 19, 2021
e30558c
test=huawei_ascend_npu
shentanyue Oct 19, 2021
61bde22
test=huawei_ascend_npu
shentanyue Oct 19, 2021
19ea81f
test=huawei_ascend_npu
shentanyue Oct 19, 2021
5d80c35
test=huawei_ascend_npu
shentanyue Oct 20, 2021
30ad4ca
test=huawei_ascend_npu
shentanyue Oct 20, 2021
3bbbe1e
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle-Lite…
shentanyue Oct 21, 2021
e55d24f
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle-Lite…
shentanyue Oct 22, 2021
cc7c5ce
fix x86 compile error test=huawei_ascend_npu
shentanyue Oct 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lite/api/paddle_use_passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,5 @@ USE_MIR_PASS(__xpu__dynamic_lstm_fuse_pass);
USE_MIR_PASS(__xpu__multi_softmax_fuse_pass);
USE_MIR_PASS(__xpu__max_pooling_pad_zero_detect_fuse_pass);
USE_MIR_PASS(x86_int8_attribute_pass);
USE_MIR_PASS(fill_range_fuse_pass);
USE_MIR_PASS(range_calc_offline_pass);
2 changes: 2 additions & 0 deletions lite/backends/nnadapter/nnadapter/core/operation/all.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ REGISTER_OPERATION(GREATER, PrepareComparisons)
REGISTER_OPERATION(GREATER_EQUAL, PrepareComparisons)
REGISTER_OPERATION(HARD_SIGMOID, PrepareHardSigmoidSwish)
REGISTER_OPERATION(HARD_SWISH, PrepareHardSigmoidSwish)
REGISTER_OPERATION(EXPAND, PrepareExpand)
REGISTER_OPERATION(INSTANCE_NORMALIZATION, PrepareInstanceNormalization)
REGISTER_OPERATION(LAYER_NORMALIZATION, PrepareLayerNormalization)
REGISTER_OPERATION(LEAKY_RELU, PrepareLeakyRelu)
Expand All @@ -55,6 +56,7 @@ REGISTER_OPERATION(MUL, PrepareElementwise)
REGISTER_OPERATION(NOT_EQUAL, PrepareComparisons)
REGISTER_OPERATION(POW, PrepareElementwise)
REGISTER_OPERATION(PRELU, PreparePRelu)
REGISTER_OPERATION(RANGE, PrepareRange)
REGISTER_OPERATION(REDUCE_MEAN, PrepareReduce)
REGISTER_OPERATION(RELU, PrepareUnaryActivations)
REGISTER_OPERATION(RELU6, PrepareUnaryActivations)
Expand Down
99 changes: 99 additions & 0 deletions lite/backends/nnadapter/nnadapter/core/operation/expand.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright (c) 2021 PaddlePaddle Authors. 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 "core/operation/expand.h"
#include <vector>
#include "core/hal/types.h"
#include "utility/debug.h"
#include "utility/logging.h"
#include "utility/modeling.h"
#include "utility/utility.h"

namespace nnadapter {
namespace operation {

int PrepareExpand(hal::Operation* operation) {
EXPAND_OPERATION_EXTRACT_INPUTS_OUTPUTS

// Infer the shape and type of output operands
auto input_type = input_operand->type;
auto& output_type = output_operand->type;
CopyOperandTypeWithQuantParams(&output_type, input_type);

output_type.dimensions.count = shape_count;

auto infer_output_shape = [&](int32_t* input_dimensions_data,
uint32_t input_dimensions_count,
int32_t* output_dimensions_data) {
std::vector<int> input_dims_vec;
for (uint32_t i = 0; i < input_dimensions_count; i++) {
input_dims_vec.push_back(input_dimensions_data[i]);
}
auto diff = shape_count - input_dimensions_count;
input_dims_vec.insert(input_dims_vec.begin(), diff, 1);
std::vector<int> final_expand_shape(input_dimensions_count);
for (uint32_t i = 0; i < input_dims_vec.size(); ++i) {
NNADAPTER_CHECK_NE(shape_data[i], 0)
<< "The expanded size cannot be zero.";
if (i < diff) {
// shape_data = [3,4,-1,-1], X = [10,2] --> // final_expand_shape =
// [3,4,10,2]
NNADAPTER_CHECK_GT(shape_data[i], 0)
<< "The expanded size " << shape_data[i]
<< "for non-existing dimensions must be positive for expand_v2 op.";
final_expand_shape[i] = shape_data[i];
} else if (shape_data[i] > 0) {
// shape_data = [3,4,10,4], X = [10,1] --> final_expand_shape =
// [3,4,10,4]
if (input_dims_vec[i] != 1) {
NNADAPTER_CHECK_EQ(input_dims_vec[i], shape_data[i])
<< "The value " << input_dims_vec[i]
<< " of the non-singleton dimension does not match the "
"corresponding value "
<< shape_data[i] << " in shape for expand_v2 op.";
final_expand_shape[i] = shape_data[i];
} else {
final_expand_shape[i] = shape_data[i];
}
} else {
// shape_data = [3,4,-1,-1], X = [10,2] --> final_expand_shape =
// [3,4,10,2]
NNADAPTER_CHECK_EQ(shape_data[i], -1)
<< "When the value in shape is negative for expand_v2 op, "
"only -1 is supported, but the value received is "
<< shape_data[i];
final_expand_shape[i] = input_dims_vec[i];
}
}

for (uint32_t i = 0; i < shape_count; ++i) {
shape_data[i] = final_expand_shape[i];
output_dimensions_data[i] = final_expand_shape[i];
}
};

infer_output_shape(input_type.dimensions.data,
input_type.dimensions.count,
output_type.dimensions.data);
for (uint32_t i = 0; i < input_type.dimensions.dynamic_count; i++) {
infer_output_shape(input_type.dimensions.dynamic_data[i],
input_type.dimensions.count,
output_type.dimensions.dynamic_data[i]);
}
NNADAPTER_VLOG(5) << "output: " << OperandToString(output_operand);
return NNADAPTER_NO_ERROR;
}

} // namespace operation
} // namespace nnadapter
22 changes: 20 additions & 2 deletions lite/backends/nnadapter/nnadapter/core/operation/expand.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,26 @@ namespace operation {
NNADAPTER_VLOG(5) << "input_operand: " << OperandToString(input_operand); \
/* Shape */ \
auto shape_operand = input_operands[1]; \
NNADAPTER_VLOG(5) << "shape operand: " \
<< OperandValueToString(shape_operand); \
NNADAPTER_VLOG(5) << "shape operand: " << OperandToString(shape_operand); \
uint32_t shape_count; \
int32_t* shape_data; \
auto& shape_type = shape_operand->type; \
if (IsConstantOperand(shape_operand)) { \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不建议把这些判断放在.h里面,将其放在.cc的infershape里面吧,而且else部分的代码有问题,shape_operand->type.dimensions.data 指的是 shape_operand 自己的维度信息

shape_count = shape_operand->length / sizeof(int32_t); \
shape_data = reinterpret_cast<int32_t*>(shape_operand->buffer); \
} else if (shape_type.lifetime == NNADAPTER_TEMPORARY_SHAPE) { \
auto shape_operand_dimension = \
*reinterpret_cast<NNAdapterOperandDimensionType*>( \
shape_operand->buffer); \
shape_count = shape_operand_dimension.count; \
shape_data = shape_operand_dimension.data; \
} else { \
shape_count = shape_operand->type.dimensions.count; \
shape_data = shape_operand->type.dimensions.data; \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

为什么要等于shape_operand的维度data?
这种情况可能是来自于一个temporary shape operand , 可以参考 fill 的实现

output_type.dimensions = *reinterpret_cast<NNAdapterOperandDimensionType*>(

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

} \
for (uint32_t i = 0; i < shape_count; i++) { \
NNADAPTER_VLOG(5) << "shape[" << i << "] = " << shape_data[i]; \
} \
/* Output */ \
auto output_operand = output_operands[0]; \
NNADAPTER_VLOG(5) << "output_operand: " << OperandToString(output_operand);
Expand Down
1 change: 1 addition & 0 deletions lite/backends/nnadapter/nnadapter/core/operation/fill.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ int PrepareFill(hal::Operation* operation) {
return NNADAPTER_INVALID_PARAMETER;
}
output_type.precision = value_operand->type.precision;
output_type.lifetime = NNADAPTER_TEMPORARY_VARIABLE;
NNADAPTER_VLOG(5) << "output: " << OperandToString(output_operand);
return NNADAPTER_NO_ERROR;
}
Expand Down
53 changes: 53 additions & 0 deletions lite/backends/nnadapter/nnadapter/core/operation/range.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) 2021 PaddlePaddle Authors. 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 "core/operation/range.h"
#include "core/hal/types.h"
#include "utility/debug.h"
#include "utility/logging.h"
#include "utility/modeling.h"
#include "utility/utility.h"

namespace nnadapter {
namespace operation {

int PrepareRange(hal::Operation* operation) {
RANGE_OPERATION_EXTRACT_INPUTS_OUTPUTS

// Infer the shape and type of output operands
auto& output_type = output_operand->type;
NNADAPTER_CHECK_EQ(start_operand->type.dimensions.count, 1);
NNADAPTER_CHECK_EQ(limit_operand->type.dimensions.count, 1);
NNADAPTER_CHECK_EQ(delta_operand->type.dimensions.count, 1);

if (IsConstantOperand(start_operand) && IsConstantOperand(limit_operand) &&
IsConstantOperand(delta_operand)) {
auto start_data = reinterpret_cast<float*>(start_operand->buffer)[0];
auto limit_data = reinterpret_cast<float*>(limit_operand->buffer)[0];
auto delta_data = reinterpret_cast<float*>(delta_operand->buffer)[0];
output_type.dimensions.data[0] =
GetSpanCount(start_data, limit_data, delta_data);
} else {
output_type.dimensions.data[0] = NNADAPTER_UNKNOWN;
}
output_type.precision = start_operand->type.precision;
output_type.lifetime = NNADAPTER_TEMPORARY_VARIABLE;
output_type.dimensions.count = 1;

NNADAPTER_VLOG(5) << "output: " << OperandToString(output_operand);
return NNADAPTER_NO_ERROR;
}

} // namespace operation
} // namespace nnadapter
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,13 @@ int ConvertExpand(Converter* converter, hal::Operation* operation) {
if (!input_operator) {
input_operator = converter->ConvertOperand(input_operand);
}
auto shape_operator = converter->ConvertOperand(shape_operand);
auto expand_op = converter->AddOperator<ge::op::Expand>(output_operand);
auto expand_op = converter->AddOperator<ge::op::ExpandD>(output_operand);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

为什么不用之前的ge::op::Expand支持shape作为输入,而是用只支持shape属性的ExpandD?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

因为在跑ppyolo模型时,expand算子出现了bug。后来参照训练那边的实现,同时改了两处地方修复了。
1、是expand支持为-1的情况
2、是改成ge::op::ExpandD

std::vector<int64_t> expand_shape(shape_count);
for (uint32_t i = 0; i < shape_count; i++) {
expand_shape[i] = shape_data[i];
}
expand_op->set_attr_shape(ge::Operator::OpListInt(expand_shape));
SET_INPUT(expand_op, x, input_operator);
SET_INPUT(expand_op, shape, shape_operator);
MAP_OUTPUT(expand_op, y, output_operand);
return NNADAPTER_NO_ERROR;
}
Expand Down
8 changes: 8 additions & 0 deletions lite/backends/nnadapter/nnadapter/utility/utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <sys/time.h>
#include <algorithm>
#include <cmath>
#include <map>
#include <string>
#include <vector>
Expand Down Expand Up @@ -218,4 +219,11 @@ inline int64_t GetCurrentUS() {
return 1000000LL * (int64_t)time.tv_sec + (int64_t)time.tv_usec;
}

template <typename T>
int64_t GetSpanCount(T start, T end, T step) {
return std::is_integral<T>::value
? ((std::abs(end - start) + std::abs(step) - 1) / std::abs(step))
: std::ceil(std::abs((end - start) / step));
}

} // namespace nnadapter
1 change: 1 addition & 0 deletions lite/backends/x86/math/gemm_s8u8_compute.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ limitations under the License. */

#include <string.h>
#include <algorithm>
#include <cmath>
#include "lite/backends/x86/math/gemm_s8u8_kernel.h"
#include "lite/backends/x86/math/gemm_s8u8_pack.h"
#include "lite/core/memory.h"
Expand Down
100 changes: 100 additions & 0 deletions lite/core/optimizer/mir/elimination/range_calc_offline_pass.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) 2019 PaddlePaddle Authors. 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 "lite/core/optimizer/mir/elimination/range_calc_offline_pass.h"
#include <algorithm>
#include <cmath>
#include <list>
#include <memory>
#include <set>
#include <vector>
#include "lite/core/optimizer/mir/pass.h"
#include "lite/core/optimizer/mir/pass_registry.h"
#include "lite/core/optimizer/mir/pattern_matcher.h"
#include "lite/model_parser/cpp_desc.h"

namespace paddle {
namespace lite {
namespace mir {

template <typename T>
int64_t GetSpanCount(T start, T end, T step) {
return std::is_integral<T>::value
? ((std::abs(end - start) + std::abs(step) - 1) / std::abs(step))
: std::ceil(std::abs((end - start) / step));
}

void RangeCalcOfflinePass::Apply(const std::unique_ptr<SSAGraph>& graph) {
RemoveRangePattern(graph);
}

void RangeCalcOfflinePass::RemoveRangePattern(
const std::unique_ptr<SSAGraph>& graph) {
for (auto& node : graph->StmtTopologicalOrder()) {
if (node->AsStmt().picked_kernel().op_type() != "range") continue;

std::set<const Node*> nodes2rm_;
auto& range_instruct = node->AsStmt();
auto* scope = range_instruct.op()->scope();
auto op_desc = range_instruct.mutable_op_info();

// Get range's input tensor
auto start_var = scope->FindVar(op_desc->Input("Start").front());
auto end_var = scope->FindVar(op_desc->Input("End").front());
auto step_var = scope->FindVar(op_desc->Input("Step").front());
auto start_t = start_var->GetMutable<lite::Tensor>();
auto end_t = end_var->GetMutable<lite::Tensor>();
auto step_t = step_var->GetMutable<lite::Tensor>();
if (!start_t->persistable() || !end_t->persistable() ||
!step_t->persistable()) {
LOG(WARNING) << "RangeCalcOfflinePass does not support input that is not "
"persistent";
return;
}
auto start = start_t->mutable_data<float>()[0];
auto end = end_t->mutable_data<float>()[0];
auto step = step_t->mutable_data<float>()[0];
// Get range's output tensor
auto out_var = scope->FindVar(op_desc->Output("Out").front());
auto out_t = out_var->GetMutable<lite::Tensor>();

// Calc range
int64_t size = GetSpanCount(start, end, step);

out_t->Resize(DDim({size}));
auto out_data = out_t->mutable_data<float>();

float value = start;
for (int64_t i = 0; i < size; ++i) {
out_data[i] = value;
value += step;
}
// Offline calc range, only retain output tensor as persistable tensor
out_t->set_persistable(true);
auto range_outlinks = node->outlinks;
for (auto& range_out_link : range_outlinks) {
range_out_link->arg()->is_weight = true;
}
nodes2rm_.insert(node);
GraphSafeRemoveNodes(graph.get(), nodes2rm_);
}
}

} // namespace mir
} // namespace lite
} // namespace paddle

REGISTER_MIR_PASS(range_calc_offline_pass,
paddle::lite::mir::RangeCalcOfflinePass)
.BindTargets({TARGET(kNNAdapter)});
38 changes: 38 additions & 0 deletions lite/core/optimizer/mir/elimination/range_calc_offline_pass.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) 2021 PaddlePaddle Authors. 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.

#pragma once

#include <limits>
#include <memory>
#include <string>
#include <vector>
#include "lite/core/optimizer/mir/pass.h"
#include "lite/core/optimizer/mir/pass_registry.h"
#include "lite/core/tensor.h"
#include "lite/core/types.h"

namespace paddle {
namespace lite {
namespace mir {

class RangeCalcOfflinePass : public mir::StmtPass {
public:
void Apply(const std::unique_ptr<SSAGraph>& graph) override;
void RemoveRangePattern(const std::unique_ptr<SSAGraph>& graph);
};

} // namespace mir
} // namespace lite
} // namespace paddle
Loading