mirror of
https://github.com/opencv/opencv.git
synced 2026-07-27 22:33:03 +04:00
Merge pull request #24231 from fengyuentau:halide_cleanup_5.x
dnn: cleanup of halide backend for 5.x #24231 Merge with https://github.com/opencv/opencv_extra/pull/1092. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -43,7 +43,6 @@
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include "../op_cuda.hpp"
|
||||
#include "../op_halide.hpp"
|
||||
#include "../op_inf_engine.hpp"
|
||||
#include "../ie_ngraph.hpp"
|
||||
#include "../op_vkcom.hpp"
|
||||
@@ -199,46 +198,6 @@ public:
|
||||
}
|
||||
|
||||
virtual void fuseWeights(const Mat& w_, const Mat& b_) = 0;
|
||||
|
||||
virtual void applyHalideScheduler(Ptr<BackendNode>& node,
|
||||
const std::vector<Mat*> &inputs,
|
||||
const std::vector<Mat> &outputs,
|
||||
int targetId) const CV_OVERRIDE
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
if (targetId != DNN_TARGET_CPU)
|
||||
{
|
||||
Layer::applyHalideScheduler(node, inputs, outputs, targetId);
|
||||
return;
|
||||
}
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n"), tile("tile"), yi("yi"), yo("yo"), co("co"), ci("ci");
|
||||
Halide::Func& top = node.dynamicCast<HalideBackendNode>()->funcs[1];
|
||||
Halide::Func& padded_input = node.dynamicCast<HalideBackendNode>()->funcs[0];
|
||||
|
||||
int outW, outH, outC, outN;
|
||||
getCanonicalSize(outputs[0].size, &outW, &outH, &outC, &outN);
|
||||
|
||||
if (outW == 1 || outH <= 2)
|
||||
return;
|
||||
|
||||
if (is1x1() || outC <= 16)
|
||||
top.reorder(x, c, y)
|
||||
.split(y, yo, yi, 2)
|
||||
.fuse(yo, n, tile)
|
||||
.parallel(tile)
|
||||
.unroll(yi)
|
||||
.vectorize(x, outW >= 16 ? 16 : outW);
|
||||
else
|
||||
top.reorder(x, c, y)
|
||||
.split(y, yo, yi, 2)
|
||||
.split(c, co, ci, 16)
|
||||
.fuse(yo, co, tile).fuse(n, tile, tile)
|
||||
.parallel(tile)
|
||||
.unroll(yi)
|
||||
.vectorize(x, outW >= 16 ? 16 : outW);
|
||||
padded_input.compute_at(top, yi);
|
||||
#endif // HAVE_HALIDE
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -329,10 +288,6 @@ public:
|
||||
#endif
|
||||
if (backendId == DNN_BACKEND_OPENCV)
|
||||
return ksize >= 1 && ksize <= 3;
|
||||
#ifdef HAVE_HALIDE
|
||||
if (backendId == DNN_BACKEND_HALIDE)
|
||||
return ksize == 2 && !blobs.empty();
|
||||
#endif
|
||||
#ifdef HAVE_VULKAN
|
||||
if (backendId == DNN_BACKEND_VKCOM)
|
||||
return ksize == 2;
|
||||
@@ -684,55 +639,6 @@ public:
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &inputs) CV_OVERRIDE
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
CV_Assert(!blobs.empty());
|
||||
Halide::Buffer<float> inputBuffer = halideBuffer(inputs[0]);
|
||||
|
||||
const int inpCn = inputBuffer.channels();
|
||||
const int outCn = blobs[0].size[0];
|
||||
const int inpGroupCn = blobs[0].size[1];
|
||||
const int group = inpCn / inpGroupCn;
|
||||
const int outGroupCn = outCn / group;
|
||||
|
||||
Halide::Buffer<float> weights = wrapToHalideBuffer(blobs[0]);
|
||||
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
|
||||
Halide::Func padded_input(name + "_constant_exterior");
|
||||
if (pad.width || pad.height)
|
||||
{
|
||||
Halide::Func bounded =
|
||||
Halide::BoundaryConditions::constant_exterior(inputBuffer, 0);
|
||||
padded_input(x, y, c, n) = bounded(x, y, c, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
padded_input(x, y, c, n) = inputBuffer(x, y, c, n);
|
||||
}
|
||||
|
||||
Halide::RDom r(0, kernel.width, 0, kernel.height, 0, inpGroupCn);
|
||||
Halide::Expr kx = x * stride.width - pad.width + r.x * dilation.width;
|
||||
Halide::Expr ky = y * stride.height - pad.height + r.y * dilation.height;
|
||||
Halide::Expr kc = r.z;
|
||||
for (int i = 1; i < group; ++i)
|
||||
{
|
||||
kc = select(c < outGroupCn * i, kc, inpGroupCn * i + r.z);
|
||||
}
|
||||
Halide::Expr topExpr = sum(padded_input(kx, ky, kc, n) *
|
||||
weights(r.x, r.y, r.z, c));
|
||||
if (hasBias())
|
||||
{
|
||||
Halide::Buffer<float> bias = wrapToHalideBuffer(blobs[1], {outCn});
|
||||
topExpr += bias(c);
|
||||
}
|
||||
top(x, y, c, n) = topExpr;
|
||||
return Ptr<BackendNode>(new HalideBackendNode({ padded_input, top }));
|
||||
#endif // HAVE_HALIDE
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
|
||||
#ifdef HAVE_CANN
|
||||
virtual Ptr<BackendNode> initCann(const std::vector<Ptr<BackendWrapper> > &inputs,
|
||||
const std::vector<Ptr<BackendWrapper> > &outputs,
|
||||
@@ -1506,7 +1412,7 @@ public:
|
||||
#endif // HAVE_INF_ENGINE
|
||||
{
|
||||
return backendId == DNN_BACKEND_CUDA ||
|
||||
(kernel_size.size() == 2 && (backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE)) ||
|
||||
(kernel_size.size() == 2 && backendId == DNN_BACKEND_OPENCV) ||
|
||||
(kernel_size.size() == 2 && backendId == DNN_BACKEND_CANN);
|
||||
}
|
||||
}
|
||||
@@ -2114,60 +2020,6 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &inputs) CV_OVERRIDE
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
CV_Assert(!blobs.empty());
|
||||
Halide::Buffer<float> inputBuffer = halideBuffer(inputs[0]);
|
||||
|
||||
int inW, inH, inC, inN;
|
||||
getCanonicalSize(inputBuffer, &inW, &inH, &inC, &inN);
|
||||
const int outGroupCn = blobs[0].size[1];
|
||||
const int group = numOutput / outGroupCn;
|
||||
const int inpGroupCn = blobs[0].size[0] / group;
|
||||
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
|
||||
Halide::Func padded_input(name + "_constant_exterior");
|
||||
auto weights = wrapToHalideBuffer(blobs[0]);
|
||||
|
||||
Halide::Func dilated_input("dilated_input");
|
||||
dilated_input(x, y, c, n) = 0.0f;
|
||||
Halide::RDom r1(0, inW, 0, inH);
|
||||
dilated_input(r1.x * stride.width, r1.y * stride.height, c, n) =
|
||||
inputBuffer(r1.x, r1.y, c, n);
|
||||
dilated_input.compute_root();
|
||||
|
||||
Halide::Func bounded =
|
||||
Halide::BoundaryConditions::constant_exterior(dilated_input, 0,
|
||||
0, (inW - 1) * stride.width + 1,
|
||||
0, (inH - 1) * stride.height + 1,
|
||||
0, inC, 0, inN);
|
||||
padded_input(x, y, c, n) = bounded(x, y, c, n);
|
||||
|
||||
Halide::RDom r(0, kernel.width, 0, kernel.height, 0, inpGroupCn);
|
||||
Halide::Expr kx = x + pad.width - r.x;
|
||||
Halide::Expr ky = y + pad.height - r.y;
|
||||
Halide::Expr kInC = r.z;
|
||||
Halide::Expr kOutC = c;
|
||||
for (int i = 1; i < group; ++i)
|
||||
{
|
||||
kInC = select(c < outGroupCn * i, kInC, inpGroupCn * i + r.z);
|
||||
kOutC = select(c < outGroupCn * i, kOutC, c - outGroupCn * i);
|
||||
}
|
||||
Halide::Expr topExpr = sum(padded_input(kx, ky, kInC, n) *
|
||||
weights(r.x, r.y, kOutC, kInC));
|
||||
if (hasBias())
|
||||
{
|
||||
auto bias = wrapToHalideBuffer(blobs[1], {numOutput});
|
||||
topExpr += bias(c);
|
||||
}
|
||||
top(x, y, c, n) = topExpr;
|
||||
return Ptr<BackendNode>(new HalideBackendNode({ padded_input, top }));
|
||||
#endif // HAVE_HALIDE
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
|
||||
#ifdef HAVE_CANN
|
||||
virtual Ptr<BackendNode> initCann(const std::vector<Ptr<BackendWrapper> > &inputs,
|
||||
const std::vector<Ptr<BackendWrapper> > &outputs,
|
||||
|
||||
Reference in New Issue
Block a user