проверка количества процессоров совсем не проста (в основном из-за многоядерных / сокетов / процессоров). Вызов GetSystemInfo
возвращает количество потоков выполнения, которые видит система, CPUID имеет разные значения в зависимости от топологии процессора (см. Руководства разработчика Intel).
Я построил что-то, чтобы поймать все ситуации, это может оказаться полезным:
static void GetProcessorTopology(size_t& nPhysical, size_t& nCores, size_t& nSystemThreads, size_t& nHWThreads, size_t& nThreadsPerCore)
{
int nInfo[4];
SYSTEM_INFO pSystemInfo;
IsWOW64() ? GetNativeSystemInfo(&pSystemInfo) : GetSystemInfo(&pSystemInfo);
nSystemThreads = pSystemInfo.dwNumberOfProcessors;
if(TestTopologyLevel(nInfo,0x0,1) || TestTopologyLevel(nInfo,0x1,1))
{
nThreadsPerCore = nInfo[1] & 0xFFFF;
if(TestTopologyLevel(nInfo,0x0,2) || TestTopologyLevel(nInfo,0x1,2))
{
nHWThreads = nInfo[1] & 0xFFFF;
nCores = (nThreadsPerCore == 0) ? GetCoreCount(nInfo) : nHWThreads / nThreadsPerCore;
}
else
{
nHWThreads = nSystemThreads;
nCores = GetCoreCount(nInfo);
}
}
else
{
nThreadsPerCore = 1;
nHWThreads = nSystemThreads;
nCores = GetCoreCount(nInfo);
}
nPhysical = (nCores == 0) ? 1 : (nSystemThreads / nThreadsPerCore) / nCores;
}
static inline bool TestTopologyLevel(int* pInfo, int nMode, int nLevel)
{
__cpuidex(pInfo,0xB,nMode);
return ((pInfo[2] >> 8) & 0xFF) == nLevel;
}
static inline size_t GetCoreCount(int* nInfo)
{
__cpuid(nInfo,0);
if(nInfo[0] >= 4)
{
__cpuidex(nInfo,0x4,0x0);
return (nInfo[0] >> 26) + 1;
}
else
{
__cpuid(nInfo,0x80000000);
int nCPUID = nInfo[0];
__cpuid(nInfo,1);
if(nInfo[3] & 0x10000000 && nCPUID >= 0x80000008)
{
__cpuid(nInfo,0x80000008);
return (nInfo[2] & 0xFF) + 1;
}
}
return 1;
}