From 751573ce6fff547b6a53769245814bc2d3fed17f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 22 Nov 2016 16:03:16 +0100 Subject: Fix T50034: Blender changes processor affinity unauthorized --- intern/cycles/util/util_system.cpp | 14 ++++++++++++++ intern/cycles/util/util_system.h | 4 ++++ intern/cycles/util/util_task.cpp | 34 +++++++++++++++++++++++++++++++--- intern/cycles/util/util_windows.cpp | 15 +++++++++++++++ intern/cycles/util/util_windows.h | 4 ++++ 5 files changed, 68 insertions(+), 3 deletions(-) (limited to 'intern') diff --git a/intern/cycles/util/util_system.cpp b/intern/cycles/util/util_system.cpp index d5fac9a0e34..2c7abbaacbb 100644 --- a/intern/cycles/util/util_system.cpp +++ b/intern/cycles/util/util_system.cpp @@ -89,6 +89,20 @@ int system_cpu_thread_count() return count; } +unsigned short system_cpu_process_groups(unsigned short max_groups, + unsigned short *grpups) +{ +#ifdef _WIN32 + unsigned short group_count = max_groups; + if(!GetProcessGroupAffinity(GetCurrentProcess(), &group_count, grpups)) { + return 0; + } + return group_count; +#else + return 0; +#endif +} + #if !defined(_WIN32) || defined(FREE_WINDOWS) static void __cpuid(int data[4], int selector) { diff --git a/intern/cycles/util/util_system.h b/intern/cycles/util/util_system.h index 557aab6cbae..ff61b260bed 100644 --- a/intern/cycles/util/util_system.h +++ b/intern/cycles/util/util_system.h @@ -30,6 +30,10 @@ int system_cpu_group_thread_count(int group); /* Get total number of threads in all groups. */ int system_cpu_thread_count(); +/* Get current process groups. */ +unsigned short system_cpu_process_groups(unsigned short max_groups, + unsigned short *grpups); + string system_cpu_brand_string(); int system_cpu_bits(); bool system_cpu_support_sse2(); diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp index 352ba81c95a..0d1fed3ebbf 100644 --- a/intern/cycles/util/util_task.cpp +++ b/intern/cycles/util/util_task.cpp @@ -195,7 +195,8 @@ void TaskScheduler::init(int num_threads) if(users == 0) { do_exit = false; - if(num_threads == 0) { + const bool use_auto_threads = (num_threads == 0); + if(use_auto_threads) { /* automatic number of threads */ num_threads = system_cpu_thread_count(); } @@ -204,7 +205,18 @@ void TaskScheduler::init(int num_threads) /* launch threads that will be waiting for work */ threads.resize(num_threads); - int num_groups = system_cpu_group_count(); + const int num_groups = system_cpu_group_count(); + unsigned short num_process_groups; + vector process_groups; + int current_group_threads; + if(num_groups > 1) { + process_groups.resize(num_groups); + num_process_groups = system_cpu_process_groups(num_groups, + &process_groups[0]); + if(num_process_groups == 1) { + current_group_threads = system_cpu_group_thread_count(process_groups[0]); + } + } int thread_index = 0; for(int group = 0; group < num_groups; ++group) { /* NOTE: That's not really efficient from threading point of view, @@ -218,9 +230,25 @@ void TaskScheduler::init(int num_threads) group_thread < num_group_threads && thread_index < threads.size(); ++group_thread, ++thread_index) { + /* NOTE: Thread group of -1 means we would not force thread affinity. */ + int thread_group; + if(num_groups == 1) { + /* Use default affinity if there's only one CPU group in the system. */ + thread_group = -1; + } + else if(use_auto_threads && + num_process_groups == 1 && + num_threads <= current_group_threads) + { + /* If we fit into curent CPU group we also don't force any affinity. */ + thread_group = -1; + } + else { + thread_group = group; + } threads[thread_index] = new thread(function_bind(&TaskScheduler::thread_run, thread_index + 1), - group); + thread_group); } } } diff --git a/intern/cycles/util/util_windows.cpp b/intern/cycles/util/util_windows.cpp index ee5b3fd73c0..4de8483564b 100644 --- a/intern/cycles/util/util_windows.cpp +++ b/intern/cycles/util/util_windows.cpp @@ -28,6 +28,7 @@ CCL_NAMESPACE_BEGIN tGetActiveProcessorGroupCount *GetActiveProcessorGroupCount; tGetActiveProcessorCount *GetActiveProcessorCount; tSetThreadGroupAffinity *SetThreadGroupAffinity; +tGetProcessGroupAffinity *GetProcessGroupAffinity; #endif static WORD GetActiveProcessorGroupCount_stub() @@ -50,6 +51,18 @@ static BOOL SetThreadGroupAffinity_stub( return TRUE; } +static BOOL GetProcessGroupAffinity_stub(HANDLE hProcess, + PUSHORT GroupCount, + PUSHORT GroupArray) +{ + if(*GroupCount < 1) { + return FALSE; + } + *GroupCount = 1; + GroupArray[0] = 0; + return TRUE; +} + static bool supports_numa() { #ifndef _M_X64 @@ -72,6 +85,7 @@ void util_windows_init_numa_groups() GetActiveProcessorGroupCount = GetActiveProcessorGroupCount_stub; GetActiveProcessorCount = GetActiveProcessorCount_stub; SetThreadGroupAffinity = SetThreadGroupAffinity_stub; + GetProcessGroupAffinity = GetProcessGroupAffinity_stub; return; } HMODULE kernel = GetModuleHandleA("kernel32.dll"); @@ -79,6 +93,7 @@ void util_windows_init_numa_groups() READ_SYMBOL(GetActiveProcessorGroupCount); READ_SYMBOL(GetActiveProcessorCount); READ_SYMBOL(SetThreadGroupAffinity); + READ_SYMBOL(GetProcessGroupAffinity); # undef READ_SUMBOL #endif } diff --git a/intern/cycles/util/util_windows.h b/intern/cycles/util/util_windows.h index ac61d5348c3..7ea3e65c2c5 100644 --- a/intern/cycles/util/util_windows.h +++ b/intern/cycles/util/util_windows.h @@ -39,10 +39,14 @@ typedef DWORD tGetActiveProcessorCount(WORD GroupNumber); typedef BOOL tSetThreadGroupAffinity(HANDLE hThread, const GROUP_AFFINITY *GroupAffinity, PGROUP_AFFINITY PreviousGroupAffinity); +typedef BOOL tGetProcessGroupAffinity(HANDLE hProcess, + PUSHORT GroupCount, + PUSHORT GroupArray); extern tGetActiveProcessorGroupCount *GetActiveProcessorGroupCount; extern tGetActiveProcessorCount *GetActiveProcessorCount; extern tSetThreadGroupAffinity *SetThreadGroupAffinity; +extern tGetProcessGroupAffinity *GetProcessGroupAffinity; #endif /* Make sure NUMA and processor groups API is initialized. */ -- cgit v1.2.3