使用multiprocessing模块充分利用所有核心

55 投票
6 回答
120103 浏览
提问于 2025-04-16 16:24

我有两段代码,正在用来学习Python 3.1中的多进程。我的目标是让所有可用的处理器都用上100%。但是,这里展示的代码片段只能达到30%到50%的使用率。

有没有办法让Python“强制”使用100%?是操作系统(Windows 7,64位)限制了Python对处理器的访问吗?当下面的代码片段在运行时,我打开任务管理器,看到处理器的使用率有波动,但从来没有达到并保持在100%。此外,我还看到多个python.exe进程在不断创建和销毁。这些进程和处理器有什么关系呢?比如说,如果我启动了4个进程,每个进程并没有使用自己的核心。那么,这些进程到底在用什么呢?它们是共享所有核心吗?如果是的话,是操作系统在强制这些进程共享核心吗?

代码片段 1

import multiprocessing

def worker():
    #worker function
    print ('Worker')
    x = 0
    while x < 1000:
        print(x)
        x += 1
    return

if __name__ == '__main__':
    jobs = []
    for i in range(50):
        p = multiprocessing.Process(target=worker)
        jobs.append(p)
        p.start()

代码片段 2

from multiprocessing import Process, Lock

def f(l, i):
    l.acquire()
    print('worker ', i)
    x = 0
    while x < 1000:
        print(x)
        x += 1
    l.release()

if __name__ == '__main__': 
    lock = Lock()
    for num in range(50):
        Process(target=f, args=(lock, num)).start()

6 个回答

10

下面是一个用纯Python写的最简单的例子:

def f(x):
    while 1:
        # ---bonus: gradually use up RAM---
        x += 10000  # linear growth; use exponential for faster ending: x *= 1.01
        y = list(range(int(x))) 
        # ---------------------------------
        pass  # infinite loop, use up CPU

if __name__ == '__main__':  # name guard to avoid recursive fork on Windows
    import multiprocessing as mp
    n = mp.cpu_count() * 32  # multiply guard against counting only active cores
    with mp.Pool(n) as p:
        p.map(f, range(n))

使用方法:在寒冷的日子里热身(不过你可以把这个循环改成其他更有意义的东西)。

注意:如果想退出程序,不要拔掉插头或按住电源键,应该按Ctrl-C。

21

你可以使用psutil这个库来把通过multiprocessing创建的每个进程固定到特定的CPU上,简单来说,就是让某个程序只在某个处理器上运行。

import multiprocessing as mp
import psutil


def spawn():
    procs = list()
    n_cpus = psutil.cpu_count()
    for cpu in range(n_cpus):
        affinity = [cpu]
        d = dict(affinity=affinity)
        p = mp.Process(target=run_child, kwargs=d)
        p.start()
        procs.append(p)
    for p in procs:
        p.join()
        print('joined')


def run_child(affinity):
    proc = psutil.Process()  # get self pid
    print(f'PID: {proc.pid}')
    aff = proc.cpu_affinity()
    print(f'Affinity before: {aff}')
    proc.cpu_affinity(affinity)
    aff = proc.cpu_affinity()
    print(f'Affinity after: {aff}')


if __name__ == '__main__':
    spawn()

注意:正如评论中提到的,psutil.Process.cpu_affinity在macOS系统上是不可用的。

49

要充分利用所有的处理器核心,尽量不要频繁地创建和销毁新的进程。

每个核心可以创建几个进程,并把它们通过管道连接起来。

在操作系统层面,这些通过管道连接的进程会同时运行。

你写的代码越少(而且越多地依赖操作系统),就越有可能充分利用所有的资源。

python p1.py | python p2.py | python p3.py | python p4.py ...

这样做可以最大限度地利用你的CPU。

撰写回答