[Bf-blender-cvs] [0494f14] depsgraph_refactor: Added threading system to evaluate the depsgraph nodes as managed by the scheduler.

Lukas Tönne noreply at git.blender.org
Thu May 22 15:22:15 CEST 2014


Commit: 0494f149a7d1651d434e1003a678a895d1856667
Author: Lukas Tönne
Date:   Thu May 22 14:23:37 2014 +0200
https://developer.blender.org/rB0494f149a7d1651d434e1003a678a895d1856667

Added threading system to evaluate the depsgraph nodes as managed by the scheduler.

This follows the same principles as the TaskScheduler/TaskPool systems in cycles
and the existing depsgraph, but uses a more flexible priority loop instead of the
simple low/high priority there.

===================================================================

M	source/blender/depsgraph/CMakeLists.txt
M	source/blender/depsgraph/intern/depsgraph_eval.cpp
M	source/blender/depsgraph/intern/depsgraph_eval.h
M	source/blender/depsgraph/intern/depsnode.cpp
M	source/blender/depsgraph/intern/depsnode.h
M	source/blender/depsgraph/intern/depsnode_component.cpp
M	source/blender/depsgraph/intern/depsnode_component.h
M	source/blender/depsgraph/intern/depsnode_operation.cpp
M	source/blender/depsgraph/intern/depsnode_operation.h
A	source/blender/depsgraph/util/depsgraph_util_thread.h

===================================================================

diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt
index e063450..803c316 100644
--- a/source/blender/depsgraph/CMakeLists.txt
+++ b/source/blender/depsgraph/CMakeLists.txt
@@ -76,6 +76,7 @@ set(SRC
 	util/depsgraph_util_rna.h
 	util/depsgraph_util_set.h
 	util/depsgraph_util_string.h
+	util/depsgraph_util_thread.h
 	util/depsgraph_util_type_traits.h
 )
 
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cpp b/source/blender/depsgraph/intern/depsgraph_eval.cpp
index a204add..23d9b26 100644
--- a/source/blender/depsgraph/intern/depsgraph_eval.cpp
+++ b/source/blender/depsgraph/intern/depsgraph_eval.cpp
@@ -70,20 +70,16 @@ extern "C" {
 /* *************************************************** */
 /* Multi-Threaded Evaluation Internals */
 
-/* Internal - Lock shared between depsgraph internals for various critical activities */
-// XXX: need to review the access modifiers here, as other files within depsgraph may need to access
-static SpinLock threaded_update_lock;
-
 /* Initialise threading lock - called during application startup */
 void DEG_threaded_init(void)
 {
-	BLI_spin_init(&threaded_update_lock);
+	Scheduler::init();
 }
 
 /* Free threading lock - called during application shutdown */
 void DEG_threaded_exit(void)
 {
-	BLI_spin_end(&threaded_update_lock);
+	Scheduler::exit();
 }
 
 /* *************************************************** */
@@ -124,12 +120,85 @@ static void deg_exec_node(Depsgraph *graph, DepsNode *node, eEvaluationContextTy
 	/* NOTE: "generic" nodes cannot be executed, but will still end up calling this */
 }
 
-Scheduler::Scheduler()
+EvalQueue Scheduler::queue;
+ThreadMutex Scheduler::queue_mutex;
+ThreadCondition Scheduler::queue_cond;
+ThreadMutex Scheduler::mutex;
+Scheduler::Threads Scheduler::threads;
+bool Scheduler::do_exit;
+
+void Scheduler::init(int num_threads)
 {
+	BLI_mutex_init(&mutex);
+	BLI_mutex_init(&queue_mutex);
+	BLI_condition_init(&queue_cond);
+	
+	do_exit = false;
+	
+	if(num_threads == 0) {
+		/* automatic number of threads */
+		num_threads = BLI_system_thread_count();
+	}
+	
+	/* launch threads that will be waiting for work */
+	threads.resize(num_threads);
+	
+	for(size_t i = 0; i < threads.size(); i++)
+		threads[i] = new Thread((Thread::run_cb_t)Scheduler::thread_run, i);
 }
 
-Scheduler::~Scheduler()
+void Scheduler::exit()
 {
+	/* stop all waiting threads */
+	do_exit = true;
+	BLI_condition_notify_all(&queue_cond);
+	
+	/* delete threads */
+	for (Threads::const_iterator it = threads.begin(); it != threads.end(); ++it) {
+		Thread *t = *it;
+		t->join();
+		delete t;
+	}
+	threads.clear();
+	
+	BLI_mutex_end(&mutex);
+	BLI_mutex_end(&queue_mutex);
+	BLI_condition_end(&queue_cond);
+}
+
+bool Scheduler::thread_wait_pop(DepsgraphTask &task)
+{
+	BLI_mutex_lock(&queue_mutex);
+
+	while(queue.empty() && !do_exit)
+		BLI_condition_wait(&queue_cond, &queue_mutex);
+
+	if(queue.empty()) {
+		BLI_assert(do_exit);
+		return false;
+	}
+	
+	task = queue.top();
+	queue.pop();
+	
+	BLI_mutex_unlock(&queue_mutex);
+	
+	return true;
+}
+
+void Scheduler::thread_run(Thread *thread)
+{
+	DepsgraphTask task;
+
+	/* keep popping off tasks */
+	while(thread_wait_pop(task)) {
+		/* run task */
+		
+		deg_exec_node(task.graph, task.node, task.context_type);
+		
+		/* notify pool task was done */
+		finish_node(task.graph, task.context_type, task.node);
+	}
 }
 
 static bool is_node_ready(OperationDepsNode *node)
@@ -137,33 +206,42 @@ static bool is_node_ready(OperationDepsNode *node)
 	return (node->flag & DEPSOP_FLAG_NEEDS_UPDATE) && node->num_links_pending == 0;
 }
 
-void Scheduler::schedule_graph(Depsgraph *graph)
+void Scheduler::schedule_graph(Depsgraph *graph, eEvaluationContextType context_type)
 {
 	for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin(); it != graph->operations.end(); ++it) {
 		OperationDepsNode *node = *it;
 		
-		if (is_node_ready(node))
-			queue.push(node);
+		if (is_node_ready(node)) {
+			schedule_node(graph, context_type, node);
+		}
 	}
 }
 
-OperationDepsNode *Scheduler::retrieve_node()
+void Scheduler::schedule_node(Depsgraph *graph, eEvaluationContextType context_type, OperationDepsNode *node)
 {
-	OperationDepsNode *node = queue.top();
-	queue.pop();
-	return node;
+	DepsgraphTask task;
+	task.graph = graph;
+	task.node = node;
+	task.context_type = context_type;
+	
+	queue.push(task);
 }
 
-void Scheduler::finish_node(OperationDepsNode *node)
+void Scheduler::finish_node(Depsgraph *graph, eEvaluationContextType context_type, OperationDepsNode *node)
 {
+	bool notify = false;
 	for (OperationDepsNode::Relations::const_iterator it = node->outlinks.begin(); it != node->outlinks.end(); ++it) {
 		DepsRelation *rel = *it;
 		
 		BLI_assert(rel->to->num_links_pending > 0);
 		--rel->to->num_links_pending;
-		if (rel->to->num_links_pending == 0)
-			queue.push(node);
+		if (rel->to->num_links_pending == 0) {
+			schedule_node(graph, context_type, rel->to);
+			notify = true;
+		}
 	}
+	if (notify)
+		BLI_condition_notify_all(&queue_cond);
 }
 
 /* *************************************************** */
@@ -179,7 +257,7 @@ static void calculate_pending_parents(Depsgraph *graph)
 		/* count number of inputs that need updates */
 		if (node->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
 			for (OperationDepsNode::Relations::const_iterator it_rel = node->inlinks.begin(); it_rel != node->inlinks.end(); ++it_rel) {
-				DepsRelation *rel = *it;
+				DepsRelation *rel = *it_rel;
 				if (rel->from->flag & DEPSOP_FLAG_NEEDS_UPDATE)
 					++node->num_links_pending;
 			}
@@ -234,8 +312,7 @@ void DEG_evaluate_on_refresh(Depsgraph *graph, eEvaluationContextType context_ty
 	
 	DEG_debug_eval_step("Eval Priority Calculation");
 	
-	Scheduler scheduler;
-	scheduler.schedule_graph(graph);
+	Scheduler::schedule_graph(graph, context_type);
 	
 	/* from the root node, start queuing up nodes to evaluate */
 	// ... start scheduler, etc.
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.h b/source/blender/depsgraph/intern/depsgraph_eval.h
index 5523d53..4bfd63e 100644
--- a/source/blender/depsgraph/intern/depsgraph_eval.h
+++ b/source/blender/depsgraph/intern/depsgraph_eval.h
@@ -33,7 +33,12 @@
 #ifndef __DEPSGRAPH_EVAL_TYPES_H__
 #define __DEPSGRAPH_EVAL_TYPES_H__
 
+#include <vector>
+
+#include "DEG_depsgraph.h"
+
 #include "depsgraph_util_priority_queue.h"
+#include "depsgraph_util_thread.h"
 
 struct Depsgraph;
 struct OperationDepsNode;
@@ -126,27 +131,50 @@ typedef struct DEG_PoseContext {
 
 /* ****************************************** */
 
+struct DepsgraphTask {
+	Depsgraph *graph;
+	OperationDepsNode *node;
+	eEvaluationContextType context_type;
+};
 
-struct CompareOperationNode {
-	bool operator() (OperationDepsNode *a, OperationDepsNode *b)
+struct CompareDepsgraphTask {
+	bool operator() (const DepsgraphTask &a, const DepsgraphTask &b)
 	{
-		return a->eval_priority < b->eval_priority;
+		return a.node->eval_priority < b.node->eval_priority;
 	}
 };
 
-typedef priority_queue<OperationDepsNode *, vector<OperationDepsNode *>, CompareOperationNode> EvalQueue;
+typedef priority_queue<DepsgraphTask, vector<DepsgraphTask>, CompareDepsgraphTask> EvalQueue;
 
 class Scheduler {
 public:
-	Scheduler();
-	~Scheduler();
+	typedef std::vector<Thread*> Threads;
+	
+	static void init(int num_threads = 0);
+	static void exit();
+	
+	/* number of threads that can work on task */
+	static int num_threads() { return threads.size(); }
+	
+	static void schedule_graph(Depsgraph *graph, eEvaluationContextType context_type);
+	static void schedule_node(Depsgraph *graph, eEvaluationContextType context_type, OperationDepsNode *node);
+	static void finish_node(Depsgraph *graph, eEvaluationContextType context_type, OperationDepsNode *node);
+	
+	static EvalQueue queue;
+	static ThreadMutex queue_mutex;
+	static ThreadCondition queue_cond;
+	/* XXX consider using spin lock here */
+	
+	static void thread_run(Thread *thread);
+	static bool thread_wait_pop(DepsgraphTask &task);
 	
-	void schedule_graph(Depsgraph *graph);
-	OperationDepsNode *retrieve_node();
-	void finish_node(OperationDepsNode *node);
+	//static void push(Entry& entry, bool front);
+	//static void clear(TaskPool *pool);
 	
 private:
-	EvalQueue queue;
+	static ThreadMutex mutex;
+	static Threads threads;
+	static bool do_exit;
 };
 
 /* ****************************************** */
diff --git a/source/blender/depsgraph/intern/depsnode.cpp b/source/blender/depsgraph/intern/depsnode.cpp
index b72c715..b95a697 100644
--- a/source/blender/depsgraph/intern/depsnode.cpp
+++ b/source/blender/depsgraph/intern/depsnode.cpp
@@ -22,8 +22,6 @@
  * Contributor(s): None Yet
  *
  * ***** END GPL LICENSE BLOCK *****
- *
- * Core routines for how the Depsgraph works
  */
 
 #include <stdlib.h>
diff --git a/source/blender/depsgraph/intern/depsnode.h b/source/blender/depsgraph/intern/depsnode.h
index ea519a1..58794bf 100644
--- a/source/blender/depsgraph/intern/depsnode.h
+++ b/source/blender/depsgraph/intern/depsnode.h
@@ -22,12 +22,6 @@
  * Contributor(s): None Yet
  *
  * ***** END GPL LICENSE BLOCK *****
- *
- * Datatypes for internal use in the Depsgraph
- * 
- * All of these datatypes are only really used within the "core" depsgraph.
- * In particular, node types declared here form the structure of operations
- * in the graph.
  */
 
 #ifndef __DEPSNODE_H__
diff --git a/source/blender/depsgraph/intern/depsnode_component.cpp b/source/blender/depsgraph/intern/depsnode_component.cpp
index ea21f7e..962dcf4 100644
--- a/source/blender/depsgraph/intern/depsnode_component.cpp
+++ b/source/blender/depsgraph/intern/depsnode_component.cpp
@@ -22,8 +22,6 @@
  * Contributor(s): None Yet
  *
  * ***** END GPL LICENSE BLOCK *****
- *
- * Core routines for how the Depsgraph works
  */
 
 #include <string.h>
diff --git a/source/blender/depsgraph/intern/depsnode_component.h b/source/blender/depsgraph/intern/depsnode_component.h
index 441c918..9bae9e0 100644
--- a/source/blender/depsgraph/intern/depsnode_component.h
+++ b/source/blender/depsgraph/intern/depsnode_component.h
@@ -22,12 +22,6 @@
  * Contributor(s): None Yet
  *
  * ***** END GPL LICENSE BLOCK *****
- *
- * Datatypes for internal u

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list