您的位置:首页 > Web前端

使用GetLogicalProcessorInformation获取逻辑处理器的详细信息(NUMA节点数、物理CPU数、CPU核心数、逻辑CPU数、各级Cache)

2012-08-08 10:01 525 查看
现在多核处理器已经很普及了,市场主流是双核处理器,还有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

三、全部代码

  全部代码——

#include <windows.h>
#include <malloc.h>
#include <stdio.h>
#include <tchar.h>

#if (_WIN32_WINNT < 0x0600)    // [zyl910] 低版本的Windows SDK没有定义 RelationProcessorPackage 等常量
#define RelationProcessorPackage    3
#define RelationGroup    4
#endif
// [zyl910] LOGICAL_PROCESSOR_RELATIONSHIP枚举的名称
const LPTSTR Names_LOGICAL_PROCESSOR_RELATIONSHIP[] = {
_T("RelationProcessorCore")
,_T("RelationNumaNode")
,_T("RelationCache")
,_T("RelationProcessorPackage")
,_T("RelationGroup")
};
// [zyl910] PROCESSOR_CACHE_TYPE枚举的名称
const LPTSTR Names_PROCESSOR_CACHE_TYPE[] = {
_T("CacheUnified")
,_T("CacheInstruction")
,_T("CacheData")
,_T("CacheTrace")
};

typedef BOOL (WINAPI *LPFN_GLPI)(
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION,
PDWORD);

// Helper function to count set bits in the processor mask.
DWORD CountSetBits(ULONG_PTR bitMask)
{
DWORD LSHIFT = sizeof(ULONG_PTR)*8 - 1;
DWORD bitSetCount = 0;
ULONG_PTR bitTest = (ULONG_PTR)1 << LSHIFT;
DWORD i;

for (i = 0; i <= LSHIFT; ++i)
{
bitSetCount += ((bitMask & bitTest)?1:0);
bitTest/=2;
}

return bitSetCount;
}

int _cdecl _tmain ()
{
LPFN_GLPI glpi;
BOOL done = FALSE;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL;
DWORD returnLength = 0;
DWORD logicalProcessorCount = 0;
DWORD numaNodeCount = 0;
DWORD processorCoreCount = 0;
DWORD processorL1CacheCount = 0;
DWORD processorL2CacheCount = 0;
DWORD processorL3CacheCount = 0;
DWORD processorPackageCount = 0;
DWORD byteOffset = 0;
PCACHE_DESCRIPTOR Cache;

glpi = (LPFN_GLPI) GetProcAddress(
GetModuleHandle(TEXT("kernel32")),
"GetLogicalProcessorInformation");
if (NULL == glpi)
{
_tprintf(TEXT("\nGetLogicalProcessorInformation is not supported.\n"));
return (1);
}

while (!done)
{
DWORD rc = glpi(buffer, &returnLength);

if (FALSE == rc)
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
if (buffer)
free(buffer);

buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(
returnLength);

if (NULL == buffer)
{
_tprintf(TEXT("\nError: Allocation failure\n"));
return (2);
}
}
else
{
_tprintf(TEXT("\nError %d\n"), GetLastError());
return (3);
}
}
else
{
done = TRUE;
}
}

ptr = buffer;

if (true)    // [zyl910] 显示SYSTEM_LOGICAL_PROCESSOR_INFORMATION结构体的详细信息
{
DWORD cnt = returnLength / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);    // 计算SYSTEM_LOGICAL_PROCESSOR_INFORMATION结构体的数目
for(DWORD i=0; i<cnt; ++i)
{
_tprintf(TEXT("SYSTEM_LOGICAL_PROCESSOR_INFORMATION[%d]\n"), i);
_tprintf(TEXT("\t.ProcessorMask:\t0x%.16I64X\t//%I64d\n"), (UINT64)ptr[i].ProcessorMask, (UINT64)ptr[i].ProcessorMask);
_tprintf(TEXT("\t.Relationship:\t%d\t//%s\n"), ptr[i].Relationship, Names_LOGICAL_PROCESSOR_RELATIONSHIP[max(0,min(ptr[i].Relationship, RelationGroup))]);
for(int j=0; j<2; ++j)    _tprintf(TEXT("\t.Reserved[%d]:\t//0x%.16I64X\t%I64d\n"), j, (UINT64)ptr[i].Reserved[j], (UINT64)ptr[i].Reserved[j]);
if (RelationCache==ptr[i].Relationship)
{
_tprintf(TEXT("\t.Cache.Level:\t%u\n"), ptr[i].Cache.Level);
_tprintf(TEXT("\t.Cache.Associativity:\t0x%.2X\t//%u\n"), ptr[i].Cache.Associativity, ptr[i].Cache.Associativity);
_tprintf(TEXT("\t.Cache.LineSize:\t0x%.4X\t//%u\n"), ptr[i].Cache.LineSize, ptr[i].Cache.LineSize);
_tprintf(TEXT("\t.Cache.Size:\t0x%.8X\t//%u\n"), ptr[i].Cache.Size, ptr[i].Cache.Size);
_tprintf(TEXT("\t.Cache.Type:\t%d\t//%s\n"), ptr[i].Cache.Type, Names_PROCESSOR_CACHE_TYPE[max(0,min(ptr[i].Cache.Type, CacheTrace))]);
}
}
}

while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength)
{
switch (ptr->Relationship)
{
case RelationNumaNode:
// Non-NUMA systems report a single record of this type.
numaNodeCount++;
break;

case RelationProcessorCore:
processorCoreCount++;

// A hyperthreaded core supplies more than one logical processor.
logicalProcessorCount += CountSetBits(ptr->ProcessorMask);
break;

case RelationCache:
// Cache data is in ptr->Cache, one CACHE_DESCRIPTOR structure for each cache.
Cache = &ptr->Cache;
if (Cache->Level == 1)
{
processorL1CacheCount++;
}
else if (Cache->Level == 2)
{
processorL2CacheCount++;
}
else if (Cache->Level == 3)
{
processorL3CacheCount++;
}
break;

case RelationProcessorPackage:
// Logical processors share a physical package.
processorPackageCount++;
break;

default:
_tprintf(TEXT("\nError: Unsupported LOGICAL_PROCESSOR_RELATIONSHIP value.\n"));
break;
}
byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
ptr++;
}

_tprintf(TEXT("\nGetLogicalProcessorInformation results:\n"));
_tprintf(TEXT("Number of NUMA nodes: %d\n"),
numaNodeCount);
_tprintf(TEXT("Number of physical processor packages: %d\n"),
processorPackageCount);
_tprintf(TEXT("Number of processor cores: %d\n"),
processorCoreCount);
_tprintf(TEXT("Number of logical processors: %d\n"),
logicalProcessorCount);
_tprintf(TEXT("Number of processor L1/L2/L3 caches: %d/%d/%d\n"),
processorL1CacheCount,
processorL2CacheCount,
processorL3CacheCount);

free(buffer);

return 0;
}


 

 

四、输出信息

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

SYSTEM_LOGICAL_PROCESSOR_INFORMATION[0]
.ProcessorMask:    0x0000000000000005    //5
.Relationship:    0    //RelationProcessorCore
.Reserved[0]:    //0x0000000000000001    1
.Reserved[1]:    //0x0000000000000000    0
SYSTEM_LOGICAL_PROCESSOR_INFORMATION[1]
.ProcessorMask:    0x0000000000000005    //5
.Relationship:    2    //RelationCache
.Reserved[0]:    //0x0000800000400801    140737492551681
.Reserved[1]:    //0x0000000000000002    2
.Cache.Level:    1
.Cache.Associativity:    0x08    //8
.Cache.LineSize:    0x0040    //64
.Cache.Size:    0x00008000    //32768
.Cache.Type:    2    //CacheData
SYSTEM_LOGICAL_PROCESSOR_INFORMATION[2]
.ProcessorMask:    0x0000000000000005    //5
.Relationship:    2    //RelationCache
.Reserved[0]:    //0x0000800000400801    140737492551681
.Reserved[1]:    //0x0000000000000001    1
.Cache.Level:    1
.Cache.Associativity:    0x08    //8
.Cache.LineSize:    0x0040    //64
.Cache.Size:    0x00008000    //32768
.Cache.Type:    1    //CacheInstruction
SYSTEM_LOGICAL_PROCESSOR_INFORMATION[3]
.ProcessorMask:    0x0000000000000005    //5
.Relationship:    2    //RelationCache
.Reserved[0]:    //0x0004000000400802    1125899911038978
.Reserved[1]:    //0x0000000000000000    0
.Cache.Level:    2
.Cache.Associativity:    0x08    //8
.Cache.LineSize:    0x0040    //64
.Cache.Size:    0x00040000    //262144
.Cache.Type:    0    //CacheUnified
SYSTEM_LOGICAL_PROCESSOR_INFORMATION[4]
.ProcessorMask:    0x000000000000000F    //15
.Relationship:    3    //RelationProcessorPackage
.Reserved[0]:    //0x0000000000000000    0
.Reserved[1]:    //0x0000000000000000    0
SYSTEM_LOGICAL_PROCESSOR_INFORMATION[5]
.ProcessorMask:    0x000000000000000A    //10
.Relationship:    0    //RelationProcessorCore
.Reserved[0]:    //0x0000000000000001    1
.Reserved[1]:    //0x0000000000000000    0
SYSTEM_LOGICAL_PROCESSOR_INFORMATION[6]
.ProcessorMask:    0x000000000000000A    //10
.Relationship:    2    //RelationCache
.Reserved[0]:    //0x0000800000400801    140737492551681
.Reserved[1]:    //0x0000000000000002    2
.Cache.Level:    1
.Cache.Associativity:    0x08    //8
.Cache.LineSize:    0x0040    //64
.Cache.Size:    0x00008000    //32768
.Cache.Type:    2    //CacheData
SYSTEM_LOGICAL_PROCESSOR_INFORMATION[7]
.ProcessorMask:    0x000000000000000A    //10
.Relationship:    2    //RelationCache
.Reserved[0]:    //0x0000800000400801    140737492551681
.Reserved[1]:    //0x0000000000000001    1
.Cache.Level:    1
.Cache.Associativity:    0x08    //8
.Cache.LineSize:    0x0040    //64
.Cache.Size:    0x00008000    //32768
.Cache.Type:    1    //CacheInstruction
SYSTEM_LOGICAL_PROCESSOR_INFORMATION[8]
.ProcessorMask:    0x000000000000000A    //10
.Relationship:    2    //RelationCache
.Reserved[0]:    //0x0004000000400802    1125899911038978
.Reserved[1]:    //0x0000000000000000    0
.Cache.Level:    2
.Cache.Associativity:    0x08    //8
.Cache.LineSize:    0x0040    //64
.Cache.Size:    0x00040000    //262144
.Cache.Type:    0    //CacheUnified
SYSTEM_LOGICAL_PROCESSOR_INFORMATION[9]
.ProcessorMask:    0x000000000000000F    //15
.Relationship:    2    //RelationCache
.Reserved[0]:    //0x0030000000400C03    13510798886308867
.Reserved[1]:    //0x0000000000000000    0
.Cache.Level:    3
.Cache.Associativity:    0x0C    //12
.Cache.LineSize:    0x0040    //64
.Cache.Size:    0x00300000    //3145728
.Cache.Type:    0    //CacheUnified
SYSTEM_LOGICAL_PROCESSOR_INFORMATION[10]
.ProcessorMask:    0x000000000000000F    //15
.Relationship:    1    //RelationNumaNode
.Reserved[0]:    //0x0000000000000000    0
.Reserved[1]:    //0x0000000000000000    0

GetLogicalProcessorInformation results:
Number of NUMA nodes: 1
Number of physical processor packages: 1
Number of processor cores: 2
Number of logical processors: 4
Number of processor L1/L2/L3 caches: 4/2/1


 

 

源码下载——

http://files.cnblogs.com/zyl910/showGetLogicalProcessorInformation.rar

作者:zyl910
出处:http://www.cnblogs.com/zyl910/
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐