1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 15:53:03 +04:00

fusion fix

This commit is contained in:
Abhishek Gola
2026-07-06 13:36:53 +05:30
parent 2089d7fdb1
commit 0843a0bb17
3 changed files with 67 additions and 0 deletions
+8
View File
@@ -154,6 +154,9 @@ void Net::Impl::clear()
prepared = false;
finalizeLayers = true;
finalized = false;
fusedSnapshotValid = false;
fusedSnapshot.clear();
}
@@ -1419,6 +1422,9 @@ void Net::Impl::getLayerShapes(const ShapesVec& netInputShapes,
LayerShapes& shapes)
{
if (mainGraph) {
// Fusion emits block-layout layers; their TransformLayout conversions are
// only inserted by finalize(), so shape inference must run post-finalize.
finalize();
std::vector<MatShape> shapeCache;
std::vector<int> typeCache;
CV_Assert(layerId == 0);
@@ -2551,6 +2557,7 @@ int64 Net::Impl::getFLOPS(const std::vector<MatShape>& netInputShapes,
const std::vector<MatType>& netInputTypes) /*const*/
{
if (mainGraph) {
finalize();
// The new graph engine executes in FP32 on CPU regardless of the requested
// target, so FP16 input types (e.g. coming from an OpenCL FP16 target) would be
// rejected by Layer::getTypes(). Normalize them to FP32 for shape/FLOPS inference.
@@ -2584,6 +2591,7 @@ int64 Net::Impl::getFLOPS(
const std::vector<MatType>& netInputTypes) /*const*/
{
if (mainGraph) {
finalize();
std::vector<MatType> inputTypes = filterFP16InputTypes(netInputTypes);
LayerShapes shapes;
std::vector<MatShape> shapeCache;
+15
View File
@@ -144,6 +144,18 @@ struct Net::Impl : public detail::NetImplBase
bool prepared; // need to rerun graph transformations/optimizations
bool finalizeLayers; // need to initialize each layer
bool finalized = false; // executors have been selected for the current backend/target
// Post-fusion (pre block-layout) snapshot so finalize() can re-run from a clean
// state on a backend/target change; useBlockLayout() is destructive and must
// run after backend assignment (see deviceOp handling in graph_block_layout.cpp).
struct FusedGraphSnapshot {
Ptr<Graph> graph;
std::vector<Ptr<LayerInfo> > prog;
std::vector<std::vector<Arg> > inputs;
std::vector<std::vector<Arg> > outputs;
};
bool fusedSnapshotValid = false;
std::vector<FusedGraphSnapshot> fusedSnapshot;
std::vector<Ptr<BackendWrapper> > argWrappers;
std::vector<const void*> argWrapperData;
TracingMode tracingMode;
@@ -426,6 +438,9 @@ struct Net::Impl : public detail::NetImplBase
void finalize();
// Selects executors for a single graph (recursing into subgraphs).
void finalizeGraph(const Ptr<Graph>& graph, bool useCUDA);
// Save/restore the fused graph so finalize() is re-entrant across backend changes.
void saveFusedSnapshot();
void restoreFusedSnapshot();
#ifdef HAVE_CUDA
Ptr<BackendWrapper> getCudaArgWrapper(Arg arg, Mat& hostMat);
#endif
+44
View File
@@ -624,6 +624,41 @@ void Net::Impl::finalizeGraph(const Ptr<Graph>& graph, bool useCUDA)
}
}
void Net::Impl::saveFusedSnapshot()
{
fusedSnapshot.clear();
for (const Ptr<Graph>& g : allgraphs) {
FusedGraphSnapshot snap;
snap.graph = g;
const std::vector<Ptr<LayerInfo> >& prog = g->prog();
snap.prog = prog;
snap.inputs.reserve(prog.size());
snap.outputs.reserve(prog.size());
for (const Ptr<LayerInfo>& op : prog) {
snap.inputs.push_back(op ? op->inputs : std::vector<Arg>());
snap.outputs.push_back(op ? op->outputs : std::vector<Arg>());
}
fusedSnapshot.push_back(std::move(snap));
}
}
void Net::Impl::restoreFusedSnapshot()
{
// Roll the graph back to its post-fusion state: undo the layer-input rewiring
// and remove the TransformLayout ops inserted by a previous useBlockLayout().
for (const FusedGraphSnapshot& snap : fusedSnapshot) {
for (size_t i = 0; i < snap.prog.size(); i++) {
const Ptr<LayerInfo>& op = snap.prog[i];
if (!op)
continue;
op->inputs = snap.inputs[i];
op->outputs = snap.outputs[i];
}
snap.graph->setProg(snap.prog);
}
totalLayers = updateGraphOfs(mainGraph, 0, true);
}
void Net::Impl::finalize()
{
#ifdef HAVE_ONNXRUNTIME
@@ -637,6 +672,15 @@ void Net::Impl::finalize()
if (finalized)
return;
// Snapshot the fused graph once so finalize() can re-run cleanly on a
// backend/target change (block layout + buffer assignment are destructive).
if (!fusedSnapshotValid) {
saveFusedSnapshot();
fusedSnapshotValid = true;
} else {
restoreFusedSnapshot();
}
bool useCUDA = false;
#ifdef HAVE_CUDA
argWrappers.clear();