-
Notifications
You must be signed in to change notification settings - Fork 4.5k
fix: support >64 CPUs on Windows via processor groups (#6142) #6823
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1373,11 +1373,11 @@ static ncnn::CpuSet get_smt_cpu_mask() | |
| if (ptr->Relationship == RelationProcessorCore) | ||
| { | ||
| ncnn::CpuSet smt_set; | ||
| smt_set.mask = ptr->ProcessorMask; | ||
| smt_set.mask[0] = ptr->ProcessorMask; | ||
| if (smt_set.num_enabled() > 1) | ||
| { | ||
| // this core is smt | ||
| smt_cpu_mask.mask |= smt_set.mask; | ||
| smt_cpu_mask.mask[0] |= smt_set.mask[0]; | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -1432,14 +1432,43 @@ static std::vector<int> get_max_freq_mhz() | |
|
|
||
| static int set_sched_affinity(const ncnn::CpuSet& thread_affinity_mask) | ||
| { | ||
| DWORD_PTR prev_mask = SetThreadAffinityMask(GetCurrentThread(), thread_affinity_mask.mask); | ||
| if (prev_mask == 0) | ||
| // Find the first enabled CPU group and bind this thread to it. | ||
| // A thread can only belong to one processor group at a time. | ||
| // For multi-group masks, set_cpu_thread_affinity() calls this | ||
| // repeatedly per-thread, each bound to a specific group. | ||
| for (int g = 0; g < NCNN_MAX_PROCESSOR_GROUPS; g++) | ||
| { | ||
| NCNN_LOGE("SetThreadAffinityMask failed %d", GetLastError()); | ||
| return -1; | ||
| if (thread_affinity_mask.mask[g] == 0) | ||
| continue; | ||
|
|
||
| #if _WIN32_WINNT >= 0x0601 // Win7+ | ||
| GROUP_AFFINITY ga; | ||
| ga.Group = (WORD)g; | ||
| ga.Mask = thread_affinity_mask.mask[g]; | ||
| ga.Reserved[0] = 0; | ||
| ga.Reserved[1] = 0; | ||
| ga.Reserved[2] = 0; | ||
|
|
||
| GROUP_AFFINITY prev; | ||
| if (!SetThreadGroupAffinity(GetCurrentThread(), &ga, &prev)) | ||
| { | ||
| NCNN_LOGE("SetThreadGroupAffinity failed for group %d: %d", g, GetLastError()); | ||
| return -1; | ||
| } | ||
| #else // XP: only group 0 supported, use legacy API | ||
| if (g != 0) | ||
| continue; // XP cannot bind beyond group 0 | ||
| DWORD_PTR prev = SetThreadAffinityMask(GetCurrentThread(), thread_affinity_mask.mask[0]); | ||
| if (prev == 0) | ||
| { | ||
| NCNN_LOGE("SetThreadAffinityMask failed %d", GetLastError()); | ||
| return -1; | ||
| } | ||
| #endif | ||
| return 0; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When the affinity mask spans multiple Windows processor groups, this early return binds every caller to only the first non-empty group. Useful? React with 👍 / 👎. |
||
| } | ||
|
|
||
| return 0; | ||
| return 0; // no CPUs enabled | ||
| } | ||
| #endif // defined _WIN32 | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,10 @@ | |
|
|
||
| #include "platform.h" | ||
|
|
||
| // Windows processor groups each contain up to 64 logical processors. | ||
| // Support up to NCNN_MAX_PROCESSOR_GROUPS groups (512 CPUs max at 8 groups). | ||
| #define NCNN_MAX_PROCESSOR_GROUPS 8 | ||
|
|
||
| namespace ncnn { | ||
|
|
||
| class NCNN_EXPORT CpuSet | ||
|
|
@@ -30,7 +34,7 @@ class NCNN_EXPORT CpuSet | |
|
|
||
| public: | ||
| #if defined _WIN32 | ||
| ULONG_PTR mask; | ||
| KAFFINITY mask[NCNN_MAX_PROCESSOR_GROUPS]; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In the current tree, changing Useful? React with 👍 / 👎. |
||
| #endif | ||
| #if defined __ANDROID__ || defined __linux__ | ||
| cpu_set_t cpu_set; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When building the repository's Windows XP configurations (
.github/workflows/windows-xp.ymluses-DNCNN_WINXP=ONand the XP toolchains set_WIN32_WINNT=0x0501), this unguarded call is not available: Microsoft documentsSetThreadGroupAffinityas requiring_WIN32_WINNT >= 0x0601/ Windows 7 (https://learn.microsoft.com/en-us/windows/win32/api/processtopologyapi/nf-processtopologyapi-setthreadgroupaffinity). Because the whole_WIN32affinity path now depends on it, those supported XP-targeted builds fail instead of falling back toSetThreadAffinityMask.Useful? React with 👍 / 👎.