Reliable way to programmatically get the number of hardware threads on Windows
I'm struggling to find a reliable way to get the number of hardware threads on Windows. I am running a Windows 7 Professional SP1 64-bit on a machine with dual CPU Intel Xeon E5-2699 v3 @ 2.30GHz totalizing 36 cores and 72 threads.
I have tried different methods to get the number of cores, and I have found that only two of them seem to work accurately in a 32-bit or 64-bit process. Here are my results:
+------------------------------------------------+----------------+----------------+
| Methods | 32-bit process | 64-bit process |
+------------------------------------------------+----------------+----------------+
| GetSystemInfo->dwNumberOfProcessors | 32 | 36 |
| GetNativeSystemInfo->dwNumberOfProcessors | 36 | 36 |
| GetLogicalProcessorInformation | 36 | 36 |
| GetProcessAffinityMask.processAffinityMask | 32 | 32 |
| GetProcessAffinityMask.systemAffinityMask | 32 | 32 |
| omp_get_num_procs | 32 | 36 |
| getenv("NUMBER_OF_PROCESSORS") | 36 | 36 |
| GetActiveProcessorCount(ALL_PROCESSOR_GROUPS) | 64 | 72 |
| GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS) | 64 | 72 |
| boost::thread::hardware_concurrency() | 32 | 36 |
| Performance counter API | 36 | 36 |
| WMI | 72 | 72 |
| HARDWAREDESCRIPTIONSystemCentralProcessor | 72 | 72 |
+------------------------------------------------+----------------+----------------+
I do not explain why all these functions return different values. The only 2 methods which seem reliable to me is either using WMI (but fairly complicated) or simply to read in the Windows registry the following key: HARDWAREDESCRIPTIONSystemCentralProcessor.
What do you think?
Do you confirm that the WMI and registry key methods are the only reliable methods?
Thanks in advance
c++ windows multithreading winapi
add a comment |
I'm struggling to find a reliable way to get the number of hardware threads on Windows. I am running a Windows 7 Professional SP1 64-bit on a machine with dual CPU Intel Xeon E5-2699 v3 @ 2.30GHz totalizing 36 cores and 72 threads.
I have tried different methods to get the number of cores, and I have found that only two of them seem to work accurately in a 32-bit or 64-bit process. Here are my results:
+------------------------------------------------+----------------+----------------+
| Methods | 32-bit process | 64-bit process |
+------------------------------------------------+----------------+----------------+
| GetSystemInfo->dwNumberOfProcessors | 32 | 36 |
| GetNativeSystemInfo->dwNumberOfProcessors | 36 | 36 |
| GetLogicalProcessorInformation | 36 | 36 |
| GetProcessAffinityMask.processAffinityMask | 32 | 32 |
| GetProcessAffinityMask.systemAffinityMask | 32 | 32 |
| omp_get_num_procs | 32 | 36 |
| getenv("NUMBER_OF_PROCESSORS") | 36 | 36 |
| GetActiveProcessorCount(ALL_PROCESSOR_GROUPS) | 64 | 72 |
| GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS) | 64 | 72 |
| boost::thread::hardware_concurrency() | 32 | 36 |
| Performance counter API | 36 | 36 |
| WMI | 72 | 72 |
| HARDWAREDESCRIPTIONSystemCentralProcessor | 72 | 72 |
+------------------------------------------------+----------------+----------------+
I do not explain why all these functions return different values. The only 2 methods which seem reliable to me is either using WMI (but fairly complicated) or simply to read in the Windows registry the following key: HARDWAREDESCRIPTIONSystemCentralProcessor.
What do you think?
Do you confirm that the WMI and registry key methods are the only reliable methods?
Thanks in advance
c++ windows multithreading winapi
You get however many you can effectively use in your program. Sure, WMI is never the wrong way to do this.
– Hans Passant
Jul 3 '15 at 14:37
add a comment |
I'm struggling to find a reliable way to get the number of hardware threads on Windows. I am running a Windows 7 Professional SP1 64-bit on a machine with dual CPU Intel Xeon E5-2699 v3 @ 2.30GHz totalizing 36 cores and 72 threads.
I have tried different methods to get the number of cores, and I have found that only two of them seem to work accurately in a 32-bit or 64-bit process. Here are my results:
+------------------------------------------------+----------------+----------------+
| Methods | 32-bit process | 64-bit process |
+------------------------------------------------+----------------+----------------+
| GetSystemInfo->dwNumberOfProcessors | 32 | 36 |
| GetNativeSystemInfo->dwNumberOfProcessors | 36 | 36 |
| GetLogicalProcessorInformation | 36 | 36 |
| GetProcessAffinityMask.processAffinityMask | 32 | 32 |
| GetProcessAffinityMask.systemAffinityMask | 32 | 32 |
| omp_get_num_procs | 32 | 36 |
| getenv("NUMBER_OF_PROCESSORS") | 36 | 36 |
| GetActiveProcessorCount(ALL_PROCESSOR_GROUPS) | 64 | 72 |
| GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS) | 64 | 72 |
| boost::thread::hardware_concurrency() | 32 | 36 |
| Performance counter API | 36 | 36 |
| WMI | 72 | 72 |
| HARDWAREDESCRIPTIONSystemCentralProcessor | 72 | 72 |
+------------------------------------------------+----------------+----------------+
I do not explain why all these functions return different values. The only 2 methods which seem reliable to me is either using WMI (but fairly complicated) or simply to read in the Windows registry the following key: HARDWAREDESCRIPTIONSystemCentralProcessor.
What do you think?
Do you confirm that the WMI and registry key methods are the only reliable methods?
Thanks in advance
c++ windows multithreading winapi
I'm struggling to find a reliable way to get the number of hardware threads on Windows. I am running a Windows 7 Professional SP1 64-bit on a machine with dual CPU Intel Xeon E5-2699 v3 @ 2.30GHz totalizing 36 cores and 72 threads.
I have tried different methods to get the number of cores, and I have found that only two of them seem to work accurately in a 32-bit or 64-bit process. Here are my results:
+------------------------------------------------+----------------+----------------+
| Methods | 32-bit process | 64-bit process |
+------------------------------------------------+----------------+----------------+
| GetSystemInfo->dwNumberOfProcessors | 32 | 36 |
| GetNativeSystemInfo->dwNumberOfProcessors | 36 | 36 |
| GetLogicalProcessorInformation | 36 | 36 |
| GetProcessAffinityMask.processAffinityMask | 32 | 32 |
| GetProcessAffinityMask.systemAffinityMask | 32 | 32 |
| omp_get_num_procs | 32 | 36 |
| getenv("NUMBER_OF_PROCESSORS") | 36 | 36 |
| GetActiveProcessorCount(ALL_PROCESSOR_GROUPS) | 64 | 72 |
| GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS) | 64 | 72 |
| boost::thread::hardware_concurrency() | 32 | 36 |
| Performance counter API | 36 | 36 |
| WMI | 72 | 72 |
| HARDWAREDESCRIPTIONSystemCentralProcessor | 72 | 72 |
+------------------------------------------------+----------------+----------------+
I do not explain why all these functions return different values. The only 2 methods which seem reliable to me is either using WMI (but fairly complicated) or simply to read in the Windows registry the following key: HARDWAREDESCRIPTIONSystemCentralProcessor.
What do you think?
Do you confirm that the WMI and registry key methods are the only reliable methods?
Thanks in advance
c++ windows multithreading winapi
c++ windows multithreading winapi
edited Nov 13 '18 at 18:03
Arnaud
2,28122751
2,28122751
asked Jul 3 '15 at 14:33
benben
411
411
You get however many you can effectively use in your program. Sure, WMI is never the wrong way to do this.
– Hans Passant
Jul 3 '15 at 14:37
add a comment |
You get however many you can effectively use in your program. Sure, WMI is never the wrong way to do this.
– Hans Passant
Jul 3 '15 at 14:37
You get however many you can effectively use in your program. Sure, WMI is never the wrong way to do this.
– Hans Passant
Jul 3 '15 at 14:37
You get however many you can effectively use in your program. Sure, WMI is never the wrong way to do this.
– Hans Passant
Jul 3 '15 at 14:37
add a comment |
3 Answers
3
active
oldest
votes
The API function that you need is GetLogicalProcessorInformationEx
. Since you have more than 64 processors, your processors are grouped. GetLogicalProcessorInformation
only reports the processors in the processor group that the thread is currently assigned. You need to use GetLogicalProcessorInformationEx
to get past that limitation.
The documentation says:
On systems with more than 64 logical processors, the GetLogicalProcessorInformation function retrieves logical processor information about processors in the processor group to which the calling thread is currently assigned. Use the GetLogicalProcessorInformationEx function to retrieve information about processors in all processor groups on the system.
add a comment |
You can use the CPUID instruction to query the processor directly (platform independent, though since you can't do inline asm in MSVC anymore for some compilers you'll need to use different functions to have access to it). The only downside is that as of a few years ago Intel and AMD handle this instruction differently, and you'll need to do a lot of work to ensure you are reading the information correctly. In fact, not only will you be able to get a core count, but you can get all kinds of processor topology information. Not sure how it works in a VM though if you are using that environment.
CPUID is hardly platform independent. You yourself note that it doesn't always behave right, and you completely ignore other processors like ARM.
– Raymond Chen
Jul 3 '15 at 18:51
add a comment |
Late answer with code:
size_t myHardwareConcurrency()
size_t concurrency=0;
DWORD length=0;
if(GetLogicalProcessorInformationEx(RelationAll,nullptr,&length)!=FALSE)
return concurrency;
if(GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
return concurrency;
std::unique_ptr<void,void(*)(void*)>buffer(std::malloc(length),std::free);
if(!buffer)
return concurrency;
unsigned char*mem=reinterpret_cast<unsigned char*>(buffer.get());
if(GetLogicalProcessorInformationEx(RelationAll,reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX>(mem),&length)==false)
return concurrency;
for(DWORD i=0;i<length;)
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 concurrency;
It worked on my dual Xeon gold 6154 with Windows 64 bit system (2 procs * 18 cores/proc * 2 threads/core = 72 threads). The result is 72 both for 32 bit processes and for 64 bit processes.
I do not have access to a system with a 32 bit Windows though.
In case of error, it returns zero like std::thread::hardware_concurrency
does.
According to MSDN you would just need to count the number of occurrences ofRelationProcessorCore
so the counting loop can be simplified to:if (proc->Relationship==RelationProcessorCore) ++concurrency;
. This is because the number of groups a core belongs to is always 1 and the mask only contains a single bit denoting the position (or affinity) in that group. I guess it would also make counting under WoW64 emulation more robust...
– klaus triendl
Nov 13 '18 at 16:46
@klaustriendl I just edited the OP question to make a clear distinction between number of cores and number of threads. Although he used the word cores all along, the number he gave were for the number of hardware threads. Your suggestion would be correct to get the number of core, but the OP wanted the number of threads.
– Arnaud
Nov 13 '18 at 18:05
Thx @Arnaud Still you wouldn't have to loop through the groups as the group count is always 1. Anyway, to me the "number of active processor cores" was equivalent to the "number of logical processors", but reading further onPROCESSOR_RELATIONSHIP
I understand that a core can have more than 1 logical processor. What happens under Wow64? Is the mask for logical processors 32 through 63 correct? Because the remarks state that it's incorrectly represented as duplicates for 0-31... (I guess for your specific machine these would be logical processors 32-35 of cores number 17+18?
– klaus triendl
Nov 13 '18 at 19:14
@klaustriendl On my machine (6 cores 12 threads 3930K), in x64 modeproc->Processor.GroupMask[0].Mask
is 3 and I need to add 2 for eachRelationProcessorCore
– Arnaud
Nov 13 '18 at 21:45
What do you mean exactly by x64 mode? Is it the 32-bit executable on a 64-bit OS, i.e. WoW64?
– klaus triendl
Nov 14 '18 at 8:35
|
show 2 more comments
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f31209256%2freliable-way-to-programmatically-get-the-number-of-hardware-threads-on-windows%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
The API function that you need is GetLogicalProcessorInformationEx
. Since you have more than 64 processors, your processors are grouped. GetLogicalProcessorInformation
only reports the processors in the processor group that the thread is currently assigned. You need to use GetLogicalProcessorInformationEx
to get past that limitation.
The documentation says:
On systems with more than 64 logical processors, the GetLogicalProcessorInformation function retrieves logical processor information about processors in the processor group to which the calling thread is currently assigned. Use the GetLogicalProcessorInformationEx function to retrieve information about processors in all processor groups on the system.
add a comment |
The API function that you need is GetLogicalProcessorInformationEx
. Since you have more than 64 processors, your processors are grouped. GetLogicalProcessorInformation
only reports the processors in the processor group that the thread is currently assigned. You need to use GetLogicalProcessorInformationEx
to get past that limitation.
The documentation says:
On systems with more than 64 logical processors, the GetLogicalProcessorInformation function retrieves logical processor information about processors in the processor group to which the calling thread is currently assigned. Use the GetLogicalProcessorInformationEx function to retrieve information about processors in all processor groups on the system.
add a comment |
The API function that you need is GetLogicalProcessorInformationEx
. Since you have more than 64 processors, your processors are grouped. GetLogicalProcessorInformation
only reports the processors in the processor group that the thread is currently assigned. You need to use GetLogicalProcessorInformationEx
to get past that limitation.
The documentation says:
On systems with more than 64 logical processors, the GetLogicalProcessorInformation function retrieves logical processor information about processors in the processor group to which the calling thread is currently assigned. Use the GetLogicalProcessorInformationEx function to retrieve information about processors in all processor groups on the system.
The API function that you need is GetLogicalProcessorInformationEx
. Since you have more than 64 processors, your processors are grouped. GetLogicalProcessorInformation
only reports the processors in the processor group that the thread is currently assigned. You need to use GetLogicalProcessorInformationEx
to get past that limitation.
The documentation says:
On systems with more than 64 logical processors, the GetLogicalProcessorInformation function retrieves logical processor information about processors in the processor group to which the calling thread is currently assigned. Use the GetLogicalProcessorInformationEx function to retrieve information about processors in all processor groups on the system.
answered Jul 3 '15 at 14:38
David HeffernanDavid Heffernan
519k348221214
519k348221214
add a comment |
add a comment |
You can use the CPUID instruction to query the processor directly (platform independent, though since you can't do inline asm in MSVC anymore for some compilers you'll need to use different functions to have access to it). The only downside is that as of a few years ago Intel and AMD handle this instruction differently, and you'll need to do a lot of work to ensure you are reading the information correctly. In fact, not only will you be able to get a core count, but you can get all kinds of processor topology information. Not sure how it works in a VM though if you are using that environment.
CPUID is hardly platform independent. You yourself note that it doesn't always behave right, and you completely ignore other processors like ARM.
– Raymond Chen
Jul 3 '15 at 18:51
add a comment |
You can use the CPUID instruction to query the processor directly (platform independent, though since you can't do inline asm in MSVC anymore for some compilers you'll need to use different functions to have access to it). The only downside is that as of a few years ago Intel and AMD handle this instruction differently, and you'll need to do a lot of work to ensure you are reading the information correctly. In fact, not only will you be able to get a core count, but you can get all kinds of processor topology information. Not sure how it works in a VM though if you are using that environment.
CPUID is hardly platform independent. You yourself note that it doesn't always behave right, and you completely ignore other processors like ARM.
– Raymond Chen
Jul 3 '15 at 18:51
add a comment |
You can use the CPUID instruction to query the processor directly (platform independent, though since you can't do inline asm in MSVC anymore for some compilers you'll need to use different functions to have access to it). The only downside is that as of a few years ago Intel and AMD handle this instruction differently, and you'll need to do a lot of work to ensure you are reading the information correctly. In fact, not only will you be able to get a core count, but you can get all kinds of processor topology information. Not sure how it works in a VM though if you are using that environment.
You can use the CPUID instruction to query the processor directly (platform independent, though since you can't do inline asm in MSVC anymore for some compilers you'll need to use different functions to have access to it). The only downside is that as of a few years ago Intel and AMD handle this instruction differently, and you'll need to do a lot of work to ensure you are reading the information correctly. In fact, not only will you be able to get a core count, but you can get all kinds of processor topology information. Not sure how it works in a VM though if you are using that environment.
answered Jul 3 '15 at 15:07
RyanPRyanP
1,7411018
1,7411018
CPUID is hardly platform independent. You yourself note that it doesn't always behave right, and you completely ignore other processors like ARM.
– Raymond Chen
Jul 3 '15 at 18:51
add a comment |
CPUID is hardly platform independent. You yourself note that it doesn't always behave right, and you completely ignore other processors like ARM.
– Raymond Chen
Jul 3 '15 at 18:51
CPUID is hardly platform independent. You yourself note that it doesn't always behave right, and you completely ignore other processors like ARM.
– Raymond Chen
Jul 3 '15 at 18:51
CPUID is hardly platform independent. You yourself note that it doesn't always behave right, and you completely ignore other processors like ARM.
– Raymond Chen
Jul 3 '15 at 18:51
add a comment |
Late answer with code:
size_t myHardwareConcurrency()
size_t concurrency=0;
DWORD length=0;
if(GetLogicalProcessorInformationEx(RelationAll,nullptr,&length)!=FALSE)
return concurrency;
if(GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
return concurrency;
std::unique_ptr<void,void(*)(void*)>buffer(std::malloc(length),std::free);
if(!buffer)
return concurrency;
unsigned char*mem=reinterpret_cast<unsigned char*>(buffer.get());
if(GetLogicalProcessorInformationEx(RelationAll,reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX>(mem),&length)==false)
return concurrency;
for(DWORD i=0;i<length;)
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 concurrency;
It worked on my dual Xeon gold 6154 with Windows 64 bit system (2 procs * 18 cores/proc * 2 threads/core = 72 threads). The result is 72 both for 32 bit processes and for 64 bit processes.
I do not have access to a system with a 32 bit Windows though.
In case of error, it returns zero like std::thread::hardware_concurrency
does.
According to MSDN you would just need to count the number of occurrences ofRelationProcessorCore
so the counting loop can be simplified to:if (proc->Relationship==RelationProcessorCore) ++concurrency;
. This is because the number of groups a core belongs to is always 1 and the mask only contains a single bit denoting the position (or affinity) in that group. I guess it would also make counting under WoW64 emulation more robust...
– klaus triendl
Nov 13 '18 at 16:46
@klaustriendl I just edited the OP question to make a clear distinction between number of cores and number of threads. Although he used the word cores all along, the number he gave were for the number of hardware threads. Your suggestion would be correct to get the number of core, but the OP wanted the number of threads.
– Arnaud
Nov 13 '18 at 18:05
Thx @Arnaud Still you wouldn't have to loop through the groups as the group count is always 1. Anyway, to me the "number of active processor cores" was equivalent to the "number of logical processors", but reading further onPROCESSOR_RELATIONSHIP
I understand that a core can have more than 1 logical processor. What happens under Wow64? Is the mask for logical processors 32 through 63 correct? Because the remarks state that it's incorrectly represented as duplicates for 0-31... (I guess for your specific machine these would be logical processors 32-35 of cores number 17+18?
– klaus triendl
Nov 13 '18 at 19:14
@klaustriendl On my machine (6 cores 12 threads 3930K), in x64 modeproc->Processor.GroupMask[0].Mask
is 3 and I need to add 2 for eachRelationProcessorCore
– Arnaud
Nov 13 '18 at 21:45
What do you mean exactly by x64 mode? Is it the 32-bit executable on a 64-bit OS, i.e. WoW64?
– klaus triendl
Nov 14 '18 at 8:35
|
show 2 more comments
Late answer with code:
size_t myHardwareConcurrency()
size_t concurrency=0;
DWORD length=0;
if(GetLogicalProcessorInformationEx(RelationAll,nullptr,&length)!=FALSE)
return concurrency;
if(GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
return concurrency;
std::unique_ptr<void,void(*)(void*)>buffer(std::malloc(length),std::free);
if(!buffer)
return concurrency;
unsigned char*mem=reinterpret_cast<unsigned char*>(buffer.get());
if(GetLogicalProcessorInformationEx(RelationAll,reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX>(mem),&length)==false)
return concurrency;
for(DWORD i=0;i<length;)
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 concurrency;
It worked on my dual Xeon gold 6154 with Windows 64 bit system (2 procs * 18 cores/proc * 2 threads/core = 72 threads). The result is 72 both for 32 bit processes and for 64 bit processes.
I do not have access to a system with a 32 bit Windows though.
In case of error, it returns zero like std::thread::hardware_concurrency
does.
According to MSDN you would just need to count the number of occurrences ofRelationProcessorCore
so the counting loop can be simplified to:if (proc->Relationship==RelationProcessorCore) ++concurrency;
. This is because the number of groups a core belongs to is always 1 and the mask only contains a single bit denoting the position (or affinity) in that group. I guess it would also make counting under WoW64 emulation more robust...
– klaus triendl
Nov 13 '18 at 16:46
@klaustriendl I just edited the OP question to make a clear distinction between number of cores and number of threads. Although he used the word cores all along, the number he gave were for the number of hardware threads. Your suggestion would be correct to get the number of core, but the OP wanted the number of threads.
– Arnaud
Nov 13 '18 at 18:05
Thx @Arnaud Still you wouldn't have to loop through the groups as the group count is always 1. Anyway, to me the "number of active processor cores" was equivalent to the "number of logical processors", but reading further onPROCESSOR_RELATIONSHIP
I understand that a core can have more than 1 logical processor. What happens under Wow64? Is the mask for logical processors 32 through 63 correct? Because the remarks state that it's incorrectly represented as duplicates for 0-31... (I guess for your specific machine these would be logical processors 32-35 of cores number 17+18?
– klaus triendl
Nov 13 '18 at 19:14
@klaustriendl On my machine (6 cores 12 threads 3930K), in x64 modeproc->Processor.GroupMask[0].Mask
is 3 and I need to add 2 for eachRelationProcessorCore
– Arnaud
Nov 13 '18 at 21:45
What do you mean exactly by x64 mode? Is it the 32-bit executable on a 64-bit OS, i.e. WoW64?
– klaus triendl
Nov 14 '18 at 8:35
|
show 2 more comments
Late answer with code:
size_t myHardwareConcurrency()
size_t concurrency=0;
DWORD length=0;
if(GetLogicalProcessorInformationEx(RelationAll,nullptr,&length)!=FALSE)
return concurrency;
if(GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
return concurrency;
std::unique_ptr<void,void(*)(void*)>buffer(std::malloc(length),std::free);
if(!buffer)
return concurrency;
unsigned char*mem=reinterpret_cast<unsigned char*>(buffer.get());
if(GetLogicalProcessorInformationEx(RelationAll,reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX>(mem),&length)==false)
return concurrency;
for(DWORD i=0;i<length;)
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 concurrency;
It worked on my dual Xeon gold 6154 with Windows 64 bit system (2 procs * 18 cores/proc * 2 threads/core = 72 threads). The result is 72 both for 32 bit processes and for 64 bit processes.
I do not have access to a system with a 32 bit Windows though.
In case of error, it returns zero like std::thread::hardware_concurrency
does.
Late answer with code:
size_t myHardwareConcurrency()
size_t concurrency=0;
DWORD length=0;
if(GetLogicalProcessorInformationEx(RelationAll,nullptr,&length)!=FALSE)
return concurrency;
if(GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
return concurrency;
std::unique_ptr<void,void(*)(void*)>buffer(std::malloc(length),std::free);
if(!buffer)
return concurrency;
unsigned char*mem=reinterpret_cast<unsigned char*>(buffer.get());
if(GetLogicalProcessorInformationEx(RelationAll,reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX>(mem),&length)==false)
return concurrency;
for(DWORD i=0;i<length;)
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 concurrency;
It worked on my dual Xeon gold 6154 with Windows 64 bit system (2 procs * 18 cores/proc * 2 threads/core = 72 threads). The result is 72 both for 32 bit processes and for 64 bit processes.
I do not have access to a system with a 32 bit Windows though.
In case of error, it returns zero like std::thread::hardware_concurrency
does.
edited Nov 14 '18 at 10:53
answered Oct 9 '18 at 8:03
ArnaudArnaud
2,28122751
2,28122751
According to MSDN you would just need to count the number of occurrences ofRelationProcessorCore
so the counting loop can be simplified to:if (proc->Relationship==RelationProcessorCore) ++concurrency;
. This is because the number of groups a core belongs to is always 1 and the mask only contains a single bit denoting the position (or affinity) in that group. I guess it would also make counting under WoW64 emulation more robust...
– klaus triendl
Nov 13 '18 at 16:46
@klaustriendl I just edited the OP question to make a clear distinction between number of cores and number of threads. Although he used the word cores all along, the number he gave were for the number of hardware threads. Your suggestion would be correct to get the number of core, but the OP wanted the number of threads.
– Arnaud
Nov 13 '18 at 18:05
Thx @Arnaud Still you wouldn't have to loop through the groups as the group count is always 1. Anyway, to me the "number of active processor cores" was equivalent to the "number of logical processors", but reading further onPROCESSOR_RELATIONSHIP
I understand that a core can have more than 1 logical processor. What happens under Wow64? Is the mask for logical processors 32 through 63 correct? Because the remarks state that it's incorrectly represented as duplicates for 0-31... (I guess for your specific machine these would be logical processors 32-35 of cores number 17+18?
– klaus triendl
Nov 13 '18 at 19:14
@klaustriendl On my machine (6 cores 12 threads 3930K), in x64 modeproc->Processor.GroupMask[0].Mask
is 3 and I need to add 2 for eachRelationProcessorCore
– Arnaud
Nov 13 '18 at 21:45
What do you mean exactly by x64 mode? Is it the 32-bit executable on a 64-bit OS, i.e. WoW64?
– klaus triendl
Nov 14 '18 at 8:35
|
show 2 more comments
According to MSDN you would just need to count the number of occurrences ofRelationProcessorCore
so the counting loop can be simplified to:if (proc->Relationship==RelationProcessorCore) ++concurrency;
. This is because the number of groups a core belongs to is always 1 and the mask only contains a single bit denoting the position (or affinity) in that group. I guess it would also make counting under WoW64 emulation more robust...
– klaus triendl
Nov 13 '18 at 16:46
@klaustriendl I just edited the OP question to make a clear distinction between number of cores and number of threads. Although he used the word cores all along, the number he gave were for the number of hardware threads. Your suggestion would be correct to get the number of core, but the OP wanted the number of threads.
– Arnaud
Nov 13 '18 at 18:05
Thx @Arnaud Still you wouldn't have to loop through the groups as the group count is always 1. Anyway, to me the "number of active processor cores" was equivalent to the "number of logical processors", but reading further onPROCESSOR_RELATIONSHIP
I understand that a core can have more than 1 logical processor. What happens under Wow64? Is the mask for logical processors 32 through 63 correct? Because the remarks state that it's incorrectly represented as duplicates for 0-31... (I guess for your specific machine these would be logical processors 32-35 of cores number 17+18?
– klaus triendl
Nov 13 '18 at 19:14
@klaustriendl On my machine (6 cores 12 threads 3930K), in x64 modeproc->Processor.GroupMask[0].Mask
is 3 and I need to add 2 for eachRelationProcessorCore
– Arnaud
Nov 13 '18 at 21:45
What do you mean exactly by x64 mode? Is it the 32-bit executable on a 64-bit OS, i.e. WoW64?
– klaus triendl
Nov 14 '18 at 8:35
According to MSDN you would just need to count the number of occurrences of
RelationProcessorCore
so the counting loop can be simplified to: if (proc->Relationship==RelationProcessorCore) ++concurrency;
. This is because the number of groups a core belongs to is always 1 and the mask only contains a single bit denoting the position (or affinity) in that group. I guess it would also make counting under WoW64 emulation more robust...– klaus triendl
Nov 13 '18 at 16:46
According to MSDN you would just need to count the number of occurrences of
RelationProcessorCore
so the counting loop can be simplified to: if (proc->Relationship==RelationProcessorCore) ++concurrency;
. This is because the number of groups a core belongs to is always 1 and the mask only contains a single bit denoting the position (or affinity) in that group. I guess it would also make counting under WoW64 emulation more robust...– klaus triendl
Nov 13 '18 at 16:46
@klaustriendl I just edited the OP question to make a clear distinction between number of cores and number of threads. Although he used the word cores all along, the number he gave were for the number of hardware threads. Your suggestion would be correct to get the number of core, but the OP wanted the number of threads.
– Arnaud
Nov 13 '18 at 18:05
@klaustriendl I just edited the OP question to make a clear distinction between number of cores and number of threads. Although he used the word cores all along, the number he gave were for the number of hardware threads. Your suggestion would be correct to get the number of core, but the OP wanted the number of threads.
– Arnaud
Nov 13 '18 at 18:05
Thx @Arnaud Still you wouldn't have to loop through the groups as the group count is always 1. Anyway, to me the "number of active processor cores" was equivalent to the "number of logical processors", but reading further on
PROCESSOR_RELATIONSHIP
I understand that a core can have more than 1 logical processor. What happens under Wow64? Is the mask for logical processors 32 through 63 correct? Because the remarks state that it's incorrectly represented as duplicates for 0-31... (I guess for your specific machine these would be logical processors 32-35 of cores number 17+18?– klaus triendl
Nov 13 '18 at 19:14
Thx @Arnaud Still you wouldn't have to loop through the groups as the group count is always 1. Anyway, to me the "number of active processor cores" was equivalent to the "number of logical processors", but reading further on
PROCESSOR_RELATIONSHIP
I understand that a core can have more than 1 logical processor. What happens under Wow64? Is the mask for logical processors 32 through 63 correct? Because the remarks state that it's incorrectly represented as duplicates for 0-31... (I guess for your specific machine these would be logical processors 32-35 of cores number 17+18?– klaus triendl
Nov 13 '18 at 19:14
@klaustriendl On my machine (6 cores 12 threads 3930K), in x64 mode
proc->Processor.GroupMask[0].Mask
is 3 and I need to add 2 for each RelationProcessorCore
– Arnaud
Nov 13 '18 at 21:45
@klaustriendl On my machine (6 cores 12 threads 3930K), in x64 mode
proc->Processor.GroupMask[0].Mask
is 3 and I need to add 2 for each RelationProcessorCore
– Arnaud
Nov 13 '18 at 21:45
What do you mean exactly by x64 mode? Is it the 32-bit executable on a 64-bit OS, i.e. WoW64?
– klaus triendl
Nov 14 '18 at 8:35
What do you mean exactly by x64 mode? Is it the 32-bit executable on a 64-bit OS, i.e. WoW64?
– klaus triendl
Nov 14 '18 at 8:35
|
show 2 more comments
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f31209256%2freliable-way-to-programmatically-get-the-number-of-hardware-threads-on-windows%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
You get however many you can effectively use in your program. Sure, WMI is never the wrong way to do this.
– Hans Passant
Jul 3 '15 at 14:37