6
6
// MacOS (g++, clang++, icpc)
7
7
// Linux (g++, clang++, icpx)
8
8
9
+ // Compiler OS-detection macros
10
+ // https://sourceforge.net/p/predef/wiki/OperatingSystems/
11
+
9
12
#include < vector>
10
13
#include < cassert>
11
14
#include < bitset>
19
22
#include < windows.h>
20
23
#elif defined (__APPLE__)
21
24
#include < sys/sysctl.h>
22
- #else
25
+ #elif __has_include(<unistd.h>)
23
26
#include < unistd.h>
24
27
#endif
25
28
26
- extern " C" unsigned int cpu_count ();
29
+ unsigned int CPUCountWindows ();
30
+ unsigned int ParseSysCtl ();
31
+ unsigned int RetrieveInformationFromCpuInfoFile ();
32
+ unsigned int QueryProcessorBySysconf ();
33
+ unsigned int QueryThreads ();
27
34
28
35
std::string ExtractValueFromCpuInfoFile (std::string buffer, const char * word,
29
36
size_t & CurrentPositionInFile, size_t init = 0 );
30
37
38
+ #ifdef __cplusplus
39
+ extern " C" {
40
+ #endif
31
41
32
42
unsigned int cpu_count (){
33
43
34
44
unsigned int NumberOfPhysicalCPU = 0 ;
45
+
46
+ #if defined (_WIN32)
47
+ NumberOfPhysicalCPU = CPUCountWindows ();
48
+ #elif defined (__APPLE__)
49
+ NumberOfPhysicalCPU = ParseSysCtl ();
50
+ #elif defined (__unix__)
51
+ NumberOfPhysicalCPU = RetrieveInformationFromCpuInfoFile ();
52
+ #endif
53
+
54
+ if (NumberOfPhysicalCPU == 0 )
55
+ NumberOfPhysicalCPU = QueryProcessorBySysconf ();
56
+
57
+ if (NumberOfPhysicalCPU == 0 )
58
+ NumberOfPhysicalCPU = QueryThreads ();
59
+
60
+ return NumberOfPhysicalCPU;
61
+
62
+ }
63
+
64
+ #ifdef __cplusplus
65
+ }
66
+ #endif
67
+
68
+
69
+ unsigned int CPUCountWindows (){
70
+
71
+ unsigned int NumberOfPhysicalCPU = 0 ;
35
72
unsigned int NumberOfLogicalCPU = 0 ;
36
73
37
74
#ifdef _WIN32
@@ -51,10 +88,12 @@ unsigned int cpu_count(){
51
88
DWORD Length = 0 ;
52
89
DWORD rc = pGetLogicalProcessorInformation (nullptr , &Length);
53
90
assert (rc == 0 );
91
+ (void )rc; // Silence unused variable warning
54
92
assert (GetLastError () == ERROR_INSUFFICIENT_BUFFER);
55
93
ProcInfo.resize (Length / sizeof (SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
56
94
rc = pGetLogicalProcessorInformation (&ProcInfo[0 ], &Length);
57
95
assert (rc != 0 );
96
+ (void )rc; // Silence unused variable warning
58
97
}
59
98
60
99
typedef std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>::iterator
@@ -75,8 +114,17 @@ unsigned int cpu_count(){
75
114
NumberOfLogicalCPU += (unsigned int )count;
76
115
}
77
116
78
- #elif defined(__linux)
117
+ #endif
118
+
119
+ return NumberOfPhysicalCPU;
120
+
121
+ }
122
+
79
123
124
+ unsigned int RetrieveInformationFromCpuInfoFile (){
125
+
126
+ unsigned int NumberOfLogicalCPU = 0 ;
127
+ unsigned int NumberOfPhysicalCPU = 0 ;
80
128
std::string buffer;
81
129
82
130
FILE* fd = fopen (" /proc/cpuinfo" , " r" );
@@ -109,9 +157,8 @@ unsigned int cpu_count(){
109
157
}
110
158
111
159
uint64_t NumberOfSockets = PhysicalIDs.size ();
112
- NumberOfSockets = std::max (NumberOfSockets, (uint64_t )1 );
113
160
// Physical ids returned by Linux don't distinguish cores.
114
- // We want to record the total number of cores in this-> NumberOfPhysicalCPU
161
+ // We want to record the total number of cores in NumberOfPhysicalCPU
115
162
// (checking only the first proc)
116
163
std::string Cores = ExtractValueFromCpuInfoFile (buffer, " cpu cores" , CurrentPositionInFile);
117
164
if (Cores.empty ()) {
@@ -122,7 +169,15 @@ unsigned int cpu_count(){
122
169
NumberOfCoresPerSocket = std::max (NumberOfCoresPerSocket, 1u );
123
170
NumberOfPhysicalCPU = NumberOfCoresPerSocket * (unsigned int )NumberOfSockets;
124
171
125
- #elif defined(__APPLE__)
172
+ return NumberOfPhysicalCPU;
173
+
174
+ }
175
+
176
+ unsigned int ParseSysCtl (){
177
+
178
+ unsigned int NumberOfPhysicalCPU = 0 ;
179
+
180
+ #ifdef __APPLE__
126
181
127
182
int N;
128
183
size_t size = sizeof (N);
@@ -136,20 +191,39 @@ unsigned int cpu_count(){
136
191
NumberOfPhysicalCPU = N;
137
192
}
138
193
139
- #elif defined(_SC_NPROCESSORS_ONLN)
194
+ #endif
195
+
196
+ return NumberOfPhysicalCPU;
140
197
141
- long N = sysconf (_SC_NPROCESSORS_ONLN);
142
- if (N > 0 )
143
- NumberOfPhysicalCPU = static_cast <unsigned int >(N);
198
+ }
199
+
200
+ unsigned int QueryProcessorBySysconf (){
201
+
202
+ unsigned int NumberOfPhysicalCPU = 0 ;
203
+
204
+ #if defined(_SC_NPROCESSORS_ONLN)
205
+
206
+ long c = sysconf (_SC_NPROCESSORS_ONLN);
207
+ if (c > 0 )
208
+ NumberOfPhysicalCPU = static_cast <unsigned int >(c);
144
209
145
- #else
146
- NumberOfPhysicalCPU = std::thread::hardware_concurrency ();
147
210
#endif
148
211
149
- return NumberOfPhysicalCPU;
212
+ return NumberOfPhysicalCPU;
150
213
151
214
}
152
215
216
+ unsigned int QueryThreads (){
217
+ // fallback, doesn't consider hyperthreading
218
+
219
+ unsigned int NumberOfLogicalCPU = std::thread::hardware_concurrency ();
220
+ unsigned int NumberOfPhysicalCPU = NumberOfLogicalCPU;
221
+
222
+ return NumberOfPhysicalCPU;
223
+
224
+ }
225
+
226
+
153
227
/* * Extract a value from the CPUInfo file */
154
228
std::string ExtractValueFromCpuInfoFile (std::string buffer, const char * word,
155
229
size_t & CurrentPositionInFile, size_t init)
0 commit comments