dnn: add the CANN backend (#22634)

* cann backend impl v1

* cann backend impl v2: use opencv parsers to build models for cann

* adjust fc according to the new transA and transB

* put cann net in cann backend node and reuse forwardLayer

* use fork() to create a child process and compile cann model

* remove legacy code

* remove debug code

* fall bcak to CPU backend if there is one layer not supoorted by CANN backend

* fix netInput forward
This commit is contained in:
Yuantao Feng
2022-12-21 14:04:41 +08:00
committed by GitHub
parent a08c98cdfb
commit a2b3acfc6e
34 changed files with 2208 additions and 28 deletions

View File

@@ -47,6 +47,7 @@
#include "../op_halide.hpp"
#include "../op_inf_engine.hpp"
#include "../op_webnn.hpp"
#include "../op_cann.hpp"
#ifdef HAVE_DNN_NGRAPH
#include "../ie_ngraph.hpp"
@@ -199,6 +200,12 @@ public:
{
return type == MAX || type == AVE || type == ROI;
}
#ifdef HAVE_CANN
if (backendId == DNN_BACKEND_CANN)
{
return type == MAX || type == AVE;
}
#endif
#ifdef HAVE_INF_ENGINE
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
{
@@ -540,6 +547,82 @@ public:
return Ptr<BackendNode>();
}
#ifdef HAVE_CANN
virtual Ptr<BackendNode> initCann(const std::vector<Ptr<BackendWrapper> > &inputsWrapper, const int index, const std::vector<Ptr<BackendNode> >& nodes) CV_OVERRIDE
{
auto x = inputsWrapper[0].dynamicCast<CannBackendWrapper>();
auto op_x = nodes[0].dynamicCast<CannBackendNode>()->getOp();
auto x_desc = x->getTensorDesc();
auto output_desc = std::make_shared<ge::TensorDesc>(ge::Shape(), ge::FORMAT_NCHW, ge::DT_FLOAT);
std::string op_name_base = cv::format("pooling_%d", index);
if (type == MAX)
{
std::string op_name = cv::format("max_%s", op_name_base.c_str());
auto op = std::make_shared<ge::op::MaxPoolV3>(op_name);
// set attributes
op->set_attr_ksize(ge::Operator::OpListInt(
{1, 1, (int64_t)kernel_size[0], (int64_t)kernel_size[1]}
));
op->set_attr_strides(ge::Operator::OpListInt(
{1, 1, (int64_t)strides[0], (int64_t)strides[1]}
));
std::string cann_pad_mode{"CALCULATED"};
if (padMode == "SAME" || padMode == "VALID")
cann_pad_mode = padMode;
op->set_attr_padding_mode(cann_pad_mode.c_str());
op->set_attr_pads(ge::Operator::OpListInt(
{(int64_t)pads_begin[0], (int64_t)pads_end[0], (int64_t)pads_begin[1], (int64_t)pads_end[1]}
));
op->set_attr_data_format("NCHW");
op->set_attr_global_pooling(globalPooling);
op->set_attr_ceil_mode(ceilMode);
// set inputs
op->set_input_x_by_name(*op_x, "y");
op->update_input_desc_x(*x_desc);
// set outputs
op->update_output_desc_y(*output_desc);
return Ptr<BackendNode>(new CannBackendNode(op));
}
else if (type == AVE)
{
std::string op_name = cv::format("avg_%s", op_name_base.c_str());
auto op = std::make_shared<ge::op::AvgPoolV2>(op_name);
// set attributes
op->set_attr_ksize(ge::Operator::OpListInt(
{1, 1, (int64_t)kernel_size[0], (int64_t)kernel_size[1]}
));
op->set_attr_strides(ge::Operator::OpListInt(
{1, 1, (int64_t)strides[0], (int64_t)strides[1]}
));
std::string cann_pad_mode{"CALCULATED"};
if (padMode == "SAME" || padMode == "VALID")
cann_pad_mode = padMode;
op->set_attr_padding_mode(cann_pad_mode.c_str());
op->set_attr_pads(ge::Operator::OpListInt(
{(int64_t)pads_begin[0], (int64_t)pads_end[0], (int64_t)pads_begin[1], (int64_t)pads_end[1]}
));
op->set_attr_global_pooling(globalPooling);
op->set_attr_ceil_mode(ceilMode);
auto cann_exclusive = !avePoolPaddedArea;
op->set_attr_exclusive(cann_exclusive);
// set inputs
op->set_input_x_by_name(*op_x, "y");
op->update_input_desc_x(*x_desc);
// set outputs
op->update_output_desc_y(*output_desc);
return Ptr<BackendNode>(new CannBackendNode(op));
}
else
CV_Error(Error::StsNotImplemented, "Unsupported pooling type");
}
#endif
#ifdef HAVE_DNN_NGRAPH
virtual Ptr<BackendNode> initNgraph(const std::vector<Ptr<BackendWrapper> >& inputs,