以可编程方式获取Windows上硬件线程数的可靠方法

时间:2015-07-03 14:33:59

标签: c++ windows multithreading winapi

我很难找到一种可靠的方法来获取Windows上的硬件线程数量。我在具有双CPU Intel Xeon E5-2699 v3 @ 2.30GHz的计算机上运行Windows 7 Professional SP1 64位,共计36个内核和72个线程。 我已经尝试了不同的方法来获取内核的数量,我发现其中只有两个似乎在32位或64位进程中准确工作。以下是我的结果:

+------------------------------------------------+----------------+----------------+
|                    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 |
| HARDWARE\DESCRIPTION\System\CentralProcessor   |             72 |             72 |
+------------------------------------------------+----------------+----------------+

我不解释为什么所有这些函数都返回不同的值。对我来说唯一可靠的两种方法是使用WMI(但相当复杂)或者只是在Windows注册表中读取以下密钥:HARDWARE \ DESCRIPTION \ System \ CentralProcessor。

你怎么看? 您确认WMI和注册表项方法是唯一可靠的方法吗?

提前致谢

3 个答案:

答案 0 :(得分:8)

您需要的API函数是GetLogicalProcessorInformationEx。由于您拥有超过64个处理器,因此您的处理器已分组。 GetLogicalProcessorInformation仅报告当前分配线程的处理器组中的处理器。您需要使用GetLogicalProcessorInformationEx来超越该限制。

documentation说:

  

在具有超过64个逻辑处理器的系统上,GetLogicalProcessorInformation函数检索有关当前为其分配调用线程的处理器组中的处理器的逻辑处理器信息。使用GetLogicalProcessorInformationEx函数检索有关系统上所有处理器组中处理器的信息。

答案 1 :(得分:0)

您可以使用CPUID指令直接查询处理器(与平台无关,但由于您无法在某些编译器中对MSVC进行内联asm,因此您需要使用不同的函数来访问它)。唯一的缺点是,几年前英特尔和AMD以不同的方式处理此指令,您需要做很多工作以确保您正确地阅读信息。实际上,您不仅可以获得核心数,还可以获得各种处理器拓扑信息。如果您正在使用该环境,则不确定它在VM中的工作原理。

答案 2 :(得分:0)

最新答案和代码:

DbParameter para = new SqlParameter("search", "%"+searchfor+"%");
IQueryable<VwSomeView> dbresult = db.vwSomeView.FromSql($"select * from vwSomeView where firstname like @search or lastname like @search",para);

它在装有Windows 64位系统的双Xeon gold 6154上工作(2个进程* 18个内核/进程* 2个线程/内核= 72个线程)。对于32位进程和64位进程,结果均为72。

虽然我无法访问具有32位Windows的系统。

如果发生错误,它会像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;} 一样返回零。