How to Find Out the Number of Cpus Using Python

How to find out the number of CPUs using python

If you're interested into the number of processors available to your current process, you have to check cpuset first. Otherwise (or if cpuset is not in use), multiprocessing.cpu_count() is the way to go in Python 2.6 and newer. The following method falls back to a couple of alternative methods in older versions of Python:

import os
import re
import subprocess

def available_cpu_count():
""" Number of available virtual or physical CPUs on this system, i.e.
user/real as output by time(1) when called with an optimally scaling
userspace-only program"""

# cpuset
# cpuset may restrict the number of *available* processors
try:
m = re.search(r'(?m)^Cpus_allowed:\s*(.*)$',
open('/proc/self/status').read())
if m:
res = bin(int(m.group(1).replace(',', ''), 16)).count('1')
if res > 0:
return res
except IOError:
pass

# Python 2.6+
try:
import multiprocessing
return multiprocessing.cpu_count()
except (ImportError, NotImplementedError):
pass

# https://github.com/giampaolo/psutil
try:
import psutil
return psutil.cpu_count() # psutil.NUM_CPUS on old versions
except (ImportError, AttributeError):
pass

# POSIX
try:
res = int(os.sysconf('SC_NPROCESSORS_ONLN'))

if res > 0:
return res
except (AttributeError, ValueError):
pass

# Windows
try:
res = int(os.environ['NUMBER_OF_PROCESSORS'])

if res > 0:
return res
except (KeyError, ValueError):
pass

# jython
try:
from java.lang import Runtime
runtime = Runtime.getRuntime()
res = runtime.availableProcessors()
if res > 0:
return res
except ImportError:
pass

# BSD
try:
sysctl = subprocess.Popen(['sysctl', '-n', 'hw.ncpu'],
stdout=subprocess.PIPE)
scStdout = sysctl.communicate()[0]
res = int(scStdout)

if res > 0:
return res
except (OSError, ValueError):
pass

# Linux
try:
res = open('/proc/cpuinfo').read().count('processor\t:')

if res > 0:
return res
except IOError:
pass

# Solaris
try:
pseudoDevices = os.listdir('/devices/pseudo/')
res = 0
for pd in pseudoDevices:
if re.match(r'^cpuid@[0-9]+$', pd):
res += 1

if res > 0:
return res
except OSError:
pass

# Other UNIXes (heuristic)
try:
try:
dmesg = open('/var/run/dmesg.boot').read()
except IOError:
dmesgProcess = subprocess.Popen(['dmesg'], stdout=subprocess.PIPE)
dmesg = dmesgProcess.communicate()[0]

res = 0
while '\ncpu' + str(res) + ':' in dmesg:
res += 1

if res > 0:
return res
except OSError:
pass

raise Exception('Can not determine number of CPUs on this system')

Portable way of detecting number of *usable* CPUs in Python

I don't think you will get any truly portable answers, so I will give a correct one.

The correct* answer for Linux is len(os.sched_getaffinity(pid)), where pid may be 0 for the current process. This function is exposed in Python 3.3 and later; if you need it in earlier, you'll have to do some fancy cffi coding.

Edit: you might try to see if you can use a function int omp_get_num_procs(); if it exists, it is the only meaningful answer I found on this question but I haven't tried it from Python.

How to determine the maximum number of processes that can be run per CPU core using python?

The number of processes a CPU core can run simultaneously is equal to the number of threads per CPU core. And to get the number of threads per CPU core in python you can do something like this:

import psutil
total_threads = psutil.cpu_count()/psutil.cpu_count(logical=False)
print('You can run {} processes per CPU core simultaneously'.format(total_threads))

To check different processors your script can run on you can use:

print(psutil.Process().cpu_affinity())

Multiprocessing in python vs number of cores

First you are mixing up threads and processes: in Python only threads not processes have to share a lock on their interpreter.
If your are using the multiprocessing library then, your are using Python processes which have their own interpreter.

When you are using Python processes, their execution is managed by your operating system scheduler, in the same manner as every other processes in your computer.
If you have more processes than CPU cores then the extra processes are waiting in background to be scheduled.
This usually happen when an other process terminates, wait on an IO, or periodically with clock interrupts.

How to get the number of threads per cores in python

You can use psutil module in python3.

python3 -m pip install psutil

The psutil.cpu_count method returns the number of logical CPUs in the system (same as os.cpu_count in Python 3.4) or None if undetermined. logical cores means the number of physical cores multiplied by the number of threads that can run on each core (this is known as Hyper Threading). If logical is False return the number of physical cores only (Hyper Thread CPUs are excluded) or None if undetermined.

import psutil

threads_count = psutil.cpu_count() / psutil.cpu_count(logical=False)

Get number of busy CPUs in Python

There are a number of complications...

  • you can't determine which CPUs are busy

Processes (and threads) are scheduled by the Linux kernel on any CPU. Even determining the "current CPU" is awkward -- see How can I see which CPU core a thread is running in?

  • multiprocessing.Pool is designed to start up N workers, which run "forever." Each accepts a task from a queue, does some work, then outputs data. A Pool doesn't change size.

Two suggestions:

  • the uptime command outputs something like this:

19:05:07 up 4 days, 20:43, 3 users, load average:0.99, 1.01, 0.82

The last three numbers are the "load average" over the last minute, five minutes, and 15 minutes. Consider using the first number to load-balance your application.

  • consider having your application do time.sleep(factor) after completing each piece of work.

Thus you can increase the factor when the system is busy (high load average), and make the delay shorter when the system is more idle (low load; ie surfing). Pool stays same size.

Is there a pytorch method to check the number of cpus?

just use this :

os.cpu_count()

How many processors should be used with multiprocessing.Pool?

The difference between the two is clearly stated in the doc:

multiprocessing.cpu_count()
Return the number of CPUs in the system.

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)).

So even if you are on a 128-core system, your program could have been somehow limited to only run on a specific set of 10 out of the 128 available CPUs. Since affinity also applies to child threads and processes, it doesn't make much sense to spawn more than 10. You could however try to increase the number of available CPUs through os.sched_setaffinity() before starting your pool.

import os
import multiprocessing as mp

cpu_count = mp.cpu_count()

if len(os.sched_getaffinity(0)) < cpu_count:
try:
os.sched_setaffinity(0, range(cpu_count))
except OSError:
print('Could not set affinity')

n = max(len(os.sched_getaffinity(0)), 96)
print('Using', n, 'processes for the pool')

pool = mp.Pool(n)
# ...

See also man 2 sched_setaffinity.



Related Topics



Leave a reply



Submit