ฉันต้องการทราบจำนวนซีพียูในเครื่องท้องถิ่นโดยใช้ Python ผลลัพธ์ควรuser/real
เป็นเอาต์พุตโดยtime(1)
เมื่อถูกเรียกด้วยการปรับขนาดโปรแกรม userspace-only อย่างเหมาะสมที่สุด
ฉันต้องการทราบจำนวนซีพียูในเครื่องท้องถิ่นโดยใช้ Python ผลลัพธ์ควรuser/real
เป็นเอาต์พุตโดยtime(1)
เมื่อถูกเรียกด้วยการปรับขนาดโปรแกรม userspace-only อย่างเหมาะสมที่สุด
คำตอบ:
หากคุณมี python พร้อมกับรุ่น> = 2.6 คุณสามารถใช้
import multiprocessing
multiprocessing.cpu_count()
http://docs.python.org/library/multiprocessing.html#multiprocessing.cpu_count
os.cpu_count()
หากคุณสนใจจำนวนโปรเซสเซอร์ที่มีอยู่สำหรับกระบวนการปัจจุบันของคุณคุณต้องตรวจสอบcpusetก่อน มิฉะนั้น (หรือหาก cpuset ไม่ได้ใช้งาน) multiprocessing.cpu_count()
เป็นวิธีที่จะใช้งานใน Python 2.6 และใหม่กว่า วิธีการต่อไปนี้กลับไปเป็นวิธีการสองทางใน 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')
/proc/self/status
จะเรียงตามลำดับ ff, f และ f --- สอดคล้องกับ 8, 4 และ 4 โดยคณิตศาสตร์ของคุณ (ถูกต้อง) อย่างไรก็ตามจำนวน CPU ที่แท้จริงตามลำดับคือ 4, 2 และ 1 ฉันพบว่าการนับจำนวนที่เกิดขึ้นของคำว่า "โปรเซสเซอร์" ใน/proc/cpuinfo
อาจเป็นวิธีที่ดีกว่า (หรือฉันมีคำถามผิดหรือเปล่า?)
/proc/cpuinfo
สิ่งนั้นหากสำหรับรายการใดรายการหนึ่งสำหรับ "ตัวประมวลผล" แต่ละตัวคุณคูณ "พี่น้อง" ด้วย "cpu cores" คุณได้รับหมายเลข "Cpus_allowed" ของคุณ และฉันรวบรวมว่าพี่น้องอ้างถึงไฮเปอร์เธรดดังนั้นการอ้างอิงของคุณถึง "เสมือน" แต่ความจริงก็คือตัวเลข "Cpus_allowed" ของคุณคือ 8 ใน MacPro ของฉันในขณะที่multiprocessing.cpu_count()
คำตอบของคุณคือ 4 ฉันเองopen('/proc/cpuinfo').read().count('processor')
ก็สร้าง 4 จำนวนแกนประมวลผลทางกายภาพ (โปรเซสเซอร์ดูอัลคอร์สองตัว)
open('/proc/self/status').read()
ลืมที่จะปิดไฟล์ ใช้with open('/proc/self/status') as f: f.read()
แทน
os.cpu_count()
with
เมื่อคุณพบกรณีที่คุณต้องการ
อีกทางเลือกหนึ่งคือการใช้psutil
ห้องสมุดซึ่งจะเป็นประโยชน์ในสถานการณ์เหล่านี้:
>>> import psutil
>>> psutil.cpu_count()
2
สิ่งนี้จะทำงานได้บนทุกแพลตฟอร์มที่รองรับโดยpsutil
(Unix และ Windows)
โปรดทราบว่าในบางโอกาสmultiprocessing.cpu_count
อาจเพิ่มสักNotImplementedError
ครู่psutil
เพื่อให้ได้จำนวนของ CPU นี่เป็นเพียงเพราะpsutil
ครั้งแรกพยายามที่จะใช้เทคนิคเดียวกันกับที่ใช้โดยmultiprocessing
และหากล้มเหลวก็จะใช้เทคนิคอื่น ๆ
psutil.cpu_count(logical = True)
psutil.cpu_count()
ให้ 12 (เป็น 6-core CPU พร้อม hyperthreading) นี่เป็นเพราะอาร์กิวเมนต์เริ่มต้นของlogical
เป็น True ดังนั้นคุณต้องเขียนอย่างชัดเจนpsutil.cpu_count(logical = False)
เพื่อรับจำนวน Cores ทางกายภาพ
ในหลาม 3.4+: os.cpu_count ()
multiprocessing.cpu_count()
ถูกนำมาใช้ในแง่ของฟังก์ชั่นนี้ แต่เพิ่มNotImplementedError
ว่าos.cpu_count()
ผลตอบแทนNone
("ไม่สามารถกำหนดจำนวนของ CPU")
cpu_count
ดูเพิ่มเติมเอกสารของ len(os.sched_getaffinity(0))
อาจจะดีกว่าขึ้นอยู่กับวัตถุประสงค์
os.cpu_count()
- เมื่อ OP ถาม) อาจแตกต่างจากจำนวนของ CPU ที่ใช้งานได้สำหรับกระบวนการปัจจุบัน ( os.sched_getaffinity(0)
)
os.sched_getaffinity(0)
คือไม่ได้มีอยู่ใน BSD ดังนั้นการใช้os.cpu_count()
จะต้อง (ไม่ห้องสมุดภายนอกอื่น ๆ ที่มี)
len(os.sched_getaffinity(0))
คือสิ่งที่คุณต้องการ
https://docs.python.org/3/library/os.html#os.sched_getaffinity
os.sched_getaffinity(0)
(เพิ่มใน Python 3) ส่งคืนชุดของ CPU ที่พร้อมใช้งานเนื่องจากการsched_setaffinity
เรียกระบบ Linuxซึ่ง จำกัด CPU ที่กระบวนการและลูกสามารถทำงานได้
0
หมายถึงการรับค่าสำหรับกระบวนการปัจจุบัน ฟังก์ชั่นส่งกลับของซีพียูได้รับอนุญาตจึงจำเป็นที่จะต้องset()
len()
multiprocessing.cpu_count()
ในทางกลับกันเพียงแค่ส่งคืนจำนวน CPU ทางกายภาพทั้งหมด
ความแตกต่างเป็นสิ่งสำคัญอย่างยิ่งเพราะระบบการจัดการคลัสเตอร์บางอย่างเช่นแพลตฟอร์ม LSFการใช้งาน CPU sched_getaffinity
งานกับขีด
ดังนั้นหากคุณใช้multiprocessing.cpu_count()
สคริปต์ของคุณอาจลองใช้วิธีการแกนมากกว่าที่มีอยู่ซึ่งอาจนำไปสู่การโอเวอร์โหลดและหมดเวลา
เราสามารถเห็นความแตกต่างอย่างชัดเจนโดยการ จำกัด ความสัมพันธ์กับtaskset
ยูทิลิตี้
ตัวอย่างเช่นถ้าฉัน จำกัด Python เพียง 1 หลัก (core 0) ในระบบ 16 core ของฉัน:
taskset -c 0 ./main.py
ด้วยสคริปต์ทดสอบ:
main.py
#!/usr/bin/env python3
import multiprocessing
import os
print(multiprocessing.cpu_count())
print(len(os.sched_getaffinity(0)))
ดังนั้นผลลัพธ์คือ:
16
1
nproc
อย่างไรก็ตามจะเคารพความสัมพันธ์ตามค่าเริ่มต้นและ:
taskset -c 0 nproc
เอาท์พุท:
1
และman nproc
ทำให้ค่อนข้างชัดเจน:
พิมพ์จำนวนหน่วยการประมวลผลที่มีอยู่
nproc
มี--all
แฟล็กสำหรับกรณีทั่วไปที่น้อยกว่าที่คุณต้องการรับจำนวนฟิสิคัล CPU:
taskset -c 0 nproc --all
ข้อเสียเพียงอย่างเดียวของวิธีนี้คือสิ่งนี้ดูเหมือนว่าจะเป็น UNIX เท่านั้น ฉันคิดว่า Windows ต้องมี affinity API ที่คล้ายกันSetProcessAffinityMask
ดังนั้นฉันจึงสงสัยว่าทำไมมันจึงไม่ได้รับการจัดวาง แต่ฉันไม่รู้อะไรเกี่ยวกับ Windows
ทดสอบใน Ubuntu 16.04, Python 3.5.2
แพลตฟอร์มอิสระ:
psutil.cpu_count (ตรรกะ = false)
psutil.cpu_count(logical=False) #4
psutil.cpu_count(logical=True) #8
และmultiprocessing.cpu_count() #8
สิ่งเหล่านี้จะช่วยให้คุณนับ CPU ที่มีเธรดมากเกินไป
multiprocessing.cpu_count()
os.cpu_count()
สิ่งเหล่านี้จะให้คุณนับ CPU ของเครื่องเสมือน
psutil.cpu_count()
numexpr.detect_number_of_cores()
จะทำงานก็ต่อเมื่อคุณทำงานบน VMs เท่านั้น
os.cpu_count()
และmultiprocessing.cpu_count()
จะส่งคืนจำนวน CPU ที่มีเธรดมากไม่ใช่จำนวนจริงของ CPU
multiprocessing.cpu_count()
จะกลับมาจำนวนซีพียูตรรกะดังนั้นหากคุณมี CPU Quad-core กับ hyperthreading 8
ก็จะกลับ หากคุณต้องการจำนวนฟิสิคัล CPU ให้ใช้การเชื่อมหลามเพื่อ hwloc:
#!/usr/bin/env python
import hwloc
topology = hwloc.Topology()
topology.load()
print topology.get_nbobjs_by_type(hwloc.OBJ_CORE)
hwloc ถูกออกแบบมาให้พกพาได้ทั้งในระบบปฏิบัติการและสถาปัตยกรรม
psutil.cpu_count(logical=False)
ไม่สามารถหาวิธีเพิ่มรหัสหรือตอบกลับข้อความได้ แต่นี่คือการสนับสนุนสำหรับ jython ที่คุณสามารถแก้ไขได้ก่อนที่คุณจะยอมแพ้:
# jython
try:
from java.lang import Runtime
runtime = Runtime.getRuntime()
res = runtime.availableProcessors()
if res > 0:
return res
except ImportError:
pass
สิ่งนี้อาจใช้ได้กับพวกเราที่ใช้ระบบปฏิบัติการ / ระบบที่แตกต่างกัน แต่ต้องการได้รับประโยชน์สูงสุดจากโลกทั้งหมด:
import os
workers = os.cpu_count()
if 'sched_getaffinity' in dir(os):
workers = len(os.sched_getaffinity(0))
คุณสามารถใช้ "joblib" เพื่อจุดประสงค์นี้
import joblib
print joblib.cpu_count()
วิธีนี้จะให้จำนวน cpus ในระบบ ต้องติดตั้ง joblib ข้อมูลเพิ่มเติมเกี่ยวกับ joblib สามารถดูได้ที่นี่ https://pythonhosted.org/joblib/parallel.html
หรือคุณสามารถใช้แพคเกจ numexpr ของ python มันมีฟังก์ชั่นง่าย ๆ มากมายที่เป็นประโยชน์สำหรับการรับข้อมูลเกี่ยวกับ cpu ระบบ
import numexpr as ne
print ne.detect_number_of_cores()
ตัวเลือกอื่นถ้าคุณไม่มี Python 2.6:
import commands
n = commands.getoutput("grep -c processor /proc/cpuinfo")
/proc/<PID>/status
มีเส้นบางที่บอกให้คุณจำนวนซีพียูใน cpuset ปัจจุบัน:Cpus_allowed_list
มองหา