Python 在使用mutliprocessing时,如何达到100%的CPU利用率?
我试图通过同时运行4个进程来使用多处理来加速我的python3脚本。然而,我的进程从未达到100%的CPU利用率。我的代码的核心只是读取Python 在使用mutliprocessing时,如何达到100%的CPU利用率?,python,linux,optimization,multiprocessing,cpu-usage,Python,Linux,Optimization,Multiprocessing,Cpu Usage,我试图通过同时运行4个进程来使用多处理来加速我的python3脚本。然而,我的进程从未达到100%的CPU利用率。我的代码的核心只是读取.mp3录音,并使用scikit learn对其进行识别,然后将结果保存到.json中 这是我的顶部输出: top - 17:07:07 up 18 days, 3:31, 4 users, load average: 3.73, 3.67, 3.87 Tasks: 137 total, 1 running, 75 sleeping, 18 sto
.mp3
录音,并使用scikit learn
对其进行识别,然后将结果保存到.json
中
这是我的顶部
输出:
top - 17:07:07 up 18 days, 3:31, 4 users, load average: 3.73, 3.67, 3.87
Tasks: 137 total, 1 running, 75 sleeping, 18 stopped, 0 zombie
%Cpu(s): 32.8 us, 20.3 sy, 0.0 ni, 46.3 id, 0.0 wa, 0.0 hi, 0.5 si, 0.1 st
KiB Mem : 8167880 total, 2683088 free, 4314756 used, 1170036 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 3564064 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
5832 am 20 0 1887644 776736 24076 S 63.0 9.5 201:10.19 python3
5829 am 20 0 1956336 845556 24348 S 55.0 10.4 200:31.20 python3
5830 am 20 0 2000772 890260 23820 S 55.0 10.9 200:39.80 python3
5834 am 20 0 2430932 1.260g 24252 S 50.3 16.2 200:45.52 python3
4657 am 20 0 108116 4460 3424 S 0.3 0.1 1:11.48 sshd
6564 root 20 0 0 0 0 I 0.3 0.0 7:30.08 kworker/2:1
1 root 20 0 225212 6660 4452 S 0.0 0.1 0:26.33 systemd
......
正如您在前面的输出中所看到的,内存上没有重载,因此有限的CPU利用率与I/O或内存无关
是否有办法“强制”python使用所有100%的资源?或者,我如何调试代码以找出导致这种情况的原因?如果我遗漏了一些明显的东西,如何更改代码以达到100%的CPU利用率?
下面是我的主要多处理代码的一个小概述:
# -*- coding: utf-8 -*-
import os
import time
import logging
import cProfile
import multiprocessing as mp
from packages.Recognizer import Recognizer
from packages.RecordingFile import RecordingFile
from packages.utils.pickle_utils import pickle_load
_PRINTS = True
class ServerSER:
def __init__(self, date, model_fname, results_path,
nprocs=1, run_type="server"):
# bunch of inits
def process_files(self):
# Setup a list of processes that we want to run
self.processes = [mp.Process(target=self.recognition_func, args=("processes/p" + str(p),
self.model_obj, p, self.output))
for p in range(self.nprocs)]
# Run processes
for p in self.processes: p.start()
# Exit the completed processes
for p in self.processes: p.join()
# Get process results from the output queue
self.results = []
for p in self.processes:
try:
r = self.output.get_nowait()
self.results.append(r)
except Exception as e:
print(e)
return [e[1][0] for e in self.results]
def recognition_func(self, pfolder, model_obj, pos, output, profile=True):
# start profiling
pr = cProfile.Profile()
pr.enable()
# start logging
logger_name = "my-logger" + str(pos)
logging.basicConfig(format='%(asctime)s %(levelname)5s %(message)s',
level=logging.INFO, filename=logger_name + ".txt")
logging.info("Start logging for process number " + str(pos))
# start processing until no files available
while len([f for f in os.listdir(pfolder) if ".mp3" in f]) > 0:
# get oldest file
oldest_file = [f for f in self.sorted_ls(pfolder) if ".mp3" in f][0]
# process
try:
recording = RecordingFile(pfolder=pfolder,
base_url=self.base_url,
fpath=oldest_file,
results_path=self.results_path)
if _PRINTS:
msg = "%10s : %50s" % ("PROCESSING", oldest_file)
logging.info(msg)
# prints
print("------------------------------------------------------------------------")
print("%10s : %50s" % ("PROCESSING", oldest_file))
print("------------------------------------------------------------------------")
# recognize for file
_ = Recognizer(recording=recording,
duration_step=1,
channel=1,
model_obj=self.model_obj)
# clean ups
recording.delete_files()
print("%10s." % ("DONE"))
print("------------------------------------------------------------------------")
except Exception as e:
self.errors[oldest_file] = e
logging.warn(e)
print(e, " while processing ", oldest_file)
# put results in queue
self.output.put((pos, [self.errors, self.durations]))
# save profiling results
# pr.print_stats(sort='time')
pr.disable()
pr.dump_stats("incode_cprofiler_output" + str(pos) + ".txt")
return True
uname-a的输出:
Linux 4.15.0-70-generic\79 Ubuntu SMP x86\U 64 x86\U 64 x86\U 64 GNU/Linux
lscpu的输出
:
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 1
Core(s) per socket: 4
Socket(s): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 94
Model name: Intel Core Processor (Skylake, IBRS)
Stepping: 3
CPU MHz: 3696.000
BogoMIPS: 7392.00
Virtualization: VT-x
Hypervisor vendor: KVM
Virtualization type: full
L1d cache: 32K
L1i cache: 32K
L2 cache: 4096K
L3 cache: 16384K
NUMA node0 CPU(s): 0-3
编辑
当对进程数进行一点调整时,会发生以下情况:
- 在我使用1个进程的情况下,CPU使用率是110%
- 对于2个进程,CPU使用率为80%
- 对于6个进程,每个进程的CPU使用率约为50%
您为什么想要100%的折扣?测试目的或?充分利用我的cpu?目前每个核心平均只达到65%,这意味着它没有充分利用可用的计算能力。我不需要它总是100%,但如果它充分利用了cpu,它应该时不时地达到。Python没有限制cpu的使用,所以问题在于self.recognition\u func
。它是磁盘密集型的吗?您可以看到它是如何在没有多处理的情况下连续工作的。比如说,你可以做6个作业,一次,然后看看cpu使用率是否上升。至少有一个或两个以上的内核(对于IO操作)是有用的。这是出乎意料的。它就像scikit在共享资源上陷入困境一样。scikit似乎不使用GPU(这是我最好的猜测)。但它确实使用pythonjoblib
来实现并行性。也许您应该研究scikit方式的多处理,而不是多处理方法。也许有一些致命的拥抱在那里的某个地方,导致等待/超时。您希望在完全提交的服务器上看到平均负载超过100%(平均负载计算是一门黑暗的艺术)。为什么要100%呢?测试目的或?充分利用我的cpu?目前每个核心平均只达到65%,这意味着它没有充分利用可用的计算能力。我不需要它总是100%,但如果它充分利用了cpu,它应该时不时地达到。Python没有限制cpu的使用,所以问题在于self.recognition\u func
。它是磁盘密集型的吗?您可以看到它是如何在没有多处理的情况下连续工作的。比如说,你可以做6个作业,一次,然后看看cpu使用率是否上升。至少有一个或两个以上的内核(对于IO操作)是有用的。这是出乎意料的。它就像scikit在共享资源上陷入困境一样。scikit似乎不使用GPU(这是我最好的猜测)。但它确实使用pythonjoblib
来实现并行性。也许您应该研究scikit方式的多处理,而不是多处理方法。也许有一些致命的拥抱在那里的某个地方,导致等待/超时。您希望在完全提交的服务器上看到平均负载超过100%(平均负载计算是一门黑暗的艺术)。