[Bf-blender-cvs] [b9fea12] depsgraph_refactor: Transitive reduction optimization for operation relations.
Lukas Tönne
noreply at git.blender.org
Mon May 19 20:01:36 CEST 2014
Commit: b9fea128e07bb9eccecc09159fb6894317f724ff
Author: Lukas Tönne
Date: Mon May 19 19:41:25 2014 +0200
https://developer.blender.org/rBb9fea128e07bb9eccecc09159fb6894317f724ff
Transitive reduction optimization for operation relations.
This removed redundant relations between operations, implementing the
transitive reduction algorithm:
http://en.wikipedia.org/wiki/Transitive_reduction
The current implementation is a bit naive, but can be improved later.
Using this optimization gives more flexibility in the build procedure,
since we don't need to have fully defined relations in a component
before adding external relations.
Performance would only be improved in some extreme cases probably
(huge amount of redundant relations), it should be much more dependent
on a good scheduling heuristic.
===================================================================
M source/blender/depsgraph/intern/depsgraph_build.cpp
M source/blender/depsgraph/intern/depsnode_operation.h
===================================================================
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cpp b/source/blender/depsgraph/intern/depsgraph_build.cpp
index 2fda0ed..bf4895e 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cpp
+++ b/source/blender/depsgraph/intern/depsgraph_build.cpp
@@ -389,6 +389,73 @@ void DepsgraphRelationBuilder::add_operation_relation(OperationDepsNode *node_fr
/* -------------------------------------------------- */
+/* performs a transitive reduction to remove redundant relations
+ * http://en.wikipedia.org/wiki/Transitive_reduction
+ *
+ * XXX The current implementation is somewhat naive and has O(V*E) worst case runtime.
+ * A more optimized algorithm can be implemented later, e.g.
+ *
+ * http://www.sciencedirect.com/science/article/pii/0304397588900321/pdf?md5=3391e309b708b6f9cdedcd08f84f4afc&pid=1-s2.0-0304397588900321-main.pdf
+ *
+ * Care has to be taken to make sure the algorithm can handle the cyclic case too!
+ * (unless we can to prevent this case early on)
+ */
+
+enum {
+ OP_VISITED = 1,
+ OP_REACHABLE = 2,
+};
+
+static void deg_graph_tag_paths_recursive(OperationDepsNode *node)
+{
+ if (node->done & OP_VISITED)
+ return;
+ node->done |= OP_VISITED;
+
+ for (OperationDepsNode::Relations::const_iterator it = node->inlinks.begin(); it != node->inlinks.end(); ++it) {
+ DepsRelation *rel = *it;
+
+ deg_graph_tag_paths_recursive(rel->from);
+ /* do this only in inlinks loop, so the target node does not get flagged! */
+ rel->from->done |= OP_REACHABLE;
+ }
+}
+
+static void deg_graph_transitive_reduction(Depsgraph *graph)
+{
+ for (Depsgraph::OperationNodes::const_iterator it_target = graph->operations.begin(); it_target != graph->operations.end(); ++it_target) {
+ OperationDepsNode *target = *it_target;
+
+ /* clear tags */
+ for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin(); it != graph->operations.end(); ++it) {
+ OperationDepsNode *node = *it;
+ node->done = 0;
+ }
+
+ /* mark nodes from which we can reach the target
+ * start with children, so the target node and direct children are not flagged
+ */
+ target->done |= OP_VISITED;
+ for (OperationDepsNode::Relations::const_iterator it = target->inlinks.begin(); it != target->inlinks.end(); ++it) {
+ DepsRelation *rel = *it;
+
+ deg_graph_tag_paths_recursive(rel->from);
+ }
+
+ /* remove redundant paths to the target */
+ for (OperationDepsNode::Relations::const_iterator it_rel = target->inlinks.begin(); it_rel != target->inlinks.end();) {
+ DepsRelation *rel = *it_rel;
+ ++it_rel; /* increment in advance, so we can safely remove the relation */
+
+ if (rel->from->done & OP_REACHABLE) {
+ delete rel;
+ }
+ }
+ }
+}
+
+/* -------------------------------------------------- */
+
/* Build depsgraph for the given scene, and dump results in given graph container */
// XXX: assume that this is called from outside, given the current scene as the "main" scene
void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene)
@@ -420,6 +487,8 @@ void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene)
/* sort nodes to determine evaluation order (in most cases) */
DEG_graph_sort(graph);
#endif
+
+ deg_graph_transitive_reduction(graph);
}
/* ************************************************* */
diff --git a/source/blender/depsgraph/intern/depsnode_operation.h b/source/blender/depsgraph/intern/depsnode_operation.h
index c085e01..6d27599 100644
--- a/source/blender/depsgraph/intern/depsnode_operation.h
+++ b/source/blender/depsgraph/intern/depsnode_operation.h
@@ -60,9 +60,6 @@ typedef enum eDepsOperation_Flag {
/* Operation is evaluated using CPython; has GIL and security implications... */
DEPSOP_FLAG_USES_PYTHON = (1 << 2),
-
- /* node was visited/handled already in traversal... */
- DEPSOP_FLAG_TEMP_TAG = (1 << 3),
} eDepsOperation_Flag;
/* Atomic Operation - Base type for all operations */
@@ -90,6 +87,7 @@ struct OperationDepsNode : public DepsNode {
short optype; /* (eDepsOperation_Type) stage of evaluation */
short flag; /* (eDepsOperation_Flag) extra settings affecting evaluation */
+ short done; /* generic tag for traversal algorithms */
};
/* Macros for common static typeinfo */
More information about the Bf-blender-cvs
mailing list