Reputation:
My iMac Pro has an Intel 3GHz Xeon 10-core W-2150B processor.
My understanding is that this is one CPU albeit with 10 cores.
Now consider this trivial Python code:-
import os
print(f'Number of CPUs={os.cpu_count()}')
This will emit:- Number of CPUs=20
...whereas I would expect it to tell that there's 1 CPU or, arguably, 10.
What's going on here?
Upvotes: 1
Views: 439
Reputation: 369458
Python simply reports the number it gets from the OS. The OS simply reports the number it gets from the firmware. The firmware simply reports the number it gets from the CPU.
So, the short answer to your question is: Python is reporting 20 CPUs because that is what Intel has decided to report.
Now, the question is of course: does it make sense to report 20 CPUs? And the answer to that is not simple. At the time when the system calls that report the number of CPUs were designed, the relationship between sockets, chips, dies, CPUs, execution cores, and threads was a very simple 1:1:1:1:1:1 relationship. So, nobody ever thought about whether the number should mean the number of sockets, the number of CPUs, the number of cores, the number of threads, or whatever, because it didn't matter. It was all the same.
But nowadays, the relationship is much more complex:
So, you have to think about what it actually is that you are interested in. And Intel has decided that what you are most likely interested in, is the number of hardware threads that can be executed in parallel. And since on the particular CPU that you have, there are 10 execution cores in the CPU and each core can execute 2 threads, the CPU reports itself as 20 CPUs, even though it is only 1 CPU.
Because as a programmer, you most likely don't care how many blobs of sand you have in your computer, but what you can do with them.
Although in reality, the question is even more complex because the two threads per execution core are not totally independent, and depending on your specific workload, you might actually only want to use one thread per CPU, so you might actually need to know the difference between execution cores and threads. Additionally, some recent CPUs have different types of cores, e.g. the Apple M1 CPU has 8 cores with identical Instruction Sets, but 4 of them are optimized for resources (and thus somewhat slower) and 4 of them are optimized for performance (and thus consume more power and produce more waste heat).
The current SPARC CPUs from Oracle can schedule up to 8 threads per execution core, of which they can execute up to 2 simultaneously. So, should this CPU report itself as 2 CPUs or 8? And so on, there are dozens of such examples that show that the answer to the question "how many CPUs do I have" is not so simple, and depends heavily on what, precisely, you actually mean by "CPU".
If you want to write high-performance and/or energy-efficient code, a simple number is not enough. You need to know the full hierarchy and dependencies between the different elements.
Upvotes: 2
Reputation: 1009
EDIT: check out this thread: https://stackoverflow.com/a/1715612/9983575 - there's multiple different ways discussed in the different answers, and a simple one is to run sysctl -n hw.ncpu
from the command line (note this is the command line, and not the python interpreter). This should match the output you see from
import os
os.cpu_count()
Specifically, some more details from the comments section:
how many physical cores does the machine have and what chip is it? If it's a core i7 with 2 physical cores for example, it will show as 4 because the chip supports hyper-threading and presents itself to the OS as if it has 4 addressable cores. – jkp Sep 26 '11 at 8:51
ORIGINAL ANSWER:
Just tried this and I also got twice the number of CPUs as expected, and looking at other documentation and methods didn't help much.
Things I checked:
help(os.cpu_count)
):Help on built-in function cpu_count in module posix:
cpu_count()
Return the number of CPUs in the system; return None if indeterminable.
This number is not equivalent to the number of CPUs the current process can
use. The number of usable CPUs can be obtained with
``len(os.sched_getaffinity(0))``
It also looks like os.sched_getaffinity(0)
doesn't seem to work for me locally and I can't figure out why, since the method is included in both help(os.cpu_count)
and https://docs.python.org/3/library/os.html#os.sched_getaffinity.
My guess is that each core on a Mac has 2 CPUs - this would explain the See the EDIT and links - my understanding is that hyperthreading causes "1 physical core" to appear as "2 cores" to the operating system20
result for you on a 10 core machine, and the 8
result for me on a quad core machine. I haven't been able to find any specifics about Mac cores/CPUs yet, but will update my answer here if I do.
Upvotes: 0