zoukankan      html  css  js  c++  java
  • 使用GetLogicalProcessorInformation获取逻辑处理器的详细信息(NUMA节点数、物理CPU数、CPU核心数、逻辑CPU数、各级Cache)

    不过必须XP SP3以上才行。所有API大全:

    https://msdn.microsoft.com/en-us/library/windows/desktop/aa363804(v=vs.85).aspx

    --------------------------------------------------------------------------------

    现在多核处理器已经很普及了,市场主流是双核处理器,还有4核、8核等高端产品。而且Intel推广了超线程技术(Hyper-Threading Technology, HTT),可以将一个物理核心模拟为两个逻辑处理器。这一切使得“CPU数量”这一概念变得复杂起来,对于软件开发人员来说,希望能获得物理CPU数、CPU核心数、逻辑CPU数等详细信息。
      在Windows平台,可以调用GetLogicalProcessorInformation函数来获取它们的详细信息。


    一、背景知识

      先来明确一下名词——
    physical processor packages:物理处理器封装个数,即俗称的“物理CPU数”。例如一块“Intel Core i3-2310M”只有1个“物理处理器封装个数”。若对于有多个处理器插槽的服务器,“物理处理器封装个数”很可能会大于1。
    processor cores:处理器核心数,即俗称的“CPU核心数”。例如“Intel Core i3-2310M”是双核处理器,它有2个“处理器核心数”。
    logical processors:逻辑处理器数,即俗称的“逻辑CPU数”。例如“Intel Core i3-2310M”支持超线程,一个物理核心能模拟为两个逻辑处理器,即一块“Intel Core i3-2310M”有4个“逻辑处理器数”。

      再来看看2个大家可能不太熟悉的名词——
    SMP:Symmetrical Multi-Processing,对称多处理机。
    NUMA:Non Uniform Memory Access,非均匀访存模型。http://msdn.microsoft.com/en-us/library/aa363804(v=vs.85).aspx

      这个两个名词牵涉到很多专业知识,这里不做详细介绍,感兴趣的同学可以自行翻阅相关资料。
      老版本的Windows系统(例如Windows XP)采用的是SMP模型。但后来因多核处理器及异构计算的发展,从Windows Server 2003开始使用NUMA模型,系统中支持多个NUMA节点。对于开发人员来说,当只有1个NUMA节点时,与SMP模型是差不多的。
      对于 Windows XP,在打上SP3补丁后,也可以利用GetLogicalProcessorInformation函数获得NUMA等信息。


    二、GetLogicalProcessorInformation函数的使用心得

      在MSDN上我们可以查到GetLogicalProcessorInformation函数的帮助——
    http://msdn.microsoft.com/en-us/library/ms683194(v=vs.85).aspx
    GetLogicalProcessorInformation function

      GetLogicalProcessorInformation函数还牵涉到一些结构体和枚举——
    http://msdn.microsoft.com/en-us/library/ms686694(v=vs.85).aspx
    SYSTEM_LOGICAL_PROCESSOR_INFORMATION structure

    http://msdn.microsoft.com/en-us/library/ms684197(v=vs.85).aspx
    LOGICAL_PROCESSOR_RELATIONSHIP enumeration

    http://msdn.microsoft.com/en-us/library/ms681979(v=vs.85).aspx
    CACHE_DESCRIPTOR structure

    http://msdn.microsoft.com/en-us/library/ms684844(v=vs.85).aspx
    PROCESSOR_CACHE_TYPE enumeration

      GetLogicalProcessorInformation函数用起来是有一定复杂性的。因为它返回的是SYSTEM_LOGICAL_PROCESSOR_INFORMATION数组,数组中的每一项分别描述了不同的信息,学习曲线较陡峭。
      虽然MSDN上有该函数的范例代码,但是它屏蔽了很多细节,对我们的帮助有限。于是我将该范例程序作了改进,显示了SYSTEM_LOGICAL_PROCESSOR_INFORMATION数组中每一项的详细信息。

      心得——
    1.SYSTEM_LOGICAL_PROCESSOR_INFORMATION结构ProcessorMask是ULONG_PTR类型的。在32位系统上是32位,64位系统上是64位。为了简化代码,建议强制转型为UINT64类型,调用printf等输出函数时使用“I64”格式码。
    2.ProcessorMask是处理器掩码,每一位代表一个逻辑处理器。所以一般来说,32位系统最多支持32个逻辑处理器,64位系统最多支持64个逻辑处理器。
    3.对于Windows 7和Windows Server 2008 R2来说,能突破64个逻辑处理器限制,最高支持256个逻辑处理器。新加了 处理器组(Processor Groups)概念,详见:http://msdn.microsoft.com/en-us/library/dd405503(v=vs.85).aspx


    三、全部代码

      全部代码——

    [cpp] view plaincopy
     
     
    1. #include <windows.h>  
    2. #include <malloc.h>      
    3. #include <stdio.h>  
    4. #include <tchar.h>  
    5.   
    6. #if (_WIN32_WINNT < 0x0600)  // [zyl910] 低版本的Windows SDK没有定义 RelationProcessorPackage 等常量  
    7. #define RelationProcessorPackage    3  
    8. #define RelationGroup   4  
    9. #endif  
    10. // [zyl910] LOGICAL_PROCESSOR_RELATIONSHIP枚举的名称  
    11. const LPTSTR Names_LOGICAL_PROCESSOR_RELATIONSHIP[] = {  
    12.     _T("RelationProcessorCore")  
    13.     ,_T("RelationNumaNode")  
    14.     ,_T("RelationCache")  
    15.     ,_T("RelationProcessorPackage")  
    16.     ,_T("RelationGroup")  
    17. };  
    18. // [zyl910] PROCESSOR_CACHE_TYPE枚举的名称  
    19. const LPTSTR Names_PROCESSOR_CACHE_TYPE[] = {  
    20.     _T("CacheUnified")  
    21.     ,_T("CacheInstruction")  
    22.     ,_T("CacheData")  
    23.     ,_T("CacheTrace")  
    24. };  
    25.   
    26. typedef BOOL (WINAPI *LPFN_GLPI)(  
    27.     PSYSTEM_LOGICAL_PROCESSOR_INFORMATION,   
    28.     PDWORD);  
    29.   
    30.   
    31. // Helper function to count set bits in the processor mask.  
    32. DWORD CountSetBits(ULONG_PTR bitMask)  
    33. {  
    34.     DWORD LSHIFT = sizeof(ULONG_PTR)*8 - 1;  
    35.     DWORD bitSetCount = 0;  
    36.     ULONG_PTR bitTest = (ULONG_PTR)1 << LSHIFT;      
    37.     DWORD i;  
    38.       
    39.     for (i = 0; i <= LSHIFT; ++i)  
    40.     {  
    41.         bitSetCount += ((bitMask & bitTest)?1:0);  
    42.         bitTest/=2;  
    43.     }  
    44.   
    45.     return bitSetCount;  
    46. }  
    47.   
    48. int _cdecl _tmain ()  
    49. {  
    50.     LPFN_GLPI glpi;  
    51.     BOOL done = FALSE;  
    52.     PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;  
    53.     PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL;  
    54.     DWORD returnLength = 0;  
    55.     DWORD logicalProcessorCount = 0;  
    56.     DWORD numaNodeCount = 0;  
    57.     DWORD processorCoreCount = 0;  
    58.     DWORD processorL1CacheCount = 0;  
    59.     DWORD processorL2CacheCount = 0;  
    60.     DWORD processorL3CacheCount = 0;  
    61.     DWORD processorPackageCount = 0;  
    62.     DWORD byteOffset = 0;  
    63.     PCACHE_DESCRIPTOR Cache;  
    64.   
    65.     glpi = (LPFN_GLPI) GetProcAddress(  
    66.                             GetModuleHandle(TEXT("kernel32")),  
    67.                             "GetLogicalProcessorInformation");  
    68.     if (NULL == glpi)   
    69.     {  
    70.         _tprintf(TEXT(" GetLogicalProcessorInformation is not supported. "));  
    71.         return (1);  
    72.     }  
    73.   
    74.     while (!done)  
    75.     {  
    76.         DWORD rc = glpi(buffer, &returnLength);  
    77.   
    78.         if (FALSE == rc)   
    79.         {  
    80.             if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)   
    81.             {  
    82.                 if (buffer)   
    83.                     free(buffer);  
    84.   
    85.                 buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(  
    86.                         returnLength);  
    87.   
    88.                 if (NULL == buffer)   
    89.                 {  
    90.                     _tprintf(TEXT(" Error: Allocation failure "));  
    91.                     return (2);  
    92.                 }  
    93.             }   
    94.             else   
    95.             {  
    96.                 _tprintf(TEXT(" Error %d "), GetLastError());  
    97.                 return (3);  
    98.             }  
    99.         }   
    100.         else  
    101.         {  
    102.             done = TRUE;  
    103.         }  
    104.     }  
    105.   
    106.     ptr = buffer;  
    107.   
    108.     if (true)   // [zyl910] 显示SYSTEM_LOGICAL_PROCESSOR_INFORMATION结构体的详细信息  
    109.     {  
    110.         DWORD cnt = returnLength / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);    // 计算SYSTEM_LOGICAL_PROCESSOR_INFORMATION结构体的数目  
    111.         for(DWORD i=0; i<cnt; ++i)  
    112.         {  
    113.             _tprintf(TEXT("SYSTEM_LOGICAL_PROCESSOR_INFORMATION[%d] "), i);  
    114.             _tprintf(TEXT(" .ProcessorMask: 0x%.16I64X //%I64d "), (UINT64)ptr[i].ProcessorMask, (UINT64)ptr[i].ProcessorMask);  
    115.             _tprintf(TEXT(" .Relationship: %d //%s "), ptr[i].Relationship, Names_LOGICAL_PROCESSOR_RELATIONSHIP[max(0,min(ptr[i].Relationship, RelationGroup))]);  
    116.             for(int j=0; j<2; ++j)   _tprintf(TEXT(" .Reserved[%d]: //0x%.16I64X %I64d "), j, (UINT64)ptr[i].Reserved[j], (UINT64)ptr[i].Reserved[j]);  
    117.             if (RelationCache==ptr[i].Relationship)  
    118.             {  
    119.                 _tprintf(TEXT(" .Cache.Level: %u "), ptr[i].Cache.Level);  
    120.                 _tprintf(TEXT(" .Cache.Associativity: 0x%.2X //%u "), ptr[i].Cache.Associativity, ptr[i].Cache.Associativity);  
    121.                 _tprintf(TEXT(" .Cache.LineSize: 0x%.4X //%u "), ptr[i].Cache.LineSize, ptr[i].Cache.LineSize);  
    122.                 _tprintf(TEXT(" .Cache.Size: 0x%.8X //%u "), ptr[i].Cache.Size, ptr[i].Cache.Size);  
    123.                 _tprintf(TEXT(" .Cache.Type: %d //%s "), ptr[i].Cache.Type, Names_PROCESSOR_CACHE_TYPE[max(0,min(ptr[i].Cache.Type, CacheTrace))]);  
    124.             }  
    125.         }  
    126.     }  
    127.   
    128.     while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength)   
    129.     {  
    130.         switch (ptr->Relationship)   
    131.         {  
    132.         case RelationNumaNode:  
    133.             // Non-NUMA systems report a single record of this type.  
    134.             numaNodeCount++;  
    135.             break;  
    136.   
    137.         case RelationProcessorCore:  
    138.             processorCoreCount++;  
    139.   
    140.             // A hyperthreaded core supplies more than one logical processor.  
    141.             logicalProcessorCount += CountSetBits(ptr->ProcessorMask);  
    142.             break;  
    143.   
    144.         case RelationCache:  
    145.             // Cache data is in ptr->Cache, one CACHE_DESCRIPTOR structure for each cache.   
    146.             Cache = &ptr->Cache;  
    147.             if (Cache->Level == 1)  
    148.             {  
    149.                 processorL1CacheCount++;  
    150.             }  
    151.             else if (Cache->Level == 2)  
    152.             {  
    153.                 processorL2CacheCount++;  
    154.             }  
    155.             else if (Cache->Level == 3)  
    156.             {  
    157.                 processorL3CacheCount++;  
    158.             }  
    159.             break;  
    160.   
    161.         case RelationProcessorPackage:  
    162.             // Logical processors share a physical package.  
    163.             processorPackageCount++;  
    164.             break;  
    165.   
    166.         default:  
    167.             _tprintf(TEXT(" Error: Unsupported LOGICAL_PROCESSOR_RELATIONSHIP value. "));  
    168.             break;  
    169.         }  
    170.         byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);  
    171.         ptr++;  
    172.     }  
    173.   
    174.     _tprintf(TEXT(" GetLogicalProcessorInformation results: "));  
    175.     _tprintf(TEXT("Number of NUMA nodes: %d "),   
    176.              numaNodeCount);  
    177.     _tprintf(TEXT("Number of physical processor packages: %d "),   
    178.              processorPackageCount);  
    179.     _tprintf(TEXT("Number of processor cores: %d "),   
    180.              processorCoreCount);  
    181.     _tprintf(TEXT("Number of logical processors: %d "),   
    182.              logicalProcessorCount);  
    183.     _tprintf(TEXT("Number of processor L1/L2/L3 caches: %d/%d/%d "),   
    184.              processorL1CacheCount,  
    185.              processorL2CacheCount,  
    186.              processorL3CacheCount);  
    187.       
    188.     free(buffer);  
    189.   
    190.     return 0;  
    191. }  

    四、输出信息


      例如我的处理器是“Intel Core i3-2310M”,该程序的输出信息为——

    [plain] view plaincopy
     
     
    1. SYSTEM_LOGICAL_PROCESSOR_INFORMATION[0]  
    2.     .ProcessorMask: 0x0000000000000005  //5  
    3.     .Relationship:  0   //RelationProcessorCore  
    4.     .Reserved[0]:   //0x0000000000000001    1  
    5.     .Reserved[1]:   //0x0000000000000000    0  
    6. SYSTEM_LOGICAL_PROCESSOR_INFORMATION[1]  
    7.     .ProcessorMask: 0x0000000000000005  //5  
    8.     .Relationship:  2   //RelationCache  
    9.     .Reserved[0]:   //0x0000800000400801    140737492551681  
    10.     .Reserved[1]:   //0x0000000000000002    2  
    11.     .Cache.Level:   1  
    12.     .Cache.Associativity:   0x08    //8  
    13.     .Cache.LineSize:    0x0040  //64  
    14.     .Cache.Size:    0x00008000  //32768  
    15.     .Cache.Type:    2   //CacheData  
    16. SYSTEM_LOGICAL_PROCESSOR_INFORMATION[2]  
    17.     .ProcessorMask: 0x0000000000000005  //5  
    18.     .Relationship:  2   //RelationCache  
    19.     .Reserved[0]:   //0x0000800000400801    140737492551681  
    20.     .Reserved[1]:   //0x0000000000000001    1  
    21.     .Cache.Level:   1  
    22.     .Cache.Associativity:   0x08    //8  
    23.     .Cache.LineSize:    0x0040  //64  
    24.     .Cache.Size:    0x00008000  //32768  
    25.     .Cache.Type:    1   //CacheInstruction  
    26. SYSTEM_LOGICAL_PROCESSOR_INFORMATION[3]  
    27.     .ProcessorMask: 0x0000000000000005  //5  
    28.     .Relationship:  2   //RelationCache  
    29.     .Reserved[0]:   //0x0004000000400802    1125899911038978  
    30.     .Reserved[1]:   //0x0000000000000000    0  
    31.     .Cache.Level:   2  
    32.     .Cache.Associativity:   0x08    //8  
    33.     .Cache.LineSize:    0x0040  //64  
    34.     .Cache.Size:    0x00040000  //262144  
    35.     .Cache.Type:    0   //CacheUnified  
    36. SYSTEM_LOGICAL_PROCESSOR_INFORMATION[4]  
    37.     .ProcessorMask: 0x000000000000000F  //15  
    38.     .Relationship:  3   //RelationProcessorPackage  
    39.     .Reserved[0]:   //0x0000000000000000    0  
    40.     .Reserved[1]:   //0x0000000000000000    0  
    41. SYSTEM_LOGICAL_PROCESSOR_INFORMATION[5]  
    42.     .ProcessorMask: 0x000000000000000A  //10  
    43.     .Relationship:  0   //RelationProcessorCore  
    44.     .Reserved[0]:   //0x0000000000000001    1  
    45.     .Reserved[1]:   //0x0000000000000000    0  
    46. SYSTEM_LOGICAL_PROCESSOR_INFORMATION[6]  
    47.     .ProcessorMask: 0x000000000000000A  //10  
    48.     .Relationship:  2   //RelationCache  
    49.     .Reserved[0]:   //0x0000800000400801    140737492551681  
    50.     .Reserved[1]:   //0x0000000000000002    2  
    51.     .Cache.Level:   1  
    52.     .Cache.Associativity:   0x08    //8  
    53.     .Cache.LineSize:    0x0040  //64  
    54.     .Cache.Size:    0x00008000  //32768  
    55.     .Cache.Type:    2   //CacheData  
    56. SYSTEM_LOGICAL_PROCESSOR_INFORMATION[7]  
    57.     .ProcessorMask: 0x000000000000000A  //10  
    58.     .Relationship:  2   //RelationCache  
    59.     .Reserved[0]:   //0x0000800000400801    140737492551681  
    60.     .Reserved[1]:   //0x0000000000000001    1  
    61.     .Cache.Level:   1  
    62.     .Cache.Associativity:   0x08    //8  
    63.     .Cache.LineSize:    0x0040  //64  
    64.     .Cache.Size:    0x00008000  //32768  
    65.     .Cache.Type:    1   //CacheInstruction  
    66. SYSTEM_LOGICAL_PROCESSOR_INFORMATION[8]  
    67.     .ProcessorMask: 0x000000000000000A  //10  
    68.     .Relationship:  2   //RelationCache  
    69.     .Reserved[0]:   //0x0004000000400802    1125899911038978  
    70.     .Reserved[1]:   //0x0000000000000000    0  
    71.     .Cache.Level:   2  
    72.     .Cache.Associativity:   0x08    //8  
    73.     .Cache.LineSize:    0x0040  //64  
    74.     .Cache.Size:    0x00040000  //262144  
    75.     .Cache.Type:    0   //CacheUnified  
    76. SYSTEM_LOGICAL_PROCESSOR_INFORMATION[9]  
    77.     .ProcessorMask: 0x000000000000000F  //15  
    78.     .Relationship:  2   //RelationCache  
    79.     .Reserved[0]:   //0x0030000000400C03    13510798886308867  
    80.     .Reserved[1]:   //0x0000000000000000    0  
    81.     .Cache.Level:   3  
    82.     .Cache.Associativity:   0x0C    //12  
    83.     .Cache.LineSize:    0x0040  //64  
    84.     .Cache.Size:    0x00300000  //3145728  
    85.     .Cache.Type:    0   //CacheUnified  
    86. SYSTEM_LOGICAL_PROCESSOR_INFORMATION[10]  
    87.     .ProcessorMask: 0x000000000000000F  //15  
    88.     .Relationship:  1   //RelationNumaNode  
    89.     .Reserved[0]:   //0x0000000000000000    0  
    90.     .Reserved[1]:   //0x0000000000000000    0  
    91.   
    92. GetLogicalProcessorInformation results:  
    93. Number of NUMA nodes: 1  
    94. Number of physical processor packages: 1  
    95. Number of processor cores: 2  
    96. Number of logical processors: 4  
    97. Number of processor L1/L2/L3 caches: 4/2/1  
     
    参考:http://blog.csdn.net/dai_jing/article/details/37692643
  • 相关阅读:
    针对web高并发量的处理
    外边距合并,外边距折叠
    cookie 和session 的区别:
    ng-if ng-show ng-hide 的区别
    JavaScript中的arguments,callee,caller
    git常见命令
    jQuery中.bind() .live() .delegate() .on()的区别
    为什么要使用sass
    js兼容性记录
    poj1004
  • 原文地址:https://www.cnblogs.com/findumars/p/4805207.html
Copyright © 2011-2022 走看看