|
|
@ -199,125 +199,6 @@ struct LayerPin |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// Objects of this class manages wrappers. For every CPU memory pointer and shape
|
|
|
|
|
|
|
|
// one and only wrapper. Now it support wrapping for single backend and target.
|
|
|
|
|
|
|
|
class BackendWrapManager |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
Ptr<BackendWrapper> wrap(const Mat& m, int backendId, int targetId) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CV_TRACE_FUNCTION(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CV_Assert(backendId != DNN_BACKEND_DEFAULT); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::map<void*, Ptr<BackendWrapper> >::iterator hostsIt; |
|
|
|
|
|
|
|
// Check that the same CPU memory was previously wrapped.
|
|
|
|
|
|
|
|
hostsIt = hostWrappers.find(m.data); |
|
|
|
|
|
|
|
if (hostsIt == hostWrappers.end()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// If not wrapped before.
|
|
|
|
|
|
|
|
return (hostWrappers[m.data] = wrapHost(m, backendId, targetId)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Find if wrapper of this host and shape was created before.
|
|
|
|
|
|
|
|
std::map<std::pair<void*, MatSize>, Ptr<BackendWrapper> >::iterator it; |
|
|
|
|
|
|
|
std::pair<void*, MatSize> key(m.data, m.size); |
|
|
|
|
|
|
|
it = extraWrappers.find(key); |
|
|
|
|
|
|
|
if (it == extraWrappers.end()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
MatShape shape(m.dims); |
|
|
|
|
|
|
|
for (int i = 0; i < m.dims; ++i) |
|
|
|
|
|
|
|
shape[i] = m.size.p[i]; |
|
|
|
|
|
|
|
return (extraWrappers[key] = wrapUser(hostsIt->second, shape)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
return it->second; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<Ptr<BackendWrapper> > wrap(const std::vector<Mat*>& mats, |
|
|
|
|
|
|
|
int backendId, int targetId) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const int num = mats.size(); |
|
|
|
|
|
|
|
std::vector<Ptr<BackendWrapper> > dst(num); |
|
|
|
|
|
|
|
for (int i = 0; i < num; ++i) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
dst[i] = wrap(*mats[i], backendId, targetId); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return dst; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<Ptr<BackendWrapper> > wrap(const std::vector<Mat>& mats, |
|
|
|
|
|
|
|
int backendId, int targetId) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const int num = mats.size(); |
|
|
|
|
|
|
|
std::vector<Ptr<BackendWrapper> > dst(num); |
|
|
|
|
|
|
|
for (int i = 0; i < num; ++i) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
dst[i] = wrap(mats[i], backendId, targetId); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return dst; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void reset() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CV_TRACE_FUNCTION(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hostWrappers.clear(); |
|
|
|
|
|
|
|
extraWrappers.clear(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
|
|
|
// Backend-specific wrapping function.
|
|
|
|
|
|
|
|
Ptr<BackendWrapper> wrapHost(const Mat& m, int backendId, int targetId) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (backendId == DNN_BACKEND_DEFAULT) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return Ptr<BackendWrapper>(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (backendId == DNN_BACKEND_HALIDE) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CV_Assert(haveHalide()); |
|
|
|
|
|
|
|
#ifdef HAVE_HALIDE |
|
|
|
|
|
|
|
return Ptr<BackendWrapper>(new HalideBackendWrapper(targetId, m)); |
|
|
|
|
|
|
|
#endif // HAVE_HALIDE
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CV_Error(Error::StsNotImplemented, "Unknown backend identifier"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return Ptr<BackendWrapper>(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Backend-specific wrapping function.
|
|
|
|
|
|
|
|
Ptr<BackendWrapper> wrapUser(const Ptr<BackendWrapper>& host, const MatShape& shape) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int backendId = host->backendId; |
|
|
|
|
|
|
|
if (backendId == DNN_BACKEND_DEFAULT) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return Ptr<BackendWrapper>(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (backendId == DNN_BACKEND_HALIDE) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CV_Assert(haveHalide()); |
|
|
|
|
|
|
|
#ifdef HAVE_HALIDE |
|
|
|
|
|
|
|
return Ptr<BackendWrapper>(new HalideBackendWrapper(host, shape)); |
|
|
|
|
|
|
|
#endif // HAVE_HALIDE
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CV_Error(Error::StsNotImplemented, "Unknown backend identifier"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return Ptr<BackendWrapper>(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Wrappers that initialized for memory hosts (first wrapping of CPU data).
|
|
|
|
|
|
|
|
std::map<void*, Ptr<BackendWrapper> > hostWrappers; |
|
|
|
|
|
|
|
// The rest of wrappers. They initialized for non-host cv::Mat.
|
|
|
|
|
|
|
|
std::map<std::pair<void*, MatSize>, Ptr<BackendWrapper> > extraWrappers; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct LayerData |
|
|
|
struct LayerData |
|
|
|
{ |
|
|
|
{ |
|
|
|
LayerData() : id(-1), flag(0) {} |
|
|
|
LayerData() : id(-1), flag(0) {} |
|
|
@ -340,6 +221,8 @@ struct LayerData |
|
|
|
std::set<int> inputLayersId; |
|
|
|
std::set<int> inputLayersId; |
|
|
|
std::set<int> requiredOutputs; |
|
|
|
std::set<int> requiredOutputs; |
|
|
|
std::vector<LayerPin> consumers; |
|
|
|
std::vector<LayerPin> consumers; |
|
|
|
|
|
|
|
std::vector<Ptr<BackendWrapper> > outputBlobsWrappers; |
|
|
|
|
|
|
|
std::vector<Ptr<BackendWrapper> > inputBlobsWrappers; |
|
|
|
|
|
|
|
|
|
|
|
Ptr<Layer> layerInstance; |
|
|
|
Ptr<Layer> layerInstance; |
|
|
|
std::vector<Mat> outputBlobs; |
|
|
|
std::vector<Mat> outputBlobs; |
|
|
@ -618,6 +501,24 @@ private: |
|
|
|
std::map<LayerPin, Mat> memHosts; |
|
|
|
std::map<LayerPin, Mat> memHosts; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static Ptr<BackendWrapper> wrapMat(int backendId, int targetId, const cv::Mat& m) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (backendId == DNN_BACKEND_DEFAULT) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return Ptr<BackendWrapper>(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (backendId == DNN_BACKEND_HALIDE) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CV_Assert(haveHalide()); |
|
|
|
|
|
|
|
#ifdef HAVE_HALIDE |
|
|
|
|
|
|
|
return Ptr<BackendWrapper>(new HalideBackendWrapper(targetId, m)); |
|
|
|
|
|
|
|
#endif // HAVE_HALIDE
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
CV_Error(Error::StsNotImplemented, "Unknown backend identifier"); |
|
|
|
|
|
|
|
return Ptr<BackendWrapper>(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct Net::Impl |
|
|
|
struct Net::Impl |
|
|
|
{ |
|
|
|
{ |
|
|
|
typedef std::map<int, LayerShapes> LayersShapesMap; |
|
|
|
typedef std::map<int, LayerShapes> LayersShapesMap; |
|
|
@ -650,8 +551,8 @@ struct Net::Impl |
|
|
|
int preferableBackend; |
|
|
|
int preferableBackend; |
|
|
|
int preferableTarget; |
|
|
|
int preferableTarget; |
|
|
|
String halideConfigFile; |
|
|
|
String halideConfigFile; |
|
|
|
// Backend-specific wrapping manager.
|
|
|
|
// Map host data to backend specific wrapper.
|
|
|
|
BackendWrapManager backendWrapper; |
|
|
|
std::map<void*, Ptr<BackendWrapper> > backendWrappers; |
|
|
|
|
|
|
|
|
|
|
|
int lastLayerId; |
|
|
|
int lastLayerId; |
|
|
|
|
|
|
|
|
|
|
@ -659,6 +560,62 @@ struct Net::Impl |
|
|
|
bool fusion; |
|
|
|
bool fusion; |
|
|
|
std::vector<int64> layersTimings; |
|
|
|
std::vector<int64> layersTimings; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ptr<BackendWrapper> wrap(const Mat& host) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (preferableBackend == DNN_BACKEND_DEFAULT) |
|
|
|
|
|
|
|
return Ptr<BackendWrapper>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MatShape shape(host.dims); |
|
|
|
|
|
|
|
for (int i = 0; i < host.dims; ++i) |
|
|
|
|
|
|
|
shape[i] = host.size[i]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void* data = host.data; |
|
|
|
|
|
|
|
if (backendWrappers.find(data) != backendWrappers.end()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Ptr<BackendWrapper> baseBuffer = backendWrappers[data]; |
|
|
|
|
|
|
|
if (preferableBackend == DNN_BACKEND_HALIDE) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CV_Assert(haveHalide()); |
|
|
|
|
|
|
|
#ifdef HAVE_HALIDE |
|
|
|
|
|
|
|
return Ptr<BackendWrapper>(new HalideBackendWrapper(baseBuffer, shape)); |
|
|
|
|
|
|
|
#endif // HAVE_HALIDE
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
CV_Error(Error::StsNotImplemented, "Unknown backend identifier"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ptr<BackendWrapper> wrapper = wrapMat(preferableBackend, preferableTarget, host); |
|
|
|
|
|
|
|
backendWrappers[data] = wrapper; |
|
|
|
|
|
|
|
return wrapper; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class HalideCompiler : public ParallelLoopBody |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
HalideCompiler(const MapIdToLayerData& layers_, int preferableTarget_) |
|
|
|
|
|
|
|
: layers(&layers_), preferableTarget(preferableTarget_) {} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void operator()(const Range& r) const |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
MapIdToLayerData::const_iterator it = layers->begin(); |
|
|
|
|
|
|
|
for (int i = 0; i < r.start && it != layers->end(); ++i, ++it) {} |
|
|
|
|
|
|
|
for (int i = r.start; i < r.end && it != layers->end(); ++i, ++it) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const LayerData &ld = it->second; |
|
|
|
|
|
|
|
Ptr<Layer> layer = ld.layerInstance; |
|
|
|
|
|
|
|
bool skip = ld.skipFlags.find(DNN_BACKEND_HALIDE)->second; |
|
|
|
|
|
|
|
if (layer->supportBackend(DNN_BACKEND_HALIDE) && !skip) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Ptr<BackendNode> node = ld.backendNodes.find(DNN_BACKEND_HALIDE)->second; |
|
|
|
|
|
|
|
dnn::compileHalide(ld.outputBlobs, node, preferableTarget); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
private: |
|
|
|
|
|
|
|
const MapIdToLayerData* layers; |
|
|
|
|
|
|
|
int preferableTarget; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
void compileHalide() |
|
|
|
void compileHalide() |
|
|
|
{ |
|
|
|
{ |
|
|
|
CV_TRACE_FUNCTION(); |
|
|
|
CV_TRACE_FUNCTION(); |
|
|
@ -682,10 +639,9 @@ struct Net::Impl |
|
|
|
ld.inputBlobs, ld.outputBlobs, |
|
|
|
ld.inputBlobs, ld.outputBlobs, |
|
|
|
preferableTarget); |
|
|
|
preferableTarget); |
|
|
|
} |
|
|
|
} |
|
|
|
dnn::compileHalide(ld.outputBlobs, ld.backendNodes[DNN_BACKEND_HALIDE], |
|
|
|
|
|
|
|
preferableTarget); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
parallel_for_(Range(0, layers.size()), HalideCompiler(layers, preferableTarget)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void clear() |
|
|
|
void clear() |
|
|
@ -917,7 +873,6 @@ struct Net::Impl |
|
|
|
{ |
|
|
|
{ |
|
|
|
CV_TRACE_FUNCTION(); |
|
|
|
CV_TRACE_FUNCTION(); |
|
|
|
|
|
|
|
|
|
|
|
backendWrapper.reset(); |
|
|
|
|
|
|
|
if (preferableBackend == DNN_BACKEND_DEFAULT) |
|
|
|
if (preferableBackend == DNN_BACKEND_DEFAULT) |
|
|
|
{ |
|
|
|
{ |
|
|
|
CV_Assert(preferableTarget == DNN_TARGET_CPU); |
|
|
|
CV_Assert(preferableTarget == DNN_TARGET_CPU); |
|
|
@ -967,12 +922,10 @@ struct Net::Impl |
|
|
|
} |
|
|
|
} |
|
|
|
// No layers fusion.
|
|
|
|
// No layers fusion.
|
|
|
|
ldTop.skipFlags[preferableBackend] = false; |
|
|
|
ldTop.skipFlags[preferableBackend] = false; |
|
|
|
std::vector<Ptr<BackendWrapper> > inputs = |
|
|
|
|
|
|
|
backendWrapper.wrap(ldTop.inputBlobs, preferableBackend, |
|
|
|
|
|
|
|
preferableTarget); |
|
|
|
|
|
|
|
if (preferableBackend == DNN_BACKEND_HALIDE) |
|
|
|
if (preferableBackend == DNN_BACKEND_HALIDE) |
|
|
|
{ |
|
|
|
{ |
|
|
|
ldTop.backendNodes[DNN_BACKEND_HALIDE] = layerTop->initHalide(inputs); |
|
|
|
ldTop.backendNodes[DNN_BACKEND_HALIDE] = |
|
|
|
|
|
|
|
layerTop->initHalide(ldTop.inputBlobsWrappers); |
|
|
|
baseIt = it; |
|
|
|
baseIt = it; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
@ -1021,12 +974,14 @@ struct Net::Impl |
|
|
|
|
|
|
|
|
|
|
|
//bind inputs
|
|
|
|
//bind inputs
|
|
|
|
ld.inputBlobs.resize(ninputs); |
|
|
|
ld.inputBlobs.resize(ninputs); |
|
|
|
|
|
|
|
ld.inputBlobsWrappers.resize(ninputs); |
|
|
|
for (size_t i = 0; i < ninputs; i++) |
|
|
|
for (size_t i = 0; i < ninputs; i++) |
|
|
|
{ |
|
|
|
{ |
|
|
|
LayerPin from = ld.inputBlobsId[i]; |
|
|
|
LayerPin from = ld.inputBlobsId[i]; |
|
|
|
CV_Assert(from.valid()); |
|
|
|
CV_Assert(from.valid()); |
|
|
|
CV_DbgAssert(layers.count(from.lid) && (int)layers[from.lid].outputBlobs.size() > from.oid); |
|
|
|
CV_DbgAssert(layers.count(from.lid) && (int)layers[from.lid].outputBlobs.size() > from.oid); |
|
|
|
ld.inputBlobs[i] = &layers[from.lid].outputBlobs[from.oid]; |
|
|
|
ld.inputBlobs[i] = &layers[from.lid].outputBlobs[from.oid]; |
|
|
|
|
|
|
|
ld.inputBlobsWrappers[i] = layers[from.lid].outputBlobsWrappers[from.oid]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
LayersShapesMap::const_iterator layerShapesIt = layersShapes.find(lid); |
|
|
|
LayersShapesMap::const_iterator layerShapesIt = layersShapes.find(lid); |
|
|
@ -1036,6 +991,11 @@ struct Net::Impl |
|
|
|
std::vector<LayerPin> pinsForInternalBlobs; |
|
|
|
std::vector<LayerPin> pinsForInternalBlobs; |
|
|
|
bool maximizeReuse = preferableBackend == DNN_BACKEND_HALIDE; |
|
|
|
bool maximizeReuse = preferableBackend == DNN_BACKEND_HALIDE; |
|
|
|
blobManager.allocateBlobsForLayer(ld, layerShapesIt->second, pinsForInternalBlobs, maximizeReuse); |
|
|
|
blobManager.allocateBlobsForLayer(ld, layerShapesIt->second, pinsForInternalBlobs, maximizeReuse); |
|
|
|
|
|
|
|
ld.outputBlobsWrappers.resize(ld.outputBlobs.size()); |
|
|
|
|
|
|
|
for (int i = 0; i < ld.outputBlobs.size(); ++i) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
ld.outputBlobsWrappers[i] = wrap(ld.outputBlobs[i]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Ptr<Layer> layerPtr = ld.getLayerInstance(); |
|
|
|
Ptr<Layer> layerPtr = ld.getLayerInstance(); |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1256,6 +1216,8 @@ struct Net::Impl |
|
|
|
getLayersShapes(inputShapes, layersShapes); |
|
|
|
getLayersShapes(inputShapes, layersShapes); |
|
|
|
|
|
|
|
|
|
|
|
blobManager.reset(); |
|
|
|
blobManager.reset(); |
|
|
|
|
|
|
|
backendWrappers.clear(); |
|
|
|
|
|
|
|
blobManager.addReference(LayerPin(0, 0)); |
|
|
|
for (it = layers.begin(); it != layers.end(); ++it) |
|
|
|
for (it = layers.begin(); it != layers.end(); ++it) |
|
|
|
{ |
|
|
|
{ |
|
|
|
const LayerData& ld = it->second; |
|
|
|
const LayerData& ld = it->second; |
|
|
@ -1291,18 +1253,28 @@ struct Net::Impl |
|
|
|
!layer->supportBackend(preferableBackend)) |
|
|
|
!layer->supportBackend(preferableBackend)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if( !ld.skipFlags[DNN_BACKEND_DEFAULT] ) |
|
|
|
if( !ld.skipFlags[DNN_BACKEND_DEFAULT] ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for (int i = 0, n = ld.inputBlobsWrappers.size(); i < n; ++i) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (!ld.inputBlobsWrappers[i].empty()) |
|
|
|
|
|
|
|
ld.inputBlobsWrappers[i]->copyToHost(); |
|
|
|
|
|
|
|
} |
|
|
|
layer->forward(ld.inputBlobs, ld.outputBlobs, ld.internals); |
|
|
|
layer->forward(ld.inputBlobs, ld.outputBlobs, ld.internals); |
|
|
|
|
|
|
|
for (int i = 0, n = ld.outputBlobsWrappers.size(); i < n; ++i) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (!ld.outputBlobsWrappers[i].empty()) |
|
|
|
|
|
|
|
ld.outputBlobsWrappers[i]->setHostDirty(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
tm.reset(); |
|
|
|
tm.reset(); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (!ld.skipFlags[preferableBackend]) |
|
|
|
else if (!ld.skipFlags[preferableBackend]) |
|
|
|
{ |
|
|
|
{ |
|
|
|
std::vector<Ptr<BackendWrapper> > outputs = |
|
|
|
|
|
|
|
backendWrapper.wrap(ld.outputBlobs, preferableBackend, preferableTarget); |
|
|
|
|
|
|
|
Ptr<BackendNode> node = ld.backendNodes[preferableBackend]; |
|
|
|
Ptr<BackendNode> node = ld.backendNodes[preferableBackend]; |
|
|
|
if (preferableBackend == DNN_BACKEND_HALIDE) |
|
|
|
if (preferableBackend == DNN_BACKEND_HALIDE) |
|
|
|
{ |
|
|
|
{ |
|
|
|
forwardHalide(outputs, node); |
|
|
|
forwardHalide(ld.outputBlobsWrappers, node); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1423,11 +1395,10 @@ struct Net::Impl |
|
|
|
CV_Error(Error::StsOutOfRange, "Layer \"" + ld.name + "\" produce only " + toString(ld.outputBlobs.size()) + |
|
|
|
CV_Error(Error::StsOutOfRange, "Layer \"" + ld.name + "\" produce only " + toString(ld.outputBlobs.size()) + |
|
|
|
" outputs, the #" + toString(pin.oid) + " was requsted"); |
|
|
|
" outputs, the #" + toString(pin.oid) + " was requsted"); |
|
|
|
} |
|
|
|
} |
|
|
|
if (preferableBackend != DNN_BACKEND_DEFAULT) |
|
|
|
if (preferableBackend != DNN_TARGET_CPU) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Transfer data to CPU if it's require.
|
|
|
|
// Transfer data to CPU if it's require.
|
|
|
|
backendWrapper.wrap(ld.outputBlobs[pin.oid], preferableBackend, |
|
|
|
ld.outputBlobsWrappers[pin.oid]->copyToHost(); |
|
|
|
preferableTarget)->copyToHost(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1635,6 +1606,7 @@ void Net::setInput(const Mat &blob_, const String& name) |
|
|
|
|
|
|
|
|
|
|
|
LayerData &ld = impl->layers[pin.lid]; |
|
|
|
LayerData &ld = impl->layers[pin.lid]; |
|
|
|
ld.outputBlobs.resize( std::max(pin.oid+1, (int)ld.requiredOutputs.size()) ); |
|
|
|
ld.outputBlobs.resize( std::max(pin.oid+1, (int)ld.requiredOutputs.size()) ); |
|
|
|
|
|
|
|
ld.outputBlobsWrappers.resize(ld.outputBlobs.size()); |
|
|
|
MatShape prevShape = shape(ld.outputBlobs[pin.oid]); |
|
|
|
MatShape prevShape = shape(ld.outputBlobs[pin.oid]); |
|
|
|
bool oldShape = prevShape == shape(blob_); |
|
|
|
bool oldShape = prevShape == shape(blob_); |
|
|
|
if (oldShape) |
|
|
|
if (oldShape) |
|
|
@ -1642,6 +1614,10 @@ void Net::setInput(const Mat &blob_, const String& name) |
|
|
|
else |
|
|
|
else |
|
|
|
ld.outputBlobs[pin.oid] = blob_.clone(); |
|
|
|
ld.outputBlobs[pin.oid] = blob_.clone(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!ld.outputBlobsWrappers[pin.oid].empty()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
ld.outputBlobsWrappers[pin.oid]->setHostDirty(); |
|
|
|
|
|
|
|
} |
|
|
|
impl->netWasAllocated = impl->netWasAllocated && oldShape; |
|
|
|
impl->netWasAllocated = impl->netWasAllocated && oldShape; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|