如何在 Python 中使用多进程实现多个任务的并行处理?

2024-08-25 23:52

本文主要是介绍如何在 Python 中使用多进程实现多个任务的并行处理?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、什么是多进程

操作系统(OS)是管理计算机硬件和软件资源的基础系统,它为用户和应用程序提供了一个接口。

在操作系统中,进程是一个正在运行的程序实例,是操作系统进行资源分配的最小单位。

每个进程在操作系统中都有自己独立的资源集合,包括CPU时间、内存、文件句柄等。

在这里插入图片描述

操作系统为每个进程分配独立的内存空间,这意味着进程A不能直接访问或修改进程B的内存数据,确保了进程之间的安全性和数据隔离。

进程的独立性还体现在它们拥有各自的执行状态,包括程序计数器、寄存器状态和栈指针,这些状态在进程之间互不干扰。

例如,一个进程崩溃或被终止,通常不会影响其他进程的运行。

在这里插入图片描述

这种设计提高了系统的稳定性和安全性,因为即使一个进程出现问题,其他进程仍能正常运行。

由于进程之间的资源相对独立,操作系统可以更有效地管理和调度系统资源,同时支持多任务并行处理。

然而,当进程需要共享数据或协作时,它们可以通过进程间通信(IPC)机制,如管道、消息队列或共享内存来进行数据交换和同步。

这种架构设计不仅保障了安全性和稳定性,还允许在必要时实现进程间的协作。

在现代计算中,多进程是一种常见的技术,用于提高计算机的性能和资源利用率。多进程允许多个进程(程序的独立执行实例)同时运行在操作系统上,从而实现任务并行处理。

二、多进程的工作原理

多进程是指在同一时间内,操作系统支持多个进程同时运行。

在现代计算中,处理器(CPU)的架构对操作系统的多进程管理和调度有着至关重要的影响。

尽管在单核CPU上,多个进程实际上是通过快速切换来实现“并行”运行的,

但在多核CPU上,多个进程可以真正并行地在不同的核上运行。

随着今天数据处理规模的增大和计算任务的复杂化,单线程执行任务的效率往往难以满足实际需求。

以英特尔第14代酷睿i9-14900HX处理器为例,这款处理器拥有24个核心,其中8个是高性能核心(P-core),16个是高效能核心(E-core),共支持32个线程。

在这里插入图片描述

操作系统必须根据任务的性质来优化调度策略。

对于需要高计算能力和低延迟的任务,操作系统通常会将这些任务分配给P核心。P核心具有较高的频率和强大的单线程性能,非常适合处理对单线程性能要求高的任务。

另一方面,对于并行执行或对延迟不敏感的后台任务,操作系统倾向于将它们调度到E核心上。E核心设计优化了能效,适合处理大量并行计算工作,从而提高整体系统的能效比。

操作系统还需实现有效的负载均衡,通过不断监控每个核心的负载情况,动态调整进程的调度位置,以防止某些核心过载而其他核心闲置。这种机制可以优化资源利用率,提高系统性能。

此外,i9-14900HX的缓存层次结构(L2和L3缓存)对上下文切换有显著影响。操作系统会考虑缓存亲和性,尽量将进程重新调度到之前运行的核心上,以利用缓存中残留的数据,从而减少缓存未命中导致的性能开销。
在这里插入图片描述

在多进程调度中,功耗管理也是一个重要因素。i9-14900HX支持动态功耗调整,操作系统可以根据当前的工作负载和功耗策略,决定是提高性能还是降低能耗。这种动态调节机制能够在性能需求和能效之间取得最佳平衡,适应不同的工作负载。

由于i9-14900HX支持32线程,操作系统可以充分利用其多核架构来进行多任务并行处理。

它非常适合同时运行多个虚拟机、容器化应用或数据分析任务等场景。

此外,对于需要同时处理高性能计算和后台任务的混合负载应用,i9-14900HX提供了理想的解决方案。高性能计算任务可以利用P核心的高频优势,而后台处理任务则可以利用E核心的高能效特性,实现性能与能效的最佳结合。

在Python中,多进程是一种实现并行计算的强大工具,能够在多核CPU上同时运行多个任务,从而显著提升程序的执行效率。

在本文中,我们来了解下如何在Python中使用多进程完成多任务并行处理,并通过几个简单的编程案例来理解和掌握这一技术。

三、Python 中多任务并行的限制

我们知道,在Python中,因为GIL(全局解释器锁)的存在,限制了多线程的并行执行,在常规编程中,是无法启用多任务并行的。

**GIL(全局解释器锁)**是Python解释器(特别是CPython)中的一个机制,它保证在同一时间只有一个线程执行Python字节码。GIL的存在是因为Python的内存管理不是线程安全的,GIL通过锁机制确保只有一个线程能执行Python代码,从而避免了多线程访问共享数据时可能发生的竞态条件和数据不一致问题。

在这里插入图片描述

由于GIL的存在,即使在多核CPU上,Python多线程也不能实现真正的并行执行。对于I/O密集型任务(例如文件读写、网络请求等),线程可能在等待I/O操作完成时被阻塞,GIL会释放给其他线程,因此多线程在这种情况下仍然有优势,因为它可以同时处理多个I/O操作。

在这里插入图片描述

然而,在CPU密集型任务(例如大量计算、数据处理等)中,线程需要持续执行大量的Python字节码,GIL始终被占用,其他线程无法获取执行时间。这导致多线程在CPU密集型任务中的性能提升非常有限,因为无法利用多核CPU的真正并行计算能力。

那如何才能在 Python 中实现多个任务的并行处理呢?

这是我们就要用到 多进程(multiprocessing)模块 了。

多进程(multiprocessing)模块是Python提供的另一种并行执行方式,它可以绕过GIL的限制。

不同于多线程在同一个进程中共享内存和GIL,多进程通过创建多个独立的进程,每个进程都有自己的Python解释器和内存空间。
在这里插入图片描述

由于每个进程是独立的,GIL只在各自的进程内有效,因此可以在多核CPU上实现真正的并行计算。

这使得多进程成为处理CPU密集型任务的理想选择,因为它能够充分利用多核架构,实现性能的显著提升。

三、在Python中使用多进程模块

multiprocessing 是Python的标准库模块,它提供了一个Process类,用于创建和管理进程。以下是使用多进程模块进行并行处理的基本步骤:

  1. 导入进程包:导入Python标准库中的multiprocessing模块。
  2. 创建进程:实例化Process对象,并指定目标函数和函数参数。
  3. 启动进程:使用start()方法启动进程。
  4. 等待进程结束:使用join()方法等待进程执行完毕。

让我们通过几个简单的示例来了解这些步骤。

示例一:并行计算多个数字的阶乘

假设我们要计算一组数字的阶乘,如果使用单线程来逐个计算,每个计算之间将会按顺序执行。使用多进程,我们可以并行计算多个数字的阶乘,从而加速计算过程。

import multiprocessing
import mathdef calculate_factorial(number):print(f"Calculating factorial of {number}")result = math.factorial(number)print(f"Factorial of {number} is {result}")if __name__ == "__main__":numbers = [5, 7, 10, 12]processes = []# 创建进程for number in numbers:process = multiprocessing.Process(target=calculate_factorial, args=(number,))processes.append(process)# 启动进程for process in processes:process.start()# 等待所有进程完成for process in processes:process.join()print("All processes are complete.")

在这个示例中,我们首先定义了一个函数calculate_factorial来计算给定数字的阶乘。

然后,在__main__块中,我们创建了多个进程,每个进程负责计算一个数字的阶乘。

使用start()方法启动所有进程,并使用join()方法等待它们完成。

我们尝试在 Pycharm 中输入程序并尝试运行。
在这里插入图片描述

运行程序代码时,我们看到所有进程几乎同时开始计算不同数字的阶乘,从而节省了总计算时间。

示例二:并行下载多个文件

在网络编程中,多进程也非常有用。例如,我们可能需要从网络上下载多个文件。使用多进程,我们可以并行进行多个文件的下载,提高下载效率。

import multiprocessing
import requestsdef download_file(url):print(f"Downloading from {url}")response = requests.get(url)filename = url.split("/")[-1]with open(filename, "wb") as file:file.write(response.content)print(f"Downloaded {filename}")if __name__ == "__main__":urls = ["https://example.com/file1.zip","https://example.com/file2.zip","https://example.com/file3.zip"]processes = []for url in urls:process = multiprocessing.Process(target=download_file, args=(url,))processes.append(process)for process in processes:process.start()for process in processes:process.join()print("All downloads are complete.")

在此示例中,我们使用了requests库来下载文件。

每个URL的下载任务由一个独立的进程处理,这样多个文件的下载可以同时进行,而不需要等待其他文件下载完成。

这种方法在处理大量网络I/O操作时非常高效。
在这里插入图片描述
在Pycharm中输入程序代码并运行,可以看到多个进程同时开启了文件下载。

示例三、使用进程池优化进程管理

在前面的例子中,我们手动管理每个进程的创建、启动和等待,这在需要大量进程时可能会显得复杂和难以管理。multiprocessing模块中的Pool类为我们提供了一种更加简洁的方式来管理进程。

import multiprocessingdef square_number(number):return number * numberif __name__ == "__main__":numbers = [1, 2, 3, 4, 5]pool = multiprocessing.Pool(processes=4)  # 创建一个进程池,包含4个进程results = pool.map(square_number, numbers)pool.close()  # 关闭进程池,不再接受新的任务pool.join()   # 等待所有进程完成print(f"Squared numbers: {results}")

在这个示例中,我们使用Pool类创建了一个包含4个进程的进程池,并通过map()方法将numbers列表中的每个元素传递给square_number函数进行并行计算每个元素的平方值。这样,我们就能够以更加简洁的方式管理多个并行任务。

在这里插入图片描述
在Pycharm中输入程序代码并运行,可以看到进程池中的4个进程并行计算了每个元素的平方值。

结论

Python的GIL(全局解释器锁)限制了多线程的并行执行。

尽管多线程适用于I/O密集型任务,但在CPU密集型任务中,其性能提升有限。

这时,使用Python的multiprocessing模块,可以轻松地实现多任务并行处理,大幅提升程序的执行效率。

通过创建独立的进程,每个进程都有自己的Python解释器和内存空间,Python程序可以有效绕过GIL限制,实现真正的并行计算。

无论是计算密集型任务,还是I/O密集型任务,多进程都能帮助我们更好地利用现代多核CPU的强大计算能力。

通过上面的示例,我们理解和掌握了在 Python 中使用多进程实现多个任务的并行处理方法。

尝试将这些技巧应用到你的项目中,充分发挥你的电脑多进程并行计算的优势吧!

这篇关于如何在 Python 中使用多进程实现多个任务的并行处理?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1106973

相关文章

详解Vue如何使用xlsx库导出Excel文件

《详解Vue如何使用xlsx库导出Excel文件》第三方库xlsx提供了强大的功能来处理Excel文件,它可以简化导出Excel文件这个过程,本文将为大家详细介绍一下它的具体使用,需要的小伙伴可以了解... 目录1. 安装依赖2. 创建vue组件3. 解释代码在Vue.js项目中导出Excel文件,使用第三

Linux alias的三种使用场景方式

《Linuxalias的三种使用场景方式》文章介绍了Linux中`alias`命令的三种使用场景:临时别名、用户级别别名和系统级别别名,临时别名仅在当前终端有效,用户级别别名在当前用户下所有终端有效... 目录linux alias三种使用场景一次性适用于当前用户全局生效,所有用户都可调用删除总结Linux

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

Python脚本实现自动删除C盘临时文件夹

《Python脚本实现自动删除C盘临时文件夹》在日常使用电脑的过程中,临时文件夹往往会积累大量的无用数据,占用宝贵的磁盘空间,下面我们就来看看Python如何通过脚本实现自动删除C盘临时文件夹吧... 目录一、准备工作二、python脚本编写三、脚本解析四、运行脚本五、案例演示六、注意事项七、总结在日常使用

Java实现Excel与HTML互转

《Java实现Excel与HTML互转》Excel是一种电子表格格式,而HTM则是一种用于创建网页的标记语言,虽然两者在用途上存在差异,但有时我们需要将数据从一种格式转换为另一种格式,下面我们就来看看... Excel是一种电子表格格式,广泛用于数据处理和分析,而HTM则是一种用于创建网页的标记语言。虽然两

java图像识别工具类(ImageRecognitionUtils)使用实例详解

《java图像识别工具类(ImageRecognitionUtils)使用实例详解》:本文主要介绍如何在Java中使用OpenCV进行图像识别,包括图像加载、预处理、分类、人脸检测和特征提取等步骤... 目录前言1. 图像识别的背景与作用2. 设计目标3. 项目依赖4. 设计与实现 ImageRecogni

Java中Springboot集成Kafka实现消息发送和接收功能

《Java中Springboot集成Kafka实现消息发送和接收功能》Kafka是一个高吞吐量的分布式发布-订阅消息系统,主要用于处理大规模数据流,它由生产者、消费者、主题、分区和代理等组件构成,Ka... 目录一、Kafka 简介二、Kafka 功能三、POM依赖四、配置文件五、生产者六、消费者一、Kaf

Python将大量遥感数据的值缩放指定倍数的方法(推荐)

《Python将大量遥感数据的值缩放指定倍数的方法(推荐)》本文介绍基于Python中的gdal模块,批量读取大量多波段遥感影像文件,分别对各波段数据加以数值处理,并将所得处理后数据保存为新的遥感影像... 本文介绍基于python中的gdal模块,批量读取大量多波段遥感影像文件,分别对各波段数据加以数值处

python管理工具之conda安装部署及使用详解

《python管理工具之conda安装部署及使用详解》这篇文章详细介绍了如何安装和使用conda来管理Python环境,它涵盖了从安装部署、镜像源配置到具体的conda使用方法,包括创建、激活、安装包... 目录pytpshheraerUhon管理工具:conda部署+使用一、安装部署1、 下载2、 安装3

Mysql虚拟列的使用场景

《Mysql虚拟列的使用场景》MySQL虚拟列是一种在查询时动态生成的特殊列,它不占用存储空间,可以提高查询效率和数据处理便利性,本文给大家介绍Mysql虚拟列的相关知识,感兴趣的朋友一起看看吧... 目录1. 介绍mysql虚拟列1.1 定义和作用1.2 虚拟列与普通列的区别2. MySQL虚拟列的类型2