548

Is there a way to determine how many cores a machine has from C/C++ in a platform-independent way? If no such thing exists, what about determining it per-platform (Windows/*nix/Mac)?

Bensuperpc
  • 1,275
  • 1
  • 14
  • 21
hazzen
  • 17,128
  • 6
  • 41
  • 33
  • 4
    If you want to use it find out how many threads to start please use NUMBER_OF_PROCESSORS as primary measure. I leave it as an excercise to you why this is much better (if people would use it more) then using hardware cores. How much cores belong to your program are an environmental issue! – Lothar Dec 14 '12 at 19:55
  • Note that `std::thread::hardware_concurrency` returns the number of physical CPU cores, but `nproc` in Linux shows only the number of CPU cores the current process can run on, which can be controlled with `sched_setaffinity`. I haven't found a way to get that instead from standard C++:, see e.g. in Python: https://stackoverflow.com/questions/1006289/how-to-find-out-the-number-of-cpus-using-python/55423170#55423170 – Ciro Santilli OurBigBook.com May 05 '19 at 18:52

20 Answers20

837

C++11

#include <thread>

//may return 0 when not able to detect
const auto processor_count = std::thread::hardware_concurrency();

Reference: std::thread::hardware_concurrency


In C++ prior to C++11, there's no portable way. Instead, you'll need to use one or more of the following methods (guarded by appropriate #ifdef lines):

  • Win32

    SYSTEM_INFO sysinfo;
    GetSystemInfo(&sysinfo);
    int numCPU = sysinfo.dwNumberOfProcessors;
    
  • Linux, Solaris, AIX and Mac OS X >=10.4 (i.e. Tiger onwards)

    int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
    
  • FreeBSD, MacOS X, NetBSD, OpenBSD, etc.

    int mib[4];
    int numCPU;
    std::size_t len = sizeof(numCPU); 
    
    /* set the mib for hw.ncpu */
    mib[0] = CTL_HW;
    mib[1] = HW_AVAILCPU;  // alternatively, try HW_NCPU;
    
    /* get the number of CPUs from the system */
    sysctl(mib, 2, &numCPU, &len, NULL, 0);
    
    if (numCPU < 1) 
    {
        mib[1] = HW_NCPU;
        sysctl(mib, 2, &numCPU, &len, NULL, 0);
        if (numCPU < 1)
            numCPU = 1;
    }
    
  • HPUX

    int numCPU = mpctl(MPC_GETNUMSPUS, NULL, NULL);
    
  • IRIX

    int numCPU = sysconf(_SC_NPROC_ONLN);
    
  • Objective-C (Mac OS X >=10.5 or iOS)

    NSUInteger a = [[NSProcessInfo processInfo] processorCount];
    NSUInteger b = [[NSProcessInfo processInfo] activeProcessorCount];
    
BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185
oz10
  • 153,307
  • 27
  • 93
  • 128
  • Add preprocessor directives so that only the OS-specific code is executed. – mcandre Jun 21 '10 at 19:17
  • 8
    @mcandre: that is left as an exercise for the reader. If I were implementing I'd probably use template-policy approach where the policy was defined in preprocessor directives. Or... you could use boost thread::hardware_concurrency(). – oz10 Jun 22 '10 at 20:26
  • 4
    as a point of clarification the Win32 solution returns total number of cores (what was asked for) not total number of physical CPUs. – Eric Feb 03 '11 at 17:59
  • 1
    The Linux/Solaris/AIX way also works on FreeBSD and has since at least 2006. Also, that will return the CPUs online, if a system is capable of turning some off they might not be counted. Calling sysconf with "_SC_NPROCESSORS_CONF" will return the total CPUs configured. – Chris S Apr 23 '11 at 18:43
  • Note that the fbsd version is much simpler - this is a combined example so it looks complicated. – Good Person Dec 19 '12 at 22:52
  • 3
    A couple of things to be aware of. `HW_NCPU` is deprecated on OS X. On Windows `GetSystemInfo` is only useful if your system has 32 logical processors or less, use `GetLogicalProcessorInformation` for systems that have more than 32 logical processors. –  Feb 26 '13 at 10:40
  • @Eric Supposedly it's worse than that and it actually returns the number of logical cores, so if you have hyperthreading turned on, it might be larger than you expect. It isn't very clear because Microsoft's docs from two different versions of the same API say two different things (one worded it as "physical" and the other worded it as "logical".) – Hakanai Apr 30 '13 at 05:57
  • 1
    @Trejkaz [the documentaion](https://msdn.microsoft.com/de-de/library/windows/desktop/ms724958(v=vs.85).aspx) clearly says "logical" - which is always counting HT cores, the word *"physical"* **always** refers to cores reported by the BIOS / UEFI as cores may also be emulated / virtualized. You can differentiate between HT/non-HT cores with functions like [GetLogicalProcessorInformation](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683194(v=vs.85).aspx), for instance. Note : HT != emulation or virtualization, thats a **big** difference, HT is a hardware optimization, so to speak – specializt Jun 27 '16 at 09:02
  • @specializt yes, if you ignore the bit about one page in the docs wording it as "physical" and the other wording it as "logical", it is pretty clear in its meaning. Or alternatively if the docs were corrected between me making that comment and you making your reply, that would also resolve the issue. – Hakanai Jun 29 '16 at 05:23
  • @Trejkaz i would like to see that doc - MSDN usually does not have such major issues, i highly doubt that they actually mixed it up, in fact they even mention the difference and connection between these terms : *"For information about the physical processors shared by logical processors, call GetLogicalProcessorInformationEx with the RelationshipType parameter set to RelationProcessorPackage (3)."* – specializt Jun 29 '16 at 08:59
  • @specializt yeah, too bad I didn't link it at the time. It's highly unlikely that I would find it now, even if I searched for it. :/ – Hakanai Jun 29 '16 at 23:10
  • because it doesnt exist. – specializt Jun 30 '16 at 07:40
  • Adding required headers (e.g. #include for linux) will make the answer perfect for future searchers. – MaMazav Jun 04 '17 at 12:40
  • 1
    **NOTE** that `std::thread::hardware_concurrency` implementations differ; Visual Studio takes into account affinity (returns 1 if process is restricted to one core etc.) whereas g++ does not. – vladr Sep 06 '17 at 16:43
  • If you are on a modern Windows and you need all the processors regardless of processor group (e.g. you're working with a system with more than 64 processors) and you're targeting Windows 7/2008 R2 or above you can use [`GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS) `](https://msdn.microsoft.com/en-us/library/windows/desktop/dd405489(v=vs.85).aspx) to retrieve a complete count. See https://github.com/python/cpython/commit/58521fdba1657f6553a1ead5cbaa100967a167b3 for an example. – Anon Feb 16 '18 at 20:58
  • What is the name of the header file where the functions (such as, `sysconf`, `sysctl`, etc.) are defined? – akm Feb 14 '22 at 06:15
230

This functionality is part of the C++11 standard.

#include <thread>

unsigned int nthreads = std::thread::hardware_concurrency();

For older compilers, you can use the Boost.Thread library.

#include <boost/thread.hpp>

unsigned int nthreads = boost::thread::hardware_concurrency();

In either case, hardware_concurrency() returns the number of threads that the hardware is capable of executing concurrently based on the number of CPU cores and hyper-threading units.

Ferruccio
  • 98,941
  • 38
  • 226
  • 299
  • 1
    Seconded...was going to use the sample code above and some preprocessor macros to expose a single function, but the hard-work was done for me. – jkp May 22 '09 at 08:35
  • For win32, it's a call to GetSystemInfo. (As of boost Version 1.41.0) Does that capture all the info to determine how many worker threads would be effective? Does one need to consider both the number of cores and hyper-threading? unsigned thread::hardware_concurrency() { SYSTEM_INFO info={0}; GetSystemInfo(&info); return info.dwNumberOfProcessors; } – Jive Dadson Apr 21 '10 at 19:51
  • According to MSDN, GetSystemInfo() returns the number of "physical processors" in dwNumberOfProcessors but it doesn't define what it means by that. The Boost documentation seems to claim that it includes hyperthreading units. – Ferruccio Apr 21 '10 at 20:26
  • 1
    see http://stackoverflow.com/questions/642348/does-getsysteminfo-give-you-the-total-number-of-virtual-cpus-i-e-hyper-threaded for hyperthreading – naugtur May 06 '10 at 10:58
65

OpenMP is supported on many platforms (including Visual Studio 2005) and it offers a

int omp_get_num_procs();

function that returns the number of processors/cores available at the time of call.

angainor
  • 11,760
  • 2
  • 36
  • 56
macbirdie
  • 16,086
  • 6
  • 47
  • 54
  • because it is a wrong answer. From http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37586 "omp_get_num_procs () will only return smaller number than the number of system CPUs online, if GOMP_CPU_AFFINITY env var is used, or if the calling process and/or thread has CPU affinity limited to a subset of CPUs". So if you earlier call e.g., `sched_setaffinity` this will not work. – angainor Nov 11 '13 at 11:53
  • 12
    This function returns the number of CPUs available to the calling process. Isn't it the most common use case anyway? Outsize of some useless reporting purposes, the actual number of CPU hardware cores is not relevant to you if you cannot take advantage of them in your code. – macbirdie Nov 14 '13 at 20:24
  • @EvanTeran Besides the fact that it was the purpose of the question, it can of course be useful. For example, for the purpose of setting thread affinity. Say, I want to run 4 threads bound to four last CPU cores on my machine, instead of four first cores. And besides, there are other ways of parallelizing the code except of OpenMP. I may want to spawn pthreads myself. Those are surely available and not restricted by OpenMP environment variables. – angainor Nov 25 '13 at 21:41
  • 2
    This returns the number of logical CPUs, not cores (physical CPUs) as such. – Michael Konečný Jun 10 '16 at 15:41
40

If you have assembly-language access, you can use the CPUID instruction to get all sorts of information about the CPU. It's portable between operating systems, though you'll need to use manufacturer-specific information to determine how to find the number of cores. Here's a document that describes how to do it on Intel chips, and page 11 of this one describes the AMD specification.

tshepang
  • 12,111
  • 21
  • 91
  • 136
Head Geek
  • 38,128
  • 22
  • 77
  • 87
  • 4
    It may have been downvoted because the question is tagged as C++ and this answer doesn't apply to systems running C++ on non-x86 architectures (ARM, PPC, etc.). I'm not saying it's a good reason to downvote an answer, just a possibility. – Ferruccio Feb 23 '11 at 12:10
  • 3
    One pitfall of this method is if you're using CPUID to detect HyperThreading on Intel processors. I ran into this problem on my laptop: while the CPU that I put into the machine supports HyperThreading (and, of course, reports that it does via CPUID), the BIOS does not. Therefore, you shouldn't attempt to utilize HT capability simply from a CPUID read. Since you can't query the BIOS about HT support (no way that I've seen), the OS should be queried to get the logical processor count. – Chuck R May 29 '13 at 08:18
37

(Almost) Platform Independent function in c-code

#ifdef _WIN32
#include <windows.h>
#elif MACOS
#include <sys/param.h>
#include <sys/sysctl.h>
#else
#include <unistd.h>
#endif

int getNumCores() {
#ifdef WIN32
    SYSTEM_INFO sysinfo;
    GetSystemInfo(&sysinfo);
    return sysinfo.dwNumberOfProcessors;
#elif MACOS
    int nm[2];
    size_t len = 4;
    uint32_t count;

    nm[0] = CTL_HW; nm[1] = HW_AVAILCPU;
    sysctl(nm, 2, &count, &len, NULL, 0);

    if(count < 1) {
        nm[1] = HW_NCPU;
        sysctl(nm, 2, &count, &len, NULL, 0);
        if(count < 1) { count = 1; }
    }
    return count;
#else
    return sysconf(_SC_NPROCESSORS_ONLN);
#endif
}
Dirk-Jan Kroon
  • 379
  • 3
  • 2
  • Seems `HW_NCPU` is deprecated on OS X [source](https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/sysctl.3.html) –  Feb 26 '13 at 10:26
  • @user152949 what is the proposed alternative? (link is broken) – ideasman42 Oct 09 '21 at 23:44
17

On Linux, you can read the /proc/cpuinfo file and count the cores.

JesperE
  • 63,317
  • 21
  • 138
  • 197
  • Except that that also counts hyperthreaded or other SMT solutions as more cores... – jakobengblom2 Oct 12 '08 at 19:08
  • 13
    @Arafangion: hyperthreading is not true parallel execution, it's a technology for reducing context switching overhead. A hyperthreaded cpu can only *execute* one thread at a time, but it can store the architectural state (register values etc.) of two threads at the same time. The performance characteristics are very different from having two cores. – Wim Coenen Jul 10 '09 at 04:17
  • 11
    @Wim: That's not completely correct. CPUs with hyperthreading generally have multiple ALUs and can dispatch multiple instructions per cycle. If due to data dependencies and stalls, not all the ALUs can be kept busy by one thread, those ALUs will instead be used for simultaneous execution of the second hardware thread. – Ben Voigt Dec 14 '13 at 16:45
  • 1
    This "works" but not for dockerized applications. Reading the /proc/cpuinfo returns the number of cores for the host, not the number of cores in your "virtualized container". https://stackoverflow.com/a/47547845/387150 – John Rocha Aug 23 '22 at 17:38
12

Note that "number of cores" might not be a particularly useful number, you might have to qualify it a bit more. How do you want to count multi-threaded CPUs such as Intel HT, IBM Power5 and Power6, and most famously, Sun's Niagara/UltraSparc T1 and T2? Or even more interesting, the MIPS 1004k with its two levels of hardware threading (supervisor AND user-level)... Not to mention what happens when you move into hypervisor-supported systems where the hardware might have tens of CPUs but your particular OS only sees a few.

The best you can hope for is to tell the number of logical processing units that you have in your local OS partition. Forget about seeing the true machine unless you are a hypervisor. The only exception to this rule today is in x86 land, but the end of non-virtual machines is coming fast...

tshepang
  • 12,111
  • 21
  • 91
  • 136
jakobengblom2
  • 5,531
  • 2
  • 25
  • 33
9

Windows (x64 and Win32) and C++11

The number of groups of logical processors sharing a single processor core. (Using GetLogicalProcessorInformationEx, see GetLogicalProcessorInformation as well)

size_t NumberOfPhysicalCores() noexcept {

    DWORD length = 0;
    const BOOL result_first = GetLogicalProcessorInformationEx(RelationProcessorCore, nullptr, &length);
    assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER);

    std::unique_ptr< uint8_t[] > buffer(new uint8_t[length]);
    const PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX info = 
            reinterpret_cast< PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX >(buffer.get());

    const BOOL result_second = GetLogicalProcessorInformationEx(RelationProcessorCore, info, &length);
    assert(result_second != FALSE);

    size_t nb_physical_cores = 0;
    size_t offset = 0;
    do {
        const PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX current_info =
            reinterpret_cast< PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX >(buffer.get() + offset);
        offset += current_info->Size;
        ++nb_physical_cores;
    } while (offset < length);
        
    return nb_physical_cores;
}

Note that the implementation of NumberOfPhysicalCores is IMHO far from trivial (i.e. "use GetLogicalProcessorInformation or GetLogicalProcessorInformationEx"). Instead it is rather subtle if one reads the documentation (explicitly present for GetLogicalProcessorInformation and implicitly present for GetLogicalProcessorInformationEx) at MSDN.

The number of logical processors. (Using GetSystemInfo)

size_t NumberOfSystemCores() noexcept {
    SYSTEM_INFO system_info;
    ZeroMemory(&system_info, sizeof(system_info));
    
    GetSystemInfo(&system_info);
    
    return static_cast< size_t >(system_info.dwNumberOfProcessors);
}

Note that both methods can easily be converted to C/C++98/C++03.

Community
  • 1
  • 1
Matthias
  • 4,481
  • 12
  • 45
  • 84
  • @KeyWeeUsr Thanks Windows programming is somewhat far from trivial and logical. In the mean time, I use a slightly more updated [C++17 version](https://github.com/matt77hias/MAGE/blob/master/MAGE/Utilities/src/parallel/parallel.cpp#L17) which is also more correct according to the static analyzer PVS-Studio with regard to some `size_t` casts. (Although, msvc++ does not complain at W4.) – Matthias Aug 11 '18 at 12:44
8

One more Windows recipe: use system-wide environment variable NUMBER_OF_PROCESSORS:

printf("%d\n", atoi(getenv("NUMBER_OF_PROCESSORS")));
Constantin
  • 27,478
  • 10
  • 60
  • 79
7

You probably won't be able to get it in a platform independent way. Windows you get number of processors.

Win32 System Information

tshepang
  • 12,111
  • 21
  • 91
  • 136
Ken
  • 2,092
  • 1
  • 19
  • 16
  • 1
    Carefull: Hyperthreaded processors say there are two. So you also need to see if the processor are hyperthread capable. – Martin York Sep 29 '08 at 20:46
5

More on OS X: sysconf(_SC_NPROCESSORS_ONLN) is available only versions >= 10.5, not 10.4.

An alternative is the HW_AVAILCPU/sysctl() BSD code which is available on versions >= 10.2.

Mysticial
  • 464,885
  • 45
  • 335
  • 332
sezero
  • 61
  • 1
  • 1
5

Unrelated to C++, but on Linux I usually do:

grep processor /proc/cpuinfo | wc -l

Handy for scripting languages like bash/perl/python/ruby.

tshepang
  • 12,111
  • 21
  • 91
  • 136
Chris
  • 953
  • 11
  • 16
4

Windows Server 2003 and later lets you leverage the GetLogicalProcessorInformation function

http://msdn.microsoft.com/en-us/library/ms683194.aspx

Chris Ballance
  • 33,810
  • 26
  • 104
  • 151
3

On linux the best programmatic way as far as I know is to use

sysconf(_SC_NPROCESSORS_CONF)

or

sysconf(_SC_NPROCESSORS_ONLN)

These aren't standard, but are in my man page for Linux.

tshepang
  • 12,111
  • 21
  • 91
  • 136
Evan Teran
  • 87,561
  • 32
  • 179
  • 238
3

On Linux, it's may not be safe to to use _SC_NPROCESSORS_ONLN as it's not part of POSIX standard and the sysconf manual states as much. So there's a possibility that _SC_NPROCESSORS_ONLN may not be present:

 These values also exist, but may not be standard.

     [...]     

     - _SC_NPROCESSORS_CONF
              The number of processors configured.   
     - _SC_NPROCESSORS_ONLN
              The number of processors currently online (available).

A simple approach would be to read /proc/stat or /proc/cpuinfo and count them:

#include<unistd.h>
#include<stdio.h>

int main(void)
{
char str[256];
int procCount = -1; // to offset for the first entry
FILE *fp;

if( (fp = fopen("/proc/stat", "r")) )
{
  while(fgets(str, sizeof str, fp))
  if( !memcmp(str, "cpu", 3) ) procCount++;
}

if ( procCount == -1) 
{ 
printf("Unable to get proc count. Defaulting to 2");
procCount=2;
}

printf("Proc Count:%d\n", procCount);
return 0;
}

Using /proc/cpuinfo:

#include<unistd.h>
#include<stdio.h>

int main(void)
{
char str[256];
int procCount = 0;
FILE *fp;

if( (fp = fopen("/proc/cpuinfo", "r")) )
{
  while(fgets(str, sizeof str, fp))
  if( !memcmp(str, "processor", 9) ) procCount++;
}

if ( !procCount ) 
{ 
printf("Unable to get proc count. Defaulting to 2");
procCount=2;
}

printf("Proc Count:%d\n", procCount);
return 0;
}

The same approach in shell using grep:

grep -c ^processor /proc/cpuinfo

Or

grep -c ^cpu /proc/stat # subtract 1 from the result
P.P
  • 117,907
  • 20
  • 175
  • 238
3

hwloc (http://www.open-mpi.org/projects/hwloc/) is worth looking at. Though requires another library integration into your code but it can provide all the information about your processor (number of cores, the topology, etc.)

Akhil
  • 2,269
  • 6
  • 32
  • 39
2

OS X alternative: The solution described earlier based on [[NSProcessInfo processInfo] processorCount] is only available on OS X 10.5.0, according to the docs. For earlier versions of OS X, use the Carbon function MPProcessors().

If you're a Cocoa programmer, don't be freaked out by the fact that this is Carbon. You just need to need to add the Carbon framework to your Xcode project and MPProcessors() will be available.

gauss256
  • 2,603
  • 4
  • 23
  • 23
2

For Win32:

While GetSystemInfo() gets you the number of logical processors, use GetLogicalProcessorInformationEx() to get the number of physical processors.

0
#include <stdint.h>

#if defined(__APPLE__) || defined(__FreeBSD__)
#include <sys/sysctl.h>

uint32_t num_physical_cores(void)
{
    uint32_t num_cores      = 0;
    size_t num_cores_len    = sizeof(num_cores);

    sysctlbyname("hw.physicalcpu", &num_cores, &num_cores_len, 0, 0);

    return num_cores;
}
#elif defined(__linux__)
#include <unistd.h>
#include <stdio.h>
uint32_t num_physical_cores(void)
{
    uint32_t lcores = 0, tsibs = 0;

    char buff[32];
    char path[64];

    for (lcores = 0;;lcores++) {
        FILE *cpu;

        snprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu%u/topology/thread_siblings_list", lcores);

        cpu = fopen(path, "r");
        if (!cpu) break;

        while (fscanf(cpu, "%[0-9]", buff)) {
            tsibs++;
            if (fgetc(cpu) != ',') break;
        }

        fclose(cpu);
    }

    return lcores / (tsibs / lcores);
}
#else
#error Unrecognized operating system
#endif

This should return the number of physical cores on the system. This is different than the number of logical cores which most of these answers provide. If you're looking to size a thread pool which performs no blocking I/O, and doesn't sleep, then you want to use the number of physical cores, not the number of logical (hyper threading) cores.

This answer only provides implementations for Linux and the BSDs.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Arran Cudbard-Bell
  • 5,912
  • 2
  • 26
  • 48
-2

you can use WMI in .net too but you're then dependent on the wmi service running etc. Sometimes it works locally, but then fail when the same code is run on servers. I believe that's a namespace issue, related to the "names" whose values you're reading.