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

Reliable way to programmatically get the number of hardware threads on Windows

本文关键字:方法 线程 硬件 方式 编程 获取 Windows      更新时间:2023-10-16

我正在努力寻找一种可靠的方法来获得Windows上硬件线程的数量。我在一台双CPU Intel Xeon E5-2699 v3@2.30GHz的机器上运行Windows 7 Professional SP1 64位,总共有36个内核和72个线程。我尝试了不同的方法来获得内核的数量,我发现在32位或64位进程中,似乎只有两种方法能准确工作。以下是我的结果:

+------------------------------------------------+----------------+----------------+|方法|32位进程|64位进程|+------------------------------------------------+----------------+----------------+|GetSystemInfo->dwNumberOfProcessors|32|36||GetNativeSystemInfo->dwNumberOfProcessors|36|36||获取逻辑处理器信息|36|36||GetProcessAffinityMask.ProcessAffinity Mask|32|32||GetProcessAffinityMask.SystemAffinityMusk|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||性能计数器API | 36 | 36||WMI|72|72||硬件\描述\系统\中央处理器|72|72|+------------------------------------------------+----------------+----------------+

我不解释为什么所有这些函数都返回不同的值。对我来说,唯一可靠的两种方法要么是使用WMI(但相当复杂(,要么只是在Windows注册表中读取以下项:硬件\描述\系统\中央处理器。

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

提前感谢

您需要的API函数是GetLogicalProcessorInformationEx。由于您有超过64个处理器,因此会对您的处理器进行分组。GetLogicalProcessorInformation仅报告当前分配线程的处理器组中的处理器。您需要使用GetLogicalProcessorInformationEx来克服这个限制。

文件上写着:

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

代码为的延迟回答

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;}

它在我的双Xeon gold 6154上运行,带有Windows 64位系统(2个进程*18个内核/proc*2个线程/core=72个线程(。对于32位处理和64位处理,结果都是72。

不过,我无法访问带有32位Windows的系统。

如果出现错误,它会像std::thread::hardware_concurrency一样返回零。

您可以使用CPUID指令直接查询处理器(独立于平台,但由于某些编译器不能再在MSVC中执行内联asm,因此需要使用不同的函数才能访问它(。唯一的缺点是,几年前,英特尔和AMD对该指令的处理方式有所不同,您需要做大量工作来确保正确读取信息。事实上,您不仅可以获得核心计数,还可以获得各种处理器拓扑信息。如果您使用的是虚拟机环境,则不确定它在虚拟机中是如何工作的。