[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