未验证 提交 3ce14a35 编写于 作者: Y yeliang2258 提交者: GitHub

Support npu kernel for Crop op (#34542)

* add crop npu op

* code style check

* update code to remove usless headers

* add testcase and upsate code
上级 a7c38367
/* 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 "paddle/fluid/operators/crop_op.h"
#include "paddle/fluid/operators/npu_op_runner.h"
namespace paddle {
namespace operators {
using Tensor = framework::Tensor;
template <typename DeviceContext, typename T>
class CropNPUKernel : public framework::OpKernel<T> {
public:
void Compute(const framework::ExecutionContext& ctx) const override {
auto* x = ctx.Input<framework::Tensor>("X");
std::vector<int> offset_list;
if (ctx.HasInput("Offsets")) {
auto* offsets_tensor = ctx.Input<framework::Tensor>("Offsets");
TensorToVector(*offsets_tensor, ctx.device_context(), &offset_list);
if (offset_list.empty()) {
offset_list.resize(x->dims().size(), 0);
}
} else {
auto res = ctx.Attr<std::vector<int>>("offsets");
if (res.empty()) {
offset_list.resize(x->dims().size(), 0);
} else {
offset_list.insert(offset_list.end(), res.begin(), res.end());
}
}
PADDLE_ENFORCE_EQ(
static_cast<int64_t>(offset_list.size()), x->dims().size(),
platform::errors::InvalidArgument(
"The shape (%d) of CropOp's "
"'offset' attribute should be equal to the shape of dims "
"(%d) of the Input(X).",
offset_list.size(), x->dims().size()));
int axis_int = 0;
framework::NPUAttributeMap attr_input = {{"offsets", offset_list},
{"axis", axis_int}};
auto* out = ctx.Output<framework::Tensor>("Out");
out->mutable_data<T>(ctx.GetPlace());
if (ctx.HasInput("Y")) {
auto* shape = ctx.Input<framework::Tensor>("Y");
PADDLE_ENFORCE_EQ(shape->dims().size(), x->dims().size(),
platform::errors::InvalidArgument(
"The shape of dims of (%d) of CropOp's "
"Input(shape) should be equal to the shape of dims "
"(%d) of the Input(X).",
shape->dims().size(), x->dims().size()));
const auto& runner =
NpuOpRunner("Crop", {*x, *shape}, {*out}, attr_input);
auto stream =
ctx.template device_context<paddle::platform::NPUDeviceContext>()
.stream();
runner.Run(stream);
} else {
auto shape_size = ctx.Attr<std::vector<int>>("shape");
PADDLE_ENFORCE_EQ(shape_size.size(), x->dims().size(),
platform::errors::InvalidArgument(
"The shape of dims of (%d) of CropOp's "
"Input(shape) should be equal to the shape of dims "
"(%d) of the Input(X).",
shape_size.size(), x->dims().size()));
Tensor tmp_shape(x->type());
tmp_shape.Resize(framework::make_ddim(shape_size));
tmp_shape.mutable_data<T>(ctx.GetPlace());
const auto& runner =
NpuOpRunner("Crop", {*x, tmp_shape}, {*out}, attr_input);
auto stream =
ctx.template device_context<paddle::platform::NPUDeviceContext>()
.stream();
runner.Run(stream);
}
}
};
} // namespace operators
} // namespace paddle
namespace ops = paddle::operators;
REGISTER_OP_NPU_KERNEL(
crop, ops::CropNPUKernel<paddle::platform::NPUDeviceContext, float>,
ops::CropNPUKernel<paddle::platform::NPUDeviceContext, int>,
ops::CropNPUKernel<paddle::platform::NPUDeviceContext,
paddle::platform::float16>);
# 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.
from __future__ import print_function
import numpy as np
import unittest
import sys
sys.path.append("..")
from op_test import OpTest
import paddle
import paddle.fluid as fluid
from paddle.fluid import core
from test_crop_op import crop
paddle.enable_static()
np.random.seed(10)
class TestCropOp(OpTest):
def setUp(self):
self.set_npu()
self.place = paddle.NPUPlace(0)
self.op_type = "crop"
self.attrs = {}
self.offset_by_input = False
self.crop_by_input = False
self.dtype = np.float32
self.initTestCase()
if self.crop_by_input:
self.inputs = {
'X': np.random.random(self.x_shape).astype(self.dtype),
'Y': np.random.random(self.crop_shape).astype(self.dtype)
}
else:
self.attrs['shape'] = self.crop_shape
self.inputs = {
'X': np.random.random(self.x_shape).astype(self.dtype),
}
if self.offset_by_input:
self.inputs['Offsets'] = np.array(self.offsets).astype('int32')
else:
self.attrs['offsets'] = self.offsets
if len(self.offsets) == 0:
self.offsets = np.zeros_like(self.crop_shape)
self.outputs = {
'Out': crop(self.inputs['X'], self.offsets, self.crop_shape)
}
def set_npu(self):
self.__class__.use_npu = True
def initTestCase(self):
self.x_shape = (10, 10)
self.crop_shape = [2, 2]
self.offsets = [1, 2]
def test_check_output(self):
self.check_output_with_place(self.place)
class TestCase1(TestCropOp):
def initTestCase(self):
self.x_shape = (16, 8, 32)
self.crop_shape = [2, 2, 3]
self.offsets = [1, 5, 3]
class TestCase2(TestCropOp):
def initTestCase(self):
self.x_shape = (15, 8)
self.crop_shape = [15, 8]
self.offsets = [0, 0]
class TestCase3(TestCropOp):
def initTestCase(self):
self.x_shape = (4, 10)
self.crop_shape = [2, 3]
self.offsets = [0, 2]
self.offset_by_input = True
class TestCase4(TestCropOp):
def initTestCase(self):
self.x_shape = (10, 9, 14)
self.crop_shape = [3, 3, 5]
self.offsets = []
class TestCase5(TestCropOp):
def initTestCase(self):
self.x_shape = (10, 9, 14)
self.crop_shape = [3, 3, 5]
self.offsets = [3, 5, 4]
self.offset_by_input = True
class TestCase6(TestCropOp):
def initTestCase(self):
self.x_shape = (10, 9, 14)
self.crop_shape = [3, 3, 5]
self.offsets = [3, 5, 4]
self.offset_by_input = True
self.__class__.no_need_check_grad = True
self.dtype = np.float16
class TestCase7(TestCropOp):
def initTestCase(self):
self.x_shape = (10, 9, 14)
self.crop_shape = [3, 3, 5]
self.offsets = [3, 5, 4]
self.offset_by_input = True
self.dtype = np.int32
class TestCase8(TestCropOp):
def initTestCase(self):
self.x_shape = (10, 9, 14)
self.crop_shape = [3, 3, 5]
self.offsets = []
self.offset_by_input = True
class TestCase9(TestCropOp):
def initTestCase(self):
self.x_shape = (10, 9, 14)
self.crop_shape = [3, 3, 5]
self.offsets = [3, 5, 4]
self.crop_by_input = True
class TestCase10(TestCropOp):
def initTestCase(self):
self.x_shape = (10, 9, 14)
self.crop_shape = [3, 3, 5]
self.offsets = [3, 5, 4]
self.crop_by_input = True
self.offset_by_input = True
if __name__ == '__main__':
unittest.main()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册