pin_drop当前位置:知识文库 ❯ 图文

multiprocessing模块详解 - Python多进程编程指南

概述

multiprocessing 是Python标准库中用于创建和管理多进程的模块。与多线程不同,多进程通过启动独立的操作系统进程来实现真正的并行计算,有效绕过了Python的GIL(全局解释器锁)限制。

每个进程拥有独立的内存空间、Python解释器和执行状态,因此多进程非常适合CPU密集型任务,如数值计算、数据处理、图像处理等。multiprocessing模块提供了与threading模块相似的API,降低了学习成本。


语法

代码示例

from multiprocessing import Process, current_process, cpu_count

# Process 构造函数
process = Process(target=函数名, args=(参数1, 参数2, ...), name='进程名', daemon=False)

# 参数说明:
# target: 进程要执行的函数(不加括号)
# args:   传递给 target 的位置参数元组
# name:   进程名称,便于调试
# daemon: 是否为守护进程(True表示父进程退出时子进程自动终止)

# 常用属性和方法:
# process.start()    — 启动进程
# process.join(timeout=None) — 等待进程结束
# process.terminate() — 强制终止进程
# process.is_alive()  — 检查进程是否存活
# process.pid         — 获取进程ID
# current_process().name — 获取当前进程名
# cpu_count()        — 获取CPU核心数

基本用法

创建和启动进程

代码示例

from multiprocessing import Process
import time

def worker(name, delay):
    """工作进程函数"""
    print(f"进程 {name} 启动")
    time.sleep(delay)
    print(f"进程 {name} 完成")

if __name__ == '__main__':
    # 创建进程对象
    p1 = Process(target=worker, args=('A', 2), name='Worker-A')
    p2 = Process(target=worker, args=('B', 1), name='Worker-B')
    
    # 启动进程
    p1.start()
    p2.start()
    
    # 等待进程结束
    p1.join()
    p2.join()
    
    print("所有子进程已结束")

批量创建进程

代码示例

from multiprocessing import Process
import time

def compute_task(task_id):
    print(f"任务 {task_id} 开始执行")
    time.sleep(1)
    print(f"任务 {task_id} 完成")

if __name__ == '__main__':
    processes = []
    
    # 批量创建并启动
    for i in range(5):
        p = Process(target=compute_task, args=(i,))
        processes.append(p)
        p.start()
    
    # 统一等待所有进程结束
    for p in processes:
        p.join()
    
    print("所有任务执行完毕")

代码示例

示例1:CPU密集型任务并行计算

代码示例

from multiprocessing import Process, cpu_count
import time
import math

def calculate_primes(n):
    """计算前n个素数(CPU密集型)"""
    primes = []
    num = 2
    while len(primes) < n:
        is_prime = True
        for i in range(2, int(math.sqrt(num)) + 1):
            if num % i == 0:
                is_prime = False
                break
        if is_prime:
            primes.append(num)
        num += 1
    print(f"找到 {len(primes)} 个素数")

if __name__ == '__main__':
    start = time.time()
    
    # 使用多进程并行计算
    processes = []
    num_cores = cpu_count()
    print(f"CPU核心数: {num_cores}")
    
    for i in range(num_cores):
        p = Process(target=calculate_primes, args=(50000,))
        processes.append(p)
        p.start()
    
    for p in processes:
        p.join()
    
    print(f"多进程耗时: {time.time() - start:.2f} 秒")

示例2:进程间数据隔离

代码示例

from multiprocessing import Process

# 全局变量
counter = 0

def increment():
    global counter
    for _ in range(100000):
        counter += 1
    print(f"子进程 counter = {counter}")

if __name__ == '__main__':
    p1 = Process(target=increment)
    p2 = Process(target=increment)
    
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    
    print(f"主进程 counter = {counter}")
    # 输出:主进程 counter = 0
    # 因为每个进程都有自己的 counter 副本,互不影响

注意事项

注意1:Windows系统必须使用 if __name__ == '__main__': 包裹进程创建代码,否则会导致无限递归创建子进程的错误。

注意2:进程数不应超过CPU核心数。过多的进程会导致CPU上下文切换开销增加,反而降低性能。建议使用 multiprocessing.cpu_count() 获取核心数作为参考。


小结

  • multiprocessing:Python标准库多进程模块,实现真正的并行计算

  • Process.start()/join():start启动进程,join等待进程结束

  • 进程间隔离:每个进程拥有独立内存,全局变量不共享

  • 适用场景:CPU密集型任务,不受GIL限制


练习题

练习1

编写程序,使用multiprocessing模块创建4个子进程,每个子进程计算一个数字列表的和,验证进程间数据隔离的特性。

练习2

编写一个函数,使用多进程并行计算1到10000000的累加和,与单线程版本对比执行时间,分析性能差异。

常见问题

为什么Windows上必须使用if __name__ == '__main__'?

Windows不支持fork系统调用,multiprocessing使用spawn方式创建子进程:通过重新导入主模块来初始化子进程。如果没有__main__保护,子进程导入主模块时会再次执行创建进程的代码,导致无限递归。

多进程和多线程应该如何选择?

CPU密集型任务(数学计算、图像处理、数据分析)选择多进程,可以绕过GIL实现真正并行。I/O密集型任务(网络请求、文件读写、数据库查询)选择多线程,线程创建开销小且GIL在I/O操作时会释放。

进程之间如何共享数据?

进程之间内存隔离,但有多种方式可以通信:Queue(进程安全队列)、Pipe(双向管道)、Value/Array(共享内存)、Manager(共享字典/列表等)。其中Queue和Pipe是最常用的方式。

标签: multiprocessing 多进程 Process 并行计算 GIL Python教程

本文涉及AI创作

内容由AI创作,请仔细甄别

list快速访问

上一篇: 线程池ThreadPoolExecutor详解 - Python并发编程指南 下一篇: 进程间通信Queue详解 - Python生产者消费者模式

poll相关推荐