static MatShape getBufferShape(const MatShape& shape) { if (shape.size() == 2 || shape.size() == 4) { int w, h, c, n; getCanonicalSize(shape, &w, &h, &c, &n); return {w, h, c, n}; } else { MatShape bufferShape(shape); std::reverse(bufferShape.begin(), bufferShape.end()); return bufferShape; } }
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &inputs) { #ifdef HAVE_HALIDE int inW, inH, inC, inN; int minN = std::max(dstRanges[0].start, 0); int minC = std::max(dstRanges[1].start, 0); int minY = std::max(dstRanges[2].start, 0); int minX = std::max(dstRanges[3].start, 0); Halide::Buffer<float> inputBuffer = halideBuffer(inputs[0]); getCanonicalSize(inputBuffer, &inW, &inH, &inC, &inN); Halide::Var x("x"), y("y"), c("c"), n("n"); Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name)); Halide::Func padded = Halide::BoundaryConditions::constant_exterior(inputBuffer, paddingValue); top(x, y, c, n) = padded(x - minX, y - minY, c - minC, n - minN); return Ptr<BackendNode>(new HalideBackendNode(top)); #endif // HAVE_HALIDE return Ptr<BackendNode>(); }
HalideBackendWrapper::HalideBackendWrapper(const Ptr<BackendWrapper>& base, const MatShape& shape) : BackendWrapper(DNN_BACKEND_HALIDE, base->targetId) { int w, h, c, n; getCanonicalSize(shape, &w, &h, &c, &n); Halide::Buffer<float> baseBuffer = halideBuffer(base); buffer = Halide::Buffer<float>((float*)baseBuffer.raw_buffer()->host, {w, h, c, n}); if (baseBuffer.has_device_allocation()) { buffer.raw_buffer()->device = baseBuffer.raw_buffer()->device; buffer.raw_buffer()->device_interface = baseBuffer.raw_buffer()->device_interface; buffer.set_device_dirty(); } else { buffer.set_host_dirty(); // Indicate that data is on CPU. CV_Assert(targetId == DNN_TARGET_CPU); } }
void compileHalide(const std::vector<Mat> &outputs, Ptr<BackendNode>& node, int targetId) { #ifdef HAVE_HALIDE CV_Assert(!node.empty()); Halide::Func& top = node.dynamicCast<HalideBackendNode>()->funcs.back(); int outW, outH, outC, outN; Halide::Var x("x"), y("y"), c("c"), n("n"); getCanonicalSize(outputs[0].size, &outW, &outH, &outC, &outN); top.bound(x, 0, outW).bound(y, 0, outH) .bound(c, 0, outC).bound(n, 0, outN); Halide::Target target = Halide::get_host_target(); target.set_feature(Halide::Target::NoAsserts); if (targetId == DNN_TARGET_OPENCL) { target.set_feature(Halide::Target::OpenCL); } CV_Assert(target.supported()); top.compile_jit(target); #endif // HAVE_HALIDE }
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &inputs) { #ifdef HAVE_HALIDE Halide::Buffer<float> inputBuffer = halideBuffer(inputs[0]); int inW, inH, inC, inN; getCanonicalSize(inputBuffer, &inW, &inH, &inC, &inN); if (inW != 1 || inH != 1) CV_Error(cv::Error::StsNotImplemented, "Halide backend for SoftMax with spatial size " "more than 1x1 is not implemented"); Halide::Var x("x"), y("y"), c("c"), n("n"); Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name)); Halide::Func expInput("expInput"); Halide::RDom r(0, inW, 0, inH, 0, inC); expInput(x, y, c, n) = exp(inputBuffer(x, y, c, n)); Halide::Expr globalSum = sum(expInput(r.x, r.y, r.z, n)); top(x, y, c, n) = expInput(x, y, c, n) / globalSum; return Ptr<BackendNode>(new HalideBackendNode(top)); #endif // HAVE_HALIDE return Ptr<BackendNode>(); }
void getCanonicalSize(const MatSize& size, int* w, int* h, int* c, int* n) { getCanonicalSize(MatShape(size.p, size.p + size[-1]), w, h, c, n); }
Halide::Buffer<float> wrapToHalideBuffer(const Mat& mat) { int n, c, w, h; getCanonicalSize(mat.size, &w, &h, &c, &n); return wrapToHalideBuffer(mat, {w, h, c, n}); }