2
0
Эх сурвалжийг харах

Merge pull request #54486 from ibrahn/thread-work-pool-lazier

Rémi Verschelde 3 жил өмнө
parent
commit
e87687a6d0

+ 20 - 4
core/templates/thread_work_pool.h

@@ -73,6 +73,7 @@ class ThreadWorkPool {
 
 
 	ThreadData *threads = nullptr;
 	ThreadData *threads = nullptr;
 	uint32_t thread_count = 0;
 	uint32_t thread_count = 0;
+	uint32_t threads_working = 0;
 	BaseWork *current_work = nullptr;
 	BaseWork *current_work = nullptr;
 
 
 	static void _thread_function(void *p_user);
 	static void _thread_function(void *p_user);
@@ -94,7 +95,9 @@ public:
 
 
 		current_work = w;
 		current_work = w;
 
 
-		for (uint32_t i = 0; i < thread_count; i++) {
+		threads_working = MIN(p_elements, thread_count);
+
+		for (uint32_t i = 0; i < threads_working; i++) {
 			threads[i].work = w;
 			threads[i].work = w;
 			threads[i].start.post();
 			threads[i].start.post();
 		}
 		}
@@ -117,19 +120,32 @@ public:
 
 
 	void end_work() {
 	void end_work() {
 		ERR_FAIL_COND(current_work == nullptr);
 		ERR_FAIL_COND(current_work == nullptr);
-		for (uint32_t i = 0; i < thread_count; i++) {
+		for (uint32_t i = 0; i < threads_working; i++) {
 			threads[i].completed.wait();
 			threads[i].completed.wait();
 			threads[i].work = nullptr;
 			threads[i].work = nullptr;
 		}
 		}
 
 
+		threads_working = 0;
 		memdelete(current_work);
 		memdelete(current_work);
 		current_work = nullptr;
 		current_work = nullptr;
 	}
 	}
 
 
 	template <class C, class M, class U>
 	template <class C, class M, class U>
 	void do_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) {
 	void do_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) {
-		begin_work(p_elements, p_instance, p_method, p_userdata);
-		end_work();
+		switch (p_elements) {
+			case 0:
+				// Nothing to do, so do nothing.
+				break;
+			case 1:
+				// No value in pushing the work to another thread if it's a single job
+				// and we're going to wait for it to finish. Just run it right here.
+				(p_instance->*p_method)(0, p_userdata);
+				break;
+			default:
+				// Multiple jobs to do; commence threaded business.
+				begin_work(p_elements, p_instance, p_method, p_userdata);
+				end_work();
+		}
 	}
 	}
 
 
 	_FORCE_INLINE_ int get_thread_count() const { return thread_count; }
 	_FORCE_INLINE_ int get_thread_count() const { return thread_count; }

+ 1 - 5
servers/physics_2d/godot_step_2d.cpp

@@ -255,11 +255,7 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta, int p_iterations)
 
 
 	// Warning: _solve_island modifies the constraint islands for optimization purpose,
 	// Warning: _solve_island modifies the constraint islands for optimization purpose,
 	// their content is not reliable after these calls and shouldn't be used anymore.
 	// their content is not reliable after these calls and shouldn't be used anymore.
-	if (island_count > 1) {
-		work_pool.do_work(island_count, this, &GodotStep2D::_solve_island, nullptr);
-	} else if (island_count > 0) {
-		_solve_island(0);
-	}
+	work_pool.do_work(island_count, this, &GodotStep2D::_solve_island, nullptr);
 
 
 	{ //profile
 	{ //profile
 		profile_endtime = OS::get_singleton()->get_ticks_usec();
 		profile_endtime = OS::get_singleton()->get_ticks_usec();

+ 1 - 5
servers/physics_3d/godot_step_3d.cpp

@@ -359,11 +359,7 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta, int p_iterations)
 
 
 	// Warning: _solve_island modifies the constraint islands for optimization purpose,
 	// Warning: _solve_island modifies the constraint islands for optimization purpose,
 	// their content is not reliable after these calls and shouldn't be used anymore.
 	// their content is not reliable after these calls and shouldn't be used anymore.
-	if (island_count > 1) {
-		work_pool.do_work(island_count, this, &GodotStep3D::_solve_island, nullptr);
-	} else if (island_count > 0) {
-		_solve_island(0);
-	}
+	work_pool.do_work(island_count, this, &GodotStep3D::_solve_island, nullptr);
 
 
 	{ //profile
 	{ //profile
 		profile_endtime = OS::get_singleton()->get_ticks_usec();
 		profile_endtime = OS::get_singleton()->get_ticks_usec();