Python 如何使用 multiprocessing 模块创建进程池

news2024/10/8 10:38:30

Python 如何使用 multiprocessing 模块创建进程池

一、简介

在现代计算中,提升程序性能的一个关键方法是并行处理,尤其是当处理大量数据或计算密集型任务时,单线程可能不够高效。Python 提供了多个模块来支持并行计算,其中最常用的就是 multiprocessing 模块。它允许我们在多个处理器上同时运行代码,通过多个进程同时处理任务,极大地提高了效率。

本文将介绍如何使用 Python 中的 multiprocessing 模块,特别是 进程池 的概念。我们会讲解如何创建进程池并在其上分配任务,通过代码示例帮助你轻松理解这一重要技术。

在这里插入图片描述

二、进程池简介

2.1 什么是进程池?

进程池(Process Pool) 是指通过预先创建的一组进程来并发执行任务。通常情况下,系统的进程创建和销毁是非常耗时的,所以使用进程池可以避免频繁的创建和销毁开销。我们可以将任务提交给进程池,让它们分配给预先启动的进程进行处理。

进程池最常用于:

  • 大量任务需要并行执行时。
  • 避免频繁的进程创建和销毁。
  • 有限的系统资源,例如 CPU 核心数有限时,通过控制池的大小来限制并发进程数。

2.2 为什么使用进程池?

在 Python 中,由于 GIL(Global Interpreter Lock,全局解释器锁) 的存在,线程并发无法在 CPU 密集型任务中充分发挥多核优势。multiprocessing 模块通过多进程方式绕过 GIL 限制,使得程序能够充分利用多核 CPU 的优势。相比于手动创建和管理多个进程,使用进程池能让我们更轻松地管理并发任务。

进程池的优点包括:

  • 自动管理多个进程的创建和销毁。
  • 可以方便地并行执行多个任务。
  • 通过池大小控制并发的进程数量,避免资源过度占用。

三、使用 multiprocessing 模块的基础知识

在开始使用进程池之前,了解 Python 中 multiprocessing 模块的基本概念很重要。

3.1 创建和启动进程

multiprocessing 模块中,我们可以通过 Process 类创建和启动进程。简单示例如下:

import multiprocessing
import time

def worker(num):
    """ 工作函数,执行一些任务 """
    print(f"Worker {num} is starting")
    time.sleep(2)  # 模拟工作
    print(f"Worker {num} is done")

if __name__ == '__main__':
    processes = []
    for i in range(5):
        p = multiprocessing.Process(target=worker, args=(i,))
        processes.append(p)
        p.start()

    for p in processes:
        p.join()  # 等待所有进程完成

这个示例演示了如何创建多个进程并并行执行任务,但当任务数很多时,手动管理这些进程就显得复杂了。这时,进程池就派上了用场。

四、创建进程池并分配任务

4.1 Pool 类的基本用法

multiprocessing 模块中的 Pool 类提供了一种方便的方式来创建进程池并分配任务。我们可以将多个任务提交给进程池,由进程池中的多个进程同时处理。

以下是使用 Pool 创建进程池并执行任务的基本示例:

import multiprocessing
import time

def worker(num):
    """ 工作函数,执行任务 """
    print(f"Worker {num} is starting")
    time.sleep(2)
    print(f"Worker {num} is done")
    return num * 2  # 返回计算结果

if __name__ == '__main__':
    # 创建包含 4 个进程的进程池
    with multiprocessing.Pool(processes=4) as pool:
        results = pool.map(worker, range(10))

    print(f"Results: {results}")

4.2 Pool.map() 方法

在上述代码中,我们使用了 Pool.map() 方法。它的作用类似于 Python 内置的 map() 函数,能够将一个可迭代对象的每个元素传递给目标函数,并将结果以列表形式返回。Pool.map() 会自动将任务分配给进程池中的多个进程并行处理。

例如:

  • range(10) 生成了 10 个任务,每个任务调用一次 worker 函数。
  • 由于进程池中有 4 个进程,所以它会一次并行执行 4 个任务,直到所有任务完成。

4.3 其他常用方法

除了 map() 方法,Pool 类还有其他一些常用的方法:

  • apply():同步执行一个函数,直到该函数执行完毕后,才能继续执行主进程的代码。

    result = pool.apply(worker, args=(5,))
    
  • apply_async():异步执行一个函数,主进程不会等待该函数执行完毕,可以继续执行其他代码。适合用于并行处理单个任务。

    result = pool.apply_async(worker, args=(5,))
    result.get()  # 获取返回值
    
  • starmap():类似 map(),但它允许传递多个参数给目标函数。

    def worker(a, b):
        return a + b
    
    results = pool.starmap(worker, [(1, 2), (3, 4), (5, 6)])
    

4.4 进程池大小的设置

在创建进程池时,我们可以通过 processes 参数来设置进程池的大小。通常,进程池大小与系统的 CPU 核心数有关。你可以通过 multiprocessing.cpu_count() 方法获取当前系统的 CPU 核心数,然后根据需要设置进程池的大小。

import multiprocessing

# 获取系统 CPU 核心数
cpu_count = multiprocessing.cpu_count()

# 创建进程池,进程数与 CPU 核心数相同
pool = multiprocessing.Pool(processes=cpu_count)

将进程池大小设置为与 CPU 核心数相同是一个常见的选择,因为这可以充分利用系统资源。

五、进程池的高级用法

5.1 异步任务处理

在实际场景中,某些任务可能会耗时较长。如果我们不希望等待这些任务完成再执行其他代码,可以使用异步任务处理方法,如 apply_async()。它允许我们在后台执行任务,而主进程可以继续执行其他代码,任务完成后我们可以通过 result.get() 获取结果。

import multiprocessing
import time

def worker(num):
    time.sleep(2)
    return num * 2

if __name__ == '__main__':
    with multiprocessing.Pool(processes=4) as pool:
        results = [pool.apply_async(worker, args=(i,)) for i in range(10)]

        # 执行其他操作
        print("主进程继续运行")

        # 获取异步任务结果
        results = [r.get() for r in results]
        print(f"Results: {results}")

在这个例子中,我们使用 apply_async() 异步执行任务,而主进程在等待任务完成之前可以执行其他操作。最终我们通过 get() 方法获取每个任务的结果。

5.2 异常处理

在并发编程中,处理异常是非常重要的。如果某个进程发生异常,我们需要确保能够捕捉到这些异常,并做出相应的处理。apply_async() 提供了 error_callback 参数,可以用于捕捉异步任务中的异常。

def worker(num):
    if num == 3:
        raise ValueError("模拟错误")
    return num * 2

def handle_error(e):
    print(f"捕获异常: {e}")

if __name__ == '__main__':
    with multiprocessing.Pool(processes=4) as pool:
        results = [pool.apply_async(worker, args=(i,), error_callback=handle_error) for i in range(10)]
        
        for result in results:
            try:
                print(result.get())
            except Exception as e:
                print(f"主进程捕获异常: {e}")

在这个例子中,如果某个任务抛出了异常,error_callback 函数会捕捉到,并进行处理。

六、实际应用场景

6.1 CPU 密集型任务

多进程并行处理非常适合处理 CPU 密集型任务,如图像处理、大规模数据运算等。在这些任务中,计算量非常大,多个进程可以同时利用系统的多个 CPU 核心,显著缩短处理时间。

def cpu_intensive_task(n):
    total = 0
    for i in range(10**6):
        total +=

 i * n
    return total

if __name__ == '__main__':
    with multiprocessing.Pool(processes=4) as pool:
        results = pool.map(cpu_intensive_task, range(10))
        print(results)

6.2 IO 密集型任务

对于 IO 密集型任务,如网络请求、文件读写等,由于进程大部分时间在等待外部资源响应,所以进程间的并发性能提升可能没有 CPU 密集型任务明显。但仍然可以通过多进程方式提高并发度,减少等待时间。

七、总结

通过本文的学习,我们了解了如何使用 Python 中的 multiprocessing 模块创建进程池,并将任务分配给多个进程执行。进程池的使用可以帮助我们有效管理并发任务,提高程序执行效率,尤其是在处理 CPU 密集型任务时效果显著。

在实践中,使用进程池时我们还需要注意以下几点:

  1. 资源管理:确保合理使用进程池,避免创建过多进程导致系统资源不足。
  2. 任务分配:根据任务的不同类型(如 CPU 密集型和 IO 密集型),选择合适的并行处理方法。
  3. 异常处理:在多进程环境中捕捉和处理异常,避免因为单个进程出错而导致整个程序崩溃。

通过掌握这些技巧,你可以在 Python 编程中充分利用并行处理的优势,构建更加高效的应用程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2196146.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

爬虫案例——爬取长沙房产网租房信息

需求: 1.爬取长沙房产网租房信息(长沙租房信息_长沙出租房源|房屋出租价格【长沙贝壳租房】 包括租房标题、标题链接,价格和地址 2.实现翻页爬取 3.使用bs4解析数据 分析 1.抓取正确的数据包——看响应内容 找到正确的后,复…

大模型之RAG-关键字检索的认识与实战(混合检索进阶储备)

前言 按照我们之前的分享(大模型应用RAG系列3-1从0搭建一个RAG:做好文档切分): RAG系统搭建的基本流程 准备对应的垂域资料文档的读取解析,进行文档切分将分割好的文本灌入检索引擎(向量数据库&#xff…

如何使用ssm实现新冠病毒校园监控平台的设计与实现+vue

TOC ssm812新冠病毒校园监控平台的设计与实现vue 绪论 课题背景 身处网络时代,随着网络系统体系发展的不断成熟和完善,人们的生活也随之发生了很大的变化。目前,人们在追求较高物质生活的同时,也在想着如何使自身的精神内涵得…

python画图|曲线动态输出基础教程

在前述学习过程中,已经掌握基本的曲线图像画法,并尝试探索过3D动画基础教程。 相关文章可以通过下述链接直达: python画三角函数图|小白入门级教程_正余弦函数画图python-CSDN博客 python动画教程|Animations using Matplotlib-官网教程程…

Hallo部署指南

一、介绍 Hallo是由复旦大学、百度公司、苏黎世联邦理工学院和南京大学的研究人员共同提出的一个AI对口型肖像图像动画技术,可基于语音音频输入来驱动生成逼真且动态的肖像图像视频。 该框架采用了基于扩散的生成模型和分层音频驱动视觉合成模块,提高了…

Linux实践|设置静态 IP 地址

引言 如果您是 Linux 系统管理员,那么您将需要在系统上配置网络。与可以使用动态 IP 地址的台式机不同,在服务器基础设施上,您需要设置静态 IP 地址(至少在大多数情况下)。 本文[1]旨在向您展示如何在最常用的 Linux 发…

TBD62783AFG的强大性能:高性能应用的可靠解决方案

在当今竞争激烈的电子市场中,工程师们始终在寻找能够提供可靠性、效率和多功能性的组件,尤其是在处理复杂、高性能系统时。东芝的TBD62783AFG 8通道源型DMOS晶体管阵列就是这样一个元件。凭借其独特的功能组合,使其成为从小型电机到感性设备的…

SpringCloud学习记录|day3

学习材料 2024最新SpringCloud微服务开发与实战,java黑马商城项目微服务实战开发(涵盖MybatisPlus、Docker、MQ、ES、Redis高级等) 微服务 1.单体架构 2.JMeter 这其实在redis还是什么教程里面用过,不过忘记得差不多了。 复习…

【重学 MySQL】六十、空间类型

【重学 MySQL】六十、空间类型 空间数据类型的分类空间数据类型的属性空间数据的表示方式空间数据的操作应用场景 在MySQL中,空间类型(Spatial Types)主要用于支持地理特征的生成、存储和分析。这些地理特征可以表示世界上具有位置的任何东西…

全是细节|大模型SFT的100个关键点

这篇文章介绍一下大模型的 sft 如何去做。我会默认读者们都知道 sft 是做什么的以及如何去做一些简单的 sft 微调工作,我主要是分享一些经验技巧和 debug 的分析思路。 背景篇 这里先普及一些 sft 涉及到的基础概念,方便新人同学理解后续内容&#xff0…

从0开始linux(6)——gcc

欢迎来到博主的专栏:从0开始linux 博主ID:代码小豪、 文章目录 gccgcc的文件风格预处理编译汇编链接 gcc gcc是linux系统下常用的C语言编译器,随着后续的扩展,gcc支持了c,并推出了g编译器,现在的gcc可以支…

C++(异常)

目录 C语言传统的处理错误的方式 传统的错误处理机制 C异常概念 异常的使用 异常的抛出和捕获 异常的抛出和匹配原则 在函数调用链中异常栈展开匹配原则 异常的重新抛出 异常安全 异常规范 自定义异常体系 C标准库的异常体系 异常的优缺点 C异常的优点 C异常的缺…

基于Python的美术馆预约系统【附源码】

效果如下: 系统首页界面 系统注册页面 美术馆详细页面 公告信息详细页面 后台登录界面 管理员主界面 美术馆管理界面 预约参观管理界面 研究背景 随着文化娱乐活动的日益丰富,美术馆作为展示艺术作品、传播文化的重要场所,其管理和服务模式…

大语言模型入门(四)——检索增强生成(RAG)

一、什么是检索增强生成 检索增强生成(Retrieval-Augmented Generation,RAG)由Facebook AI Research(FAIR)团队于2020年首次提出,这是一种结合了信息检索技术与语言生成模型的人工智能技术。它通过从外部知…

局域网内探测在线好友是如何做到的?

一、前言 随着局域网(LAN)应用的广泛使用,网络通信已经成为软件设计中不可或缺的一部分。局域网聊天软件作为一种常见的网络应用,可以实现多个用户之间的实时通信,广泛应用于企业内部沟通和小型网络环境中。本项目设计…

‌视频尺寸修改与批量剪辑技巧

在当今这个数字化时代,视频内容已成为人们获取信息、娱乐和社交的重要方式。然而,面对海量的视频素材,如何高效地管理和编辑它们成为了一个挑战。 1打开视频剪辑高手软件,切换功能到“批量剪辑视频” 2把需要剪辑的视频导入到表格…

希尔排序和直接插入排序

因为排序这些比较复杂点我就分几期给大家来讲~~~ 直接插入排序 直接插入排序是一种简单的排序算法,主要用于对少量数据进行排序。其基本思想是将待排序的元素逐个插入到已经排好序的部分中,从而形成一个有序序列。 具体步骤如下: 初始化&…

基于32单片机的博物馆安全监控系统设计

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 检测 分别是温湿度 光照 PM2.5、烟雾、红外,然后用OLED屏幕显示, 红外超过阈值则蜂鸣器报警,这是防盗报警;温度或烟雾超过阈值,则蜂鸣器…

【目标检测】木制地板缺陷破损数据集338张6类VOC+YOLO格式

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):3383 标注数量(xml文件个数):3383 标注数量(txt文件个数):3383 标注…

fiddler抓包21_(性能测试)耗时分析

课程大纲 使用场景 1. 查看请求耗时。 2. (更多)前端性能分析、优化。 1. 查看单个请求耗时 耗时详情:选择请求 - 右侧标签菜单选择Statistics“请求统计”。 传输时间线:选择请求 - 右侧选择“TimeLine”。 2. 前端性能分析&a…