31#include <sys/sysctl.h>
32#elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
36#elif defined(_WIN32) || defined(_WIN64)
40#ifndef WIN32_LEAN_AND_MEAN
41#define WIN32_LEAN_AND_MEAN
52#if defined(_WIN32) || defined(_WIN64)
62CountSetBits(ULONG_PTR pBitMask) {
63 DWORD dwLeftShift =
sizeof(ULONG_PTR) * 8 - 1;
64 DWORD dwBitSetCount = 0;
65 ULONG_PTR pBitTest = (ULONG_PTR) 1 << dwLeftShift;
67 for (DWORD i = 0; i <= dwLeftShift; ++i) {
68 dwBitSetCount += ((pBitMask & pBitTest) ? 1 : 0);
92template <
typename T,
typename TCleaner>
95 return std::unique_ptr<typename std::remove_pointer<T>::type, TCleaner>(handle,
109template <
typename TCleaner>
112 return std::unique_ptr<void, TCleaner>(handle, cleaner);
124template <
typename TCleaner>
127 return std::unique_ptr<void, TCleaner>(&cleaner, cleaner);
140 CPU(
const CPU &) =
delete;
141 CPU(CPU &&)
noexcept =
delete;
144 CPU &operator=(
const CPU &) =
delete;
145 CPU &operator=(CPU &&)
noexcept =
delete;
154#if defined(__APPLE__)
156 size_t size =
sizeof(result);
157 if (sysctlbyname(
"machdep.cpu.brand_string", result, &size,
nullptr, 0) == 0)
161#elif defined(unix) || defined(__unix) || defined(__unix__)
162 static std::regex pattern(
"model name(.*): (.*)");
165 std::ifstream stream(
"/proc/cpuinfo");
166 while (getline(stream, line)) {
168 if (std::regex_match(line, matches, pattern))
173#elif defined(_WIN32) || defined(_WIN64)
175 LONG lError = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
176 "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
177 0, KEY_READ, &hKeyProcessor);
178 if (lError != ERROR_SUCCESS)
182 auto key =
resource(hKeyProcessor, [](HKEY hKey) { RegCloseKey(hKey); });
184 CHAR pBuffer[_MAX_PATH] = {0};
185 DWORD dwBufferSize =
sizeof(pBuffer);
186 lError = RegQueryValueExA(key.get(),
"ProcessorNameString",
nullptr,
nullptr,
187 (LPBYTE) pBuffer, &dwBufferSize);
188 if (lError != ERROR_SUCCESS)
191 return std::string(pBuffer);
193#error Unsupported platform
203#if defined(__APPLE__)
205 size_t logical_size =
sizeof(logical);
206 if (sysctlbyname(
"hw.logicalcpu", &logical, &logical_size,
nullptr, 0) != 0)
210#elif defined(unix) || defined(__unix) || defined(__unix__)
211 long processors = sysconf(_SC_NPROCESSORS_ONLN);
213#elif defined(_WIN32) || defined(_WIN64)
216 return si.dwNumberOfProcessors;
218#error Unsupported platform
244 static std::pair<int, int>
246#if defined(__APPLE__)
248 size_t logical_size =
sizeof(logical);
249 if (sysctlbyname(
"hw.logicalcpu", &logical, &logical_size,
nullptr, 0) != 0)
253 size_t physical_size =
sizeof(physical);
254 if (sysctlbyname(
"hw.physicalcpu", &physical, &physical_size,
nullptr, 0) != 0)
257 return std::make_pair(logical, physical);
258#elif defined(unix) || defined(__unix) || defined(__unix__)
259 long processors = sysconf(_SC_NPROCESSORS_ONLN);
260 return std::make_pair(processors, processors);
261#elif defined(_WIN32) || defined(_WIN64)
262 BOOL allocated = FALSE;
263 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION pBuffer =
nullptr;
267 BOOL bResult = GetLogicalProcessorInformation(pBuffer, &dwLength);
268 if (bResult == FALSE) {
269 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
270 if (pBuffer !=
nullptr)
273 (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION) std::malloc(dwLength);
274 if (pBuffer ==
nullptr)
275 return std::make_pair(-1, -1);
277 return std::make_pair(-1, -1);
282 std::pair<int, int> result(0, 0);
283 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION pCurrent = pBuffer;
286 while (dwOffset +
sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= dwLength) {
287 switch (pCurrent->Relationship) {
288 case RelationProcessorCore:
289 result.first += Internals::CountSetBits(pCurrent->ProcessorMask);
292 case RelationNumaNode:
294 case RelationProcessorPackage:
297 return std::make_pair(-1, -1);
299 dwOffset +=
sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
307#error Unsupported platform
317#if defined(__APPLE__)
318 uint64_t frequency = 0;
319 size_t size =
sizeof(frequency);
320 if (sysctlbyname(
"hw.cpufrequency", &frequency, &size,
nullptr, 0) == 0)
324#elif defined(unix) || defined(__unix) || defined(__unix__)
325 static std::regex pattern(
"cpu MHz(.*): (.*)");
328 std::ifstream stream(
"/proc/cpuinfo");
329 while (getline(stream, line)) {
331 if (std::regex_match(line, matches, pattern))
332 return (int64_t) (atof(matches[2].str().c_str()) * 1000000);
336#elif defined(_WIN32) || defined(_WIN64)
338 long lError = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
339 "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
340 0, KEY_READ, &hKeyProcessor);
341 if (lError != ERROR_SUCCESS)
345 auto key =
resource(hKeyProcessor, [](HKEY hKey) { RegCloseKey(hKey); });
348 DWORD dwBufferSize =
sizeof(DWORD);
349 lError = RegQueryValueExA(key.get(),
"~MHz",
nullptr,
nullptr, (LPBYTE) &dwMHz,
351 if (lError != ERROR_SUCCESS)
354 return dwMHz * 1000000;
356#error Unsupported platform
367 return (cores.first != cores.second);
374#include <emmintrin.h>
391#elif defined(_MSC_VER) && _MSC_VER >= 1800 && (defined(_M_X64) || defined(_M_IX86))
413 std::this_thread::yield();
static std::string Architecture()
Gets the CPU architecture name/description.
Definition cpu.h:153
static bool HyperThreading()
Checks if hyperthreading is enabled.
Definition cpu.h:365
static int Affinity()
Gets the number of logical processors available to the process.
Definition cpu.h:202
static std::pair< int, int > TotalCores()
Gets both logical and physical core counts.
Definition cpu.h:245
static int LogicalCores()
Gets the number of logical CPU cores.
Definition cpu.h:227
static int PhysicalCores()
Gets the number of physical CPU cores.
Definition cpu.h:236
static int64_t ClockSpeed()
Gets the CPU clock speed in Hz.
Definition cpu.h:316
auto resource(T handle, TCleaner cleaner)
Creates a unique_ptr with a custom deleter for a resource.
Definition cpu.h:94
void spin_loop_pause() noexcept
Fallback implementation of spin_loop_pause for platforms without CPU pause.
Definition cpu.h:412
Internal helper functions for CPU information.