<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/72267>72267</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
`std::thread::hardware_concurrency` return incorrect count threads in NUMA multi-CPU configuration
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
GermanAizek
</td>
</tr>
</table>
<pre>
I have Xeon 2xE5-2699v4 Windows detect 88 threads and 44 cores. I noticed that all binaries that are compiled using Clang incorrectly detect count threads on multi 2x 4x socket motherboards with NUMA architecture. Therefore, I propose my own version, which is modified and works on all systems. I read on visual studio forum and realized that this is a WinAPI problem.
```cpp
#include <iostream>
#include <Windows.h>
#include <thread>
// modified my function
size_t MyHardwareConcurrency() noexcept
{
DWORD length = 0;
size_t concurrency = 0;
const auto validConcurrency = [&concurrency]() noexcept -> size_t {
if (concurrency == 0)
return std::thread::hardware_concurrency();
else
return concurrency;
};
if (GetLogicalProcessorInformationEx(RelationAll, nullptr, &length) != FALSE) {
return validConcurrency();
}
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
return validConcurrency();
}
std::unique_ptr<void, void (*)(void*)> buffer(std::malloc(length), std::free);
if (!buffer) {
return validConcurrency();
}
auto* mem = reinterpret_cast<unsigned char*>(buffer.get());
if (GetLogicalProcessorInformationEx(
RelationAll, reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX>(mem), &length) == false) {
return validConcurrency();
}
DWORD i = 0;
while (i < length) {
const auto* proc = reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX>(mem + i);
if (proc->Relationship == RelationProcessorCore) {
for (WORD group = 0; group < proc->Processor.GroupCount; ++group) {
for (KAFFINITY mask = proc->Processor.GroupMask[group].Mask; mask != 0; mask >>= 1) {
concurrency += mask & 1;
}
}
}
i += proc->Size;
}
return validConcurrency();
}
uint32_t get_thread_count()
{
static const uint32_t g_count = []()
{
#ifdef _WIN32
::SYSTEM_INFO sysInfo;
::GetNativeSystemInfo(&sysInfo);
return sysInfo.dwNumberOfProcessors;
#else
return ::sysconf(_SC_NPROCESSORS_ONLN);
#endif
}();
return g_count;
}
// in llvm-project/libcxx/src/thread.cpp
DWORD getWin32Count()
{
SYSTEM_INFO info;
GetSystemInfo(&info);
return info.dwNumberOfProcessors;
}
int main()
{
std::cout << MyHardwareConcurrency() << '\n';
std::cout << get_thread_count() << '\n';
std::cout << getWin32Count() << '\n';
}
```
Result: MSVC v19.37 latest
```
88
44
44
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJysV01z4jwS_jXKpWsoW-bLBw7EQJbahKQgs_O-J0rYbayNLLGSDMn8-i35ExgyM7s1FIWx1Hq6--lWt8SM4XuJOCGDezKY3bHCZkpPHlDnTE75d3y726nkY7KEjB0R_kIlgb7PB1_oMAyPffjGZaJOBhK0GFsYj8FmGlligMkE-n2IlUbTgyVIZXmMCdiMWWBCwI5LpjmaekQjxCo_cIEJFIbLPUSCyT1wGSutMbbio9ESq0LaVpGSkBfCcqDv0H8Ho-I3tJArm6HeKaYTAyduM1h9fZoC03HGHUihsQevGWpMlUZCI1jCQauDMgj5B6iThCNqw5V0c6eMxxlwA7lKeMoxKd07Kf1W6nfumA9jMS9ddXa54SM3BRNgbJFwBanSRV6u08gE_95wYTNuHDRzZE5fSjN2AvMe8WbEm9a_Q6_6xodDPUIDLmNRJAgkiLgyViPLSTC_NV2HqZd9Ml9x2U3WIgtCF53L-QekhYyt46QUMPw7bi08ffyD6eTENEZKxoXWKOMPQseEhiAVvsd4sDXi6L5REM6-Pa9nIFDubQYkmIFHgm62ho47wB9lYiWNBVZYBUcmeBJdCbuUpsMzCDKYXZkFX0gwh1rZuXXEC3kKhI6vLKiMoOG5IPFCjbbQEoxNSDAlwbTh0_3PanK28TU7584QL0Rh8Dbu-crLNWQ0Ox-pbH5A-6j2PGbiRasYjVF6KVOlc-ZiN38ndLxGUb5MhXD5LQshDla7v4QOq6A4ngj1nceL6eNmXr5fUlSbd83-De9Gsxs2MmPnWitdB6VWNl-vn9fb5WrzdbFYRsv56nV7_3WxmK__lAFtlArJ_1Pg1jkeREfFE-e_e0IJMHUYdFxNlC_BHHZFmqKzuEXJmRAqJnTc0uZg2ulUI14ZUzFAqN-A_Rm_3E4gdAo55mX-a-TSoj5otNuYGUuCqJBluU8gzph2TgVzQseVGb092lrBLXN_I6nOPbhKsBu2vGz-3rzOn7aPzw_LaPq4fVk_R_PNpoz94nn9NH1dPq-2878qG3PMa2YvE7Takilze-cP8VhVJv5jwTllXKDjws1FcGbFpdauMLlwHLSKP4vH_8wBEHoP_MfaUcXIqXIVrSHfZPzQUNSMtdGLyr73g_HEC1OlHVpJw16r4tBS0b5G0Ohq8XoPbi5yvdlJEnpP6H0pf1tLp-if08ViuVq-_g05M2-lsk_Qn5h5I4MadTDrle_Bfb2uqh9eNxDMy-8M_E9NqMLVlXh67-RrvCH41_W2rbpXg1cjl6-8wW3c2vDv-Fn6_WbOdivcb8GlDejWwh7ttuo-2_KYVC-7bL8AAMYyy2OocrVbXq1q-2fTMet1HYU04GmCKWy_LVcB7WCbT1X86vR2yewOSK5gtB7UIg9oV8zyI27KA1Qp4lQOG_kzp88VNC23kuolp1WR71A_p23KmI4sGnTN9QZIZYn5MLGSKaHj7Sbartq9uNk-rx5XF-TTAGXC00tAF5LrwlLO11pqbj8LYX3c4hKEOOZfDlr9G2NL6ELwXfz-TujC6JjQRRXdXnsQrMrVHu03LgMafRp04oXn4eDnsSBe-ID2OgL8iv4uOfmvKb90jksLOePyJ-lY98tYFS79IldjfnayrEUIHZFBJN0j-BXc7b3xfyJds_0TmI6L5hR_Ts0aTSEsCabwtPlXBEc_7AUjEMyisTeXjetG2-9fPluxu2QSJGEQsjuc-MMwDEf9cRDeZZMw9YasTweDvp-GqT-IgyTwEpaGA8aCkPl3fEI9Gvi-3_cHfjAIe8zz_T7SlAaMjf3hiPQ9zBkXPZejPaX3d9yYAicjSoejO8F2KEx5l6RU4gnKSUKpu1rqSZnXu2JvSN8T3FjToVhuBU7I0Pv9I_TQgzYb6yvi1c2Qy-rSV14Pv0QvX121S_m-0GUnvCu0mGTWHozTUu6-PbdZsevFKnf7Thybx9luLF0yhC5Kl_8bAAD__wcwdNM">