[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [59676] trunk/blender/intern/cycles: Fix #36137: cycles render not using all GPU's when the number of GPU' s is larger

Brecht Van Lommel brechtvanlommel at pandora.be
Sat Aug 31 01:09:23 CEST 2013


Revision: 59676
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=59676
Author:   blendix
Date:     2013-08-30 23:09:22 +0000 (Fri, 30 Aug 2013)
Log Message:
-----------
Fix #36137: cycles render not using all GPU's when the number of GPU's is larger
than the number of CPU threads

Modified Paths:
--------------
    trunk/blender/intern/cycles/device/device_cuda.cpp
    trunk/blender/intern/cycles/device/device_opencl.cpp
    trunk/blender/intern/cycles/util/util_task.cpp
    trunk/blender/intern/cycles/util/util_task.h

Modified: trunk/blender/intern/cycles/device/device_cuda.cpp
===================================================================
--- trunk/blender/intern/cycles/device/device_cuda.cpp	2013-08-30 22:04:37 UTC (rev 59675)
+++ trunk/blender/intern/cycles/device/device_cuda.cpp	2013-08-30 23:09:22 UTC (rev 59676)
@@ -37,7 +37,7 @@
 class CUDADevice : public Device
 {
 public:
-	TaskPool task_pool;
+	DedicatedTaskPool task_pool;
 	CUdevice cuDevice;
 	CUcontext cuContext;
 	CUmodule cuModule;
@@ -976,7 +976,7 @@
 
 	void task_wait()
 	{
-		task_pool.wait_work();
+		task_pool.wait();
 	}
 
 	void task_cancel()

Modified: trunk/blender/intern/cycles/device/device_opencl.cpp
===================================================================
--- trunk/blender/intern/cycles/device/device_opencl.cpp	2013-08-30 22:04:37 UTC (rev 59675)
+++ trunk/blender/intern/cycles/device/device_opencl.cpp	2013-08-30 23:09:22 UTC (rev 59676)
@@ -314,7 +314,7 @@
 class OpenCLDevice : public Device
 {
 public:
-	TaskPool task_pool;
+	DedicatedTaskPool task_pool;
 	cl_context cxContext;
 	cl_command_queue cqCommandQueue;
 	cl_platform_id cpPlatform;
@@ -1100,7 +1100,7 @@
 
 	void task_wait()
 	{
-		task_pool.wait_work();
+		task_pool.wait();
 	}
 
 	void task_cancel()

Modified: trunk/blender/intern/cycles/util/util_task.cpp
===================================================================
--- trunk/blender/intern/cycles/util/util_task.cpp	2013-08-30 22:04:37 UTC (rev 59675)
+++ trunk/blender/intern/cycles/util/util_task.cpp	2013-08-30 23:09:22 UTC (rev 59676)
@@ -168,7 +168,7 @@
 thread_mutex TaskScheduler::mutex;
 int TaskScheduler::users = 0;
 vector<thread*> TaskScheduler::threads;
-volatile bool TaskScheduler::do_exit = false;
+bool TaskScheduler::do_exit = false;
 
 list<TaskScheduler::Entry> TaskScheduler::queue;
 thread_mutex TaskScheduler::queue_mutex;
@@ -298,5 +298,153 @@
 	pool->num_decrease(done);
 }
 
+/* Dedicated Task Pool */
+
+DedicatedTaskPool::DedicatedTaskPool()
+{
+	do_cancel = false;
+	do_exit = false;
+	num = 0;
+
+	worker_thread = new thread(function_bind(&DedicatedTaskPool::thread_run, this));
+}
+
+DedicatedTaskPool::~DedicatedTaskPool()
+{
+	stop();
+	worker_thread->join();
+	delete worker_thread;
+}
+
+void DedicatedTaskPool::push(Task *task, bool front)
+{
+	num_increase();
+
+	/* add task to queue */
+	queue_mutex.lock();
+	if(front)
+		queue.push_front(task);
+	else
+		queue.push_back(task);
+
+	queue_cond.notify_one();
+	queue_mutex.unlock();
+}
+
+void DedicatedTaskPool::push(const TaskRunFunction& run, bool front)
+{
+	push(new Task(run), front);
+}
+
+void DedicatedTaskPool::wait()
+{
+	thread_scoped_lock num_lock(num_mutex);
+
+	while(num)
+		num_cond.wait(num_lock);
+}
+
+void DedicatedTaskPool::cancel()
+{
+	do_cancel = true;
+
+	clear();
+	wait();
+
+	do_cancel = false;
+}
+
+void DedicatedTaskPool::stop()
+{
+	clear();
+
+	do_exit = true;
+	queue_cond.notify_all();
+
+	wait();
+
+	assert(num == 0);
+}
+
+bool DedicatedTaskPool::cancelled()
+{
+	return do_cancel;
+}
+
+void DedicatedTaskPool::num_decrease(int done)
+{
+	num_mutex.lock();
+	num -= done;
+
+	assert(num >= 0);
+	if(num == 0)
+		num_cond.notify_all();
+
+	num_mutex.unlock();
+}
+
+void DedicatedTaskPool::num_increase()
+{
+	thread_scoped_lock num_lock(num_mutex);
+	num++;
+	num_cond.notify_all();
+}
+
+bool DedicatedTaskPool::thread_wait_pop(Task*& task)
+{
+	thread_scoped_lock queue_lock(queue_mutex);
+
+	while(queue.empty() && !do_exit)
+		queue_cond.wait(queue_lock);
+
+	if(queue.empty()) {
+		assert(do_exit);
+		return false;
+	}
+
+	task = queue.front();
+	queue.pop_front();
+
+	return true;
+}
+
+void DedicatedTaskPool::thread_run()
+{
+	Task *task;
+
+	/* keep popping off tasks */
+	while(thread_wait_pop(task)) {
+		/* run task */
+		task->run();
+
+		/* delete task */
+		delete task;
+
+		/* notify task was done */
+		num_decrease(1);
+	}
+}
+
+void DedicatedTaskPool::clear()
+{
+	thread_scoped_lock queue_lock(queue_mutex);
+
+	/* erase all tasks from the queue */
+	list<Task*>::iterator it = queue.begin();
+	int done = 0;
+
+	while(it != queue.end()) {
+		done++;
+		delete *it;
+
+		it = queue.erase(it);
+	}
+
+	queue_lock.unlock();
+
+	/* notify done */
+	num_decrease(done);
+}
+
 CCL_NAMESPACE_END
 

Modified: trunk/blender/intern/cycles/util/util_task.h
===================================================================
--- trunk/blender/intern/cycles/util/util_task.h	2013-08-30 22:04:37 UTC (rev 59675)
+++ trunk/blender/intern/cycles/util/util_task.h	2013-08-30 23:09:22 UTC (rev 59676)
@@ -50,7 +50,7 @@
  * pool, we can wait for all tasks to be done, or cancel them before they are
  * done.
  *
- * The run callback that actually executes the task may be create like this:
+ * The run callback that actually executes the task may be created like this:
  * function_bind(&MyClass::task_execute, this, _1, _2) */
 
 class TaskPool
@@ -77,8 +77,8 @@
 	thread_mutex num_mutex;
 	thread_condition_variable num_cond;
 
-	volatile int num;
-	volatile bool do_cancel;
+	int num;
+	bool do_cancel;
 };
 
 /* Task Scheduler
@@ -109,7 +109,7 @@
 	static thread_mutex mutex;
 	static int users;
 	static vector<thread*> threads;
-	static volatile bool do_exit;
+	static bool do_exit;
 
 	static list<Entry> queue;
 	static thread_mutex queue_mutex;
@@ -122,6 +122,51 @@
 	static void clear(TaskPool *pool);
 };
 
+/* Dedicated Task Pool
+ *
+ * Like a TaskPool, but will launch one dedicated thread to execute all tasks.
+ *
+ * The run callback that actually executes the task may be created like this:
+ * function_bind(&MyClass::task_execute, this, _1, _2) */
+
+class DedicatedTaskPool
+{
+public:
+	DedicatedTaskPool();
+	~DedicatedTaskPool();
+
+	void push(Task *task, bool front = false);
+	void push(const TaskRunFunction& run, bool front = false);
+
+	void wait();        /* wait until all tasks are done */
+	void cancel();		/* cancel all tasks, keep worker thread running */
+	void stop();		/* stop worker thread */
+
+	bool cancelled();	/* for worker thread, test if cancelled */
+
+protected:
+	void num_decrease(int done);
+	void num_increase();
+
+	void thread_run();
+	bool thread_wait_pop(Task*& entry);
+
+	void clear();
+
+	thread_mutex num_mutex;
+	thread_condition_variable num_cond;
+
+	list<Task*> queue;
+	thread_mutex queue_mutex;
+	thread_condition_variable queue_cond;
+
+	int num;
+	bool do_cancel;
+	bool do_exit;
+
+	thread *worker_thread;
+};
+
 CCL_NAMESPACE_END
 
 #endif




More information about the Bf-blender-cvs mailing list