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

@@ -8,6 +8,7 @@
#include "layers_common.hpp"
#include "../op_cuda.hpp"
#include "../op_inf_engine.hpp"
#include "../op_cann.hpp"
#include <opencv2/imgproc.hpp>
#ifdef HAVE_DNN_NGRAPH
@@ -77,6 +78,9 @@ public:
if (backendId == DNN_BACKEND_CUDA)
return interpolation == "nearest" || interpolation == "bilinear" || interpolation == "opencv_linear";
if (backendId == DNN_BACKEND_CANN)
return interpolation == "nearest" || interpolation == "bilinear" || interpolation == "opencv_linear";
#ifdef HAVE_INF_ENGINE
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
{
@@ -307,6 +311,67 @@ public:
CV_Error(Error::StsNotImplemented, "Unknown interpolation: " + interpolation);
}
#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 x_desc = x->getTensorDesc();
auto op_x = nodes[0].dynamicCast<CannBackendNode>()->getOp();
auto output_y_desc = std::make_shared<ge::TensorDesc>(ge::Shape(), ge::FORMAT_NCHW, ge::DT_FLOAT);
// create operator
std::string op_name = cv::format("resize_%d", index);
if (interpolation == "nearest")
{
auto op = std::make_shared<ge::op::ResizeNearestNeighborV2>(op_name);
// set attributes
op->set_attr_align_corners(alignCorners);
op->set_attr_half_pixel_centers(halfPixelCenters);
// set inputs : x
op->set_input_x_by_name(*op_x, "y");
op->update_input_desc_x(*x_desc);
// set inputs : size
std::vector<int> shape_of_size_mat{2};
Mat size_mat(2, 1, CV_32S, Scalar(outHeight, outWidth));
auto op_const_size = std::make_shared<CannConstOp>(size_mat.data, size_mat.type(), shape_of_size_mat, cv::format("%s_size", op_name.c_str()));
op->set_input_size(*(op_const_size->getOp()));
op->update_input_desc_size(*(op_const_size->getTensorDesc()));
// set outputs
op->update_output_desc_y(*output_y_desc);
return Ptr<BackendNode>(new CannBackendNode(op));
}
else if (interpolation == "opencv_linear" || interpolation == "bilinear")
{
auto op = std::make_shared<ge::op::ResizeBilinearV2>(op_name);
// set attributes
op->set_attr_align_corners(alignCorners);
op->set_attr_half_pixel_centers(halfPixelCenters);
// set inputs : x
op->set_input_x_by_name(*op_x, "y");
op->update_input_desc_x(*x_desc);
// set inputs : size
std::vector<int> shape_of_size_mat{2};
Mat size_mat(2, 1, CV_32S, Scalar(outHeight, outWidth));
auto op_const_size = std::make_shared<CannConstOp>(size_mat.data, size_mat.type(), shape_of_size_mat, cv::format("%s_size", op_name.c_str()));
op->set_input_size(*(op_const_size->getOp()));
op->update_input_desc_size(*(op_const_size->getTensorDesc()));
// set outputs
op->update_output_desc_y(*output_y_desc);
return Ptr<BackendNode>(new CannBackendNode(op));
}
else
CV_Error(Error::StsNotImplemented, "Unsupported interpolation by CANN backend: " + interpolation);
}
#endif // HAVE_CANN
#ifdef HAVE_DNN_NGRAPH
virtual Ptr<BackendNode> initNgraph(const std::vector<Ptr<BackendWrapper> >& inputs,