Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Daniel Pfeifer
KWSys
Commits
9c4230b7
Commit
9c4230b7
authored
Jan 26, 2017
by
Nicolás Bértolo
Committed by
Brad King
Feb 09, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
SystemInformation: Fix counts of logical and physical cores
Issue:
cmake/cmake#16594
parent
a423d829
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
65 additions
and
182 deletions
+65
-182
SystemInformation.cxx
SystemInformation.cxx
+64
-181
SystemInformation.hxx.in
SystemInformation.hxx.in
+1
-1
No files found.
SystemInformation.cxx
View file @
9c4230b7
...
...
@@ -35,8 +35,13 @@
#include "SystemInformation.hxx.in"
#endif
#include <algorithm>
#include <bitset>
#include <cassert>
#include <fstream>
#include <iostream>
#include <limits>
#include <set>
#include <sstream>
#include <string>
#include <vector>
...
...
@@ -394,7 +399,6 @@ public:
bool
SupportsMP
;
bool
HasMMXPlus
;
bool
HasSSEMMX
;
bool
SupportsHyperthreading
;
unsigned
int
LogicalProcessorsPerPhysical
;
int
APIC_ID
;
CPUPowerManagement
PowerManagement
;
...
...
@@ -463,10 +467,9 @@ protected:
unsigned
int
NumberOfLogicalCPU
;
unsigned
int
NumberOfPhysicalCPU
;
int
CPUCount
();
// For windows
unsigned
char
LogicalCPUPerPhysicalCPU
();
void
CPUCountWindows
();
// For windows
unsigned
char
GetAPICId
();
// For windows
bool
Is
HyperThreading
Supported
();
bool
Is
SMT
Supported
();
static
LongLong
GetCyclesDifference
(
DELAY_FUNC
,
unsigned
int
);
// For windows
// For Linux and Cygwin, /proc/cpuinfo formats are slightly different
...
...
@@ -1542,7 +1545,7 @@ void SystemInformationImplementation::RunCPUCheck()
RetrieveProcessorSerialNumber
();
}
this
->
CPUCount
();
this
->
CPUCount
Windows
();
#elif defined(__APPLE__)
this
->
ParseSysCtl
();
...
...
@@ -2090,16 +2093,10 @@ bool SystemInformationImplementation::RetrieveCPUFeatures()
// Retrieve Intel specific extended features.
if
(
this
->
ChipManufacturer
==
Intel
)
{
this
->
Features
.
ExtendedFeatures
.
SupportsHyperthreading
=
((
cpuinfo
[
3
]
&
0x10000000
)
!=
0
);
// Intel specific: Hyperthreading --> Bit 28
this
->
Features
.
ExtendedFeatures
.
LogicalProcessorsPerPhysical
=
(
this
->
Features
.
ExtendedFeatures
.
SupportsHyperthreading
)
?
((
cpuinfo
[
1
]
&
0x00FF0000
)
>>
16
)
:
1
;
if
((
this
->
Features
.
ExtendedFeatures
.
SupportsHyperthreading
)
&&
(
this
->
Features
.
HasAPIC
))
{
bool
SupportsSMT
=
((
cpuinfo
[
3
]
&
0x10000000
)
!=
0
);
// Intel specific: SMT --> Bit 28
if
((
SupportsSMT
)
&&
(
this
->
Features
.
HasAPIC
))
{
// Retrieve APIC information if there is one present.
this
->
Features
.
ExtendedFeatures
.
APIC_ID
=
((
cpuinfo
[
1
]
&
0xFF000000
)
>>
24
);
...
...
@@ -3401,7 +3398,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
fclose
(
fd
);
buffer
.
resize
(
fileSize
-
2
);
// Number of logical CPUs (combination of multiple processors, multi-core
// and
hyperthreading
)
// and
SMT
)
size_t
pos
=
buffer
.
find
(
"processor
\t
"
);
while
(
pos
!=
buffer
.
npos
)
{
this
->
NumberOfLogicalCPU
++
;
...
...
@@ -3409,30 +3406,24 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
}
#ifdef __linux
//
Find the largest physical id
.
int
maxId
=
-
1
;
//
Count sockets
.
std
::
set
<
int
>
PhysicalIDs
;
std
::
string
idc
=
this
->
ExtractValueFromCpuInfoFile
(
buffer
,
"physical id"
);
while
(
this
->
CurrentPositionInFile
!=
buffer
.
npos
)
{
int
id
=
atoi
(
idc
.
c_str
());
if
(
id
>
maxId
)
{
maxId
=
id
;
}
PhysicalIDs
.
insert
(
id
);
idc
=
this
->
ExtractValueFromCpuInfoFile
(
buffer
,
"physical id"
,
this
->
CurrentPositionInFile
+
1
);
}
uint64_t
NumberOfSockets
=
PhysicalIDs
.
size
();
NumberOfSockets
=
std
::
max
(
NumberOfSockets
,
(
uint64_t
)
1
);
// Physical ids returned by Linux don't distinguish cores.
// We want to record the total number of cores in this->NumberOfPhysicalCPU
// (checking only the first proc)
std
::
string
cores
=
this
->
ExtractValueFromCpuInfoFile
(
buffer
,
"cpu cores"
);
int
numberOfCoresPerCPU
=
atoi
(
cores
.
c_str
());
if
(
maxId
>
0
)
{
this
->
NumberOfPhysicalCPU
=
static_cast
<
unsigned
int
>
(
numberOfCoresPerCPU
*
(
maxId
+
1
));
}
else
{
// Linux Sparc: get cpu count
this
->
NumberOfPhysicalCPU
=
atoi
(
this
->
ExtractValueFromCpuInfoFile
(
buffer
,
"ncpus active"
).
c_str
());
}
std
::
string
Cores
=
this
->
ExtractValueFromCpuInfoFile
(
buffer
,
"cpu cores"
);
int
NumberOfCoresPerSocket
=
atoi
(
Cores
.
c_str
());
NumberOfCoresPerSocket
=
std
::
max
(
NumberOfCoresPerSocket
,
1
);
this
->
NumberOfPhysicalCPU
=
NumberOfCoresPerSocket
*
NumberOfSockets
;
#else // __CYGWIN__
// does not have "physical id" entries, neither "cpu cores"
...
...
@@ -3447,7 +3438,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
if
(
this
->
NumberOfPhysicalCPU
<=
0
)
{
this
->
NumberOfPhysicalCPU
=
1
;
}
// LogicalProcessorsPerPhysical>1 =>
hyperthreading
.
// LogicalProcessorsPerPhysical>1 =>
SMT
.
this
->
Features
.
ExtendedFeatures
.
LogicalProcessorsPerPhysical
=
this
->
NumberOfLogicalCPU
/
this
->
NumberOfPhysicalCPU
;
...
...
@@ -4322,68 +4313,10 @@ void SystemInformationImplementation::DelayOverhead(unsigned int uiMS)
(
void
)
uiMS
;
}
/** Return the number of logical CPU per physical CPUs Works only for windows
*/
unsigned
char
SystemInformationImplementation
::
LogicalCPUPerPhysicalCPU
(
void
)
{
#ifdef __APPLE__
size_t
len
=
4
;
int
cores_per_package
=
0
;
int
err
=
sysctlbyname
(
"machdep.cpu.cores_per_package"
,
&
cores_per_package
,
&
len
,
NULL
,
0
);
if
(
err
!=
0
)
{
return
1
;
// That name was not found, default to 1
}
return
static_cast
<
unsigned
char
>
(
cores_per_package
);
#else
int
Regs
[
4
]
=
{
0
,
0
,
0
,
0
};
#if USE_CPUID
if
(
!
this
->
IsHyperThreadingSupported
())
{
return
static_cast
<
unsigned
char
>
(
1
);
// HT not supported
}
call_cpuid
(
1
,
Regs
);
#endif
return
static_cast
<
unsigned
char
>
((
Regs
[
1
]
&
NUM_LOGICAL_BITS
)
>>
16
);
#endif
}
/** Works only for windows */
bool
SystemInformationImplementation
::
Is
HyperThreading
Supported
()
bool
SystemInformationImplementation
::
Is
SMT
Supported
()
{
if
(
this
->
Features
.
ExtendedFeatures
.
SupportsHyperthreading
)
{
return
true
;
}
#if USE_CPUID
int
Regs
[
4
]
=
{
0
,
0
,
0
,
0
},
VendorId
[
4
]
=
{
0
,
0
,
0
,
0
};
// Get vendor id string
if
(
!
call_cpuid
(
0
,
VendorId
))
{
return
false
;
}
// eax contains family processor type
// edx has info about the availability of hyper-Threading
if
(
!
call_cpuid
(
1
,
Regs
))
{
return
false
;
}
if
(((
Regs
[
0
]
&
FAMILY_ID
)
==
PENTIUM4_ID
)
||
(
Regs
[
0
]
&
EXT_FAMILY_ID
))
{
if
(
VendorId
[
1
]
==
0x756e6547
)
// 'uneG'
{
if
(
VendorId
[
3
]
==
0x49656e69
)
// 'Ieni'
{
if
(
VendorId
[
2
]
==
0x6c65746e
)
// 'letn'
{
// Genuine Intel with hyper-Threading technology
this
->
Features
.
ExtendedFeatures
.
SupportsHyperthreading
=
((
Regs
[
3
]
&
HT_BIT
)
!=
0
);
return
this
->
Features
.
ExtendedFeatures
.
SupportsHyperthreading
;
}
}
}
}
#endif
return
0
;
// Not genuine Intel processor
return
this
->
Features
.
ExtendedFeatures
.
LogicalProcessorsPerPhysical
>
1
;
}
/** Return the APIC Id. Works only for windows. */
...
...
@@ -4392,7 +4325,7 @@ unsigned char SystemInformationImplementation::GetAPICId()
int
Regs
[
4
]
=
{
0
,
0
,
0
,
0
};
#if USE_CPUID
if
(
!
this
->
Is
HyperThreading
Supported
())
{
if
(
!
this
->
Is
SMT
Supported
())
{
return
static_cast
<
unsigned
char
>
(
-
1
);
// HT not supported
}
// Logical processor = 1
call_cpuid
(
1
,
Regs
);
...
...
@@ -4402,102 +4335,46 @@ unsigned char SystemInformationImplementation::GetAPICId()
}
/** Count the number of CPUs. Works only on windows. */
int
SystemInformationImplementation
::
CPUCount
()
void
SystemInformationImplementation
::
CPUCount
Windows
()
{
#if defined(_WIN32)
unsigned
char
StatusFlag
=
0
;
SYSTEM_INFO
info
;
std
::
vector
<
SYSTEM_LOGICAL_PROCESSOR_INFORMATION
>
ProcInfo
;
this
->
NumberOfPhysicalCPU
=
0
;
this
->
NumberOfLogicalCPU
=
0
;
info
.
dwNumberOfProcessors
=
0
;
GetSystemInfo
(
&
info
);
// Number of physical processors in a non-Intel system
// or in a 32-bit Intel system with Hyper-Threading technology disabled
this
->
NumberOfPhysicalCPU
=
(
unsigned
char
)
info
.
dwNumberOfProcessors
;
if
(
this
->
IsHyperThreadingSupported
())
{
unsigned
char
HT_Enabled
=
0
;
this
->
NumberOfLogicalCPU
=
this
->
LogicalCPUPerPhysicalCPU
();
if
(
this
->
NumberOfLogicalCPU
>=
1
)
// >1 Doesn't mean HT is enabled in the BIOS
{
HANDLE
hCurrentProcessHandle
;
#ifndef _WIN64
#define DWORD_PTR DWORD
#endif
DWORD_PTR
dwProcessAffinity
;
DWORD_PTR
dwSystemAffinity
;
DWORD
dwAffinityMask
;
// Calculate the appropriate shifts and mask based on the
// number of logical processors.
unsigned
int
i
=
1
;
unsigned
char
PHY_ID_MASK
=
0xFF
;
// unsigned char PHY_ID_SHIFT = 0;
while
(
i
<
this
->
NumberOfLogicalCPU
)
{
i
*=
2
;
PHY_ID_MASK
<<=
1
;
// PHY_ID_SHIFT++;
}
hCurrentProcessHandle
=
GetCurrentProcess
();
GetProcessAffinityMask
(
hCurrentProcessHandle
,
&
dwProcessAffinity
,
&
dwSystemAffinity
);
// Check if available process affinity mask is equal to the
// available system affinity mask
if
(
dwProcessAffinity
!=
dwSystemAffinity
)
{
StatusFlag
=
HT_CANNOT_DETECT
;
this
->
NumberOfPhysicalCPU
=
(
unsigned
char
)
-
1
;
return
StatusFlag
;
}
dwAffinityMask
=
1
;
while
(
dwAffinityMask
!=
0
&&
dwAffinityMask
<=
dwProcessAffinity
)
{
// Check if this CPU is available
if
(
dwAffinityMask
&
dwProcessAffinity
)
{
if
(
SetProcessAffinityMask
(
hCurrentProcessHandle
,
dwAffinityMask
))
{
unsigned
char
APIC_ID
,
LOG_ID
;
Sleep
(
0
);
// Give OS time to switch CPU
APIC_ID
=
GetAPICId
();
LOG_ID
=
APIC_ID
&
~
PHY_ID_MASK
;
if
(
LOG_ID
!=
0
)
{
HT_Enabled
=
1
;
}
}
}
dwAffinityMask
=
dwAffinityMask
<<
1
;
}
// Reset the processor affinity
SetProcessAffinityMask
(
hCurrentProcessHandle
,
dwProcessAffinity
);
{
DWORD
Length
=
0
;
DWORD
rc
=
GetLogicalProcessorInformation
(
NULL
,
&
Length
);
assert
(
FALSE
==
rc
);
(
void
)
rc
;
// Silence unused variable warning in Borland C++ 5.81
assert
(
GetLastError
()
==
ERROR_INSUFFICIENT_BUFFER
);
ProcInfo
.
resize
(
Length
/
sizeof
(
SYSTEM_LOGICAL_PROCESSOR_INFORMATION
));
rc
=
GetLogicalProcessorInformation
(
&
ProcInfo
[
0
],
&
Length
);
assert
(
rc
!=
FALSE
);
(
void
)
rc
;
// Silence unused variable warning in Borland C++ 5.81
}
typedef
std
::
vector
<
SYSTEM_LOGICAL_PROCESSOR_INFORMATION
>::
iterator
pinfoIt_t
;
for
(
pinfoIt_t
it
=
ProcInfo
.
begin
();
it
!=
ProcInfo
.
end
();
++
it
)
{
SYSTEM_LOGICAL_PROCESSOR_INFORMATION
PInfo
=
*
it
;
if
(
PInfo
.
Relationship
!=
RelationProcessorCore
)
{
continue
;
}
if
(
this
->
NumberOfLogicalCPU
==
1
)
// Normal P4 : HT is disabled in hardware
{
StatusFlag
=
HT_DISABLED
;
}
else
{
if
(
HT_Enabled
)
{
// Total physical processors in a Hyper-Threading enabled system.
this
->
NumberOfPhysicalCPU
/=
(
this
->
NumberOfLogicalCPU
);
StatusFlag
=
HT_ENABLED
;
}
else
{
StatusFlag
=
HT_SUPPORTED_NOT_ENABLED
;
}
}
std
::
bitset
<
std
::
numeric_limits
<
ULONG_PTR
>::
digits
>
ProcMask
(
(
unsigned
long
long
)
PInfo
.
ProcessorMask
);
unsigned
int
count
=
(
unsigned
int
)
ProcMask
.
count
();
if
(
count
==
0
)
{
// I think this should never happen, but just to be safe.
continue
;
}
}
else
{
// Processors do not have Hyper-Threading technology
StatusFlag
=
HT_NOT_CAPABLE
;
this
->
NumberOfLogicalCPU
=
1
;
this
->
NumberOfPhysicalCPU
++
;
this
->
NumberOfLogicalCPU
+=
(
unsigned
int
)
count
;
this
->
Features
.
ExtendedFeatures
.
LogicalProcessorsPerPhysical
=
count
;
}
return
StatusFlag
;
this
->
NumberOfPhysicalCPU
=
std
::
max
(
1u
,
this
->
NumberOfPhysicalCPU
);
this
->
NumberOfLogicalCPU
=
std
::
max
(
1u
,
this
->
NumberOfLogicalCPU
);
#else
return
0
;
#endif
}
...
...
@@ -4559,8 +4436,14 @@ bool SystemInformationImplementation::ParseSysCtl()
sysctlbyname
(
"hw.physicalcpu"
,
&
this
->
NumberOfPhysicalCPU
,
&
len
,
NULL
,
0
);
len
=
sizeof
(
this
->
NumberOfLogicalCPU
);
sysctlbyname
(
"hw.logicalcpu"
,
&
this
->
NumberOfLogicalCPU
,
&
len
,
NULL
,
0
);
int
cores_per_package
=
0
;
len
=
sizeof
(
cores_per_package
);
err
=
sysctlbyname
(
"machdep.cpu.cores_per_package"
,
&
cores_per_package
,
&
len
,
NULL
,
0
);
// That name was not found, default to 1
this
->
Features
.
ExtendedFeatures
.
LogicalProcessorsPerPhysical
=
this
->
LogicalCPUPerPhysicalCPU
(
);
err
!=
0
?
1
:
static_cast
<
unsigned
char
>
(
cores_per_package
);
len
=
sizeof
(
value
);
sysctlbyname
(
"hw.cpufrequency"
,
&
value
,
&
len
,
NULL
,
0
);
...
...
SystemInformation.hxx.in
View file @
9c4230b7
...
...
@@ -67,7 +67,7 @@ public:
bool Is64Bits();
unsigned int GetNumberOfLogicalCPU();
// per physical cpu
unsigned int GetNumberOfLogicalCPU();
unsigned int GetNumberOfPhysicalCPU();
bool DoesCPUSupportCPUID();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment