山东网站建设哪里好,有个印度做网站的天天找我,专业做汽车网站优化排名,网站模板兼容手机使用进程池/线程池 加速 Python数据处理 目标简单模式多进程模式 参考 Python 是一种出色的编程语言#xff0c;可用于处理数据和自动执行重复任务。尽管 Python 使编码变得有趣#xff0c;但它并不总是运行速度最快的。默认情况下#xff0c;Python 程序使用单个 CPU 作为单… 使用进程池/线程池 加速 Python数据处理 目标简单模式多进程模式 参考 Python 是一种出色的编程语言可用于处理数据和自动执行重复任务。尽管 Python 使编码变得有趣但它并不总是运行速度最快的。默认情况下Python 程序使用单个 CPU 作为单个进程执行。
如果有一台近十年生产的计算机它很可能有 4 个或更多CPU 核心。这意味着在等待程序完成运行时计算机 75% 或更多的资源几乎处于闲置状态 如何通过并行运行 Python 函数来充分利用计算机的处理能力。得益于Python的concurrent.futures模块只需要3行代码就可以将一个普通程序变成可以并行处理数据的程序。
目标
假设有一个装满照片的文件夹想要创建每张照片的缩略图。 这是一个简短的程序它使用 Python 的内置 glob 函数获取文件夹中所有 jpeg 文件的列表然后使用 Pillow 图像处理库保存每张照片的 128 像素缩略图
简单模式
# thumbnails_1.py
import glob
import os
from PIL import Imagedef make_image_thumbnail(filename):# 缩略图将被命名为original_filename_thumbnail.jpgbase_filename, file_extension os.path.splitext(filename)thumbnail_filename f{base_filename}_thumbnail{file_extension}# 创建和存储缩略图image Image.open(filename)image.thumbnail(size(128, 128))image.save(thumbnail_filename, JPEG)return thumbnail_filename# 遍历文件夹下的所有jpg文件并为每一张图生成缩略图
for image_file in glob.glob(*.jpg):thumbnail_file make_image_thumbnail(image_file)print(fA thumbnail for {image_file} was saved as {thumbnail_file})该程序运行时间为 8.9 秒。但是计算机大概有75%的cpu处于空闲状态问题是电脑有 4 个 CPU 核心但 Python 只使用其中之一。因此当最大限度地发挥一个 CPU时其他三个 CPU 却没有执行任何操作。
多进程模式
将 jpeg 文件列表分成 4 个较小的块。 运行 4 个独立的 Python 解释器实例。让每个 Python 实例处理 4 个数据块之一。 合并 4 个过程的结果即可得到最终结果列表。 在四个独立的 CPU 上运行的四个 Python 副本应该能够完成大约是一个 CPU 的 4 倍的工作量对吗 只需要3步 导入concurrent.futures库 启动 4个Python 实例通过创建一个进程池来做到这一点 要求进程池使用这 4 个进程在数据列表上执行辅助函数。executor.map() 函数接受要调用的辅助函数以及要使用它处理的数据列表。它完成了拆分列表、将子列表发送到每个子进程、运行子进程以及组合结果等所有艰苦工作。非常的简洁 executor.map() 函数返回结果的顺序与给它处理的数据列表的顺序相同。所以使用Python的zip()函数作为快捷方式来一步获取原始文件名和匹配结果。
# thumbnails_2.pyimport glob
import os
from PIL import Image
import concurrent.futuresdef make_image_thumbnail(filename):# 缩略图将被命名为original_filename_thumbnail.jpgbase_filename, file_extension os.path.splitext(filename)thumbnail_filename f{base_filename}_thumbnail{file_extension}# 创建和存储缩略图image Image.open(filename)image.thumbnail(size(128, 128))image.save(thumbnail_filename, JPEG)return thumbnail_filename# 创建一个线程池处理为每个cpu创建一个实例
with concurrent.futures.ProcessPoolExecutor() as executor:# 获取所有要处理的jpg文件image_files glob.glob(*.jpg)# 处理文件列表 将任务拆分到线程池以利用所有的cpufor image_file, thumbnail_file in zip(image_files, executor.map(make_image_thumbnail, image_files)):print(fA thumbnail for {image_file} was saved as {thumbnail_file})2.2秒就完成了与原始版本相比速度提高了 4 倍。由于使用 4 个 CPU 而不是 1 个因此运行时间更快。 但如果仔细观察你会发现“用户”时间几乎是 9 秒。程序如何在 2.2 秒内完成但仍然运行了 9 秒这似乎……不可能 这是因为“用户”时间是所有 CPU 的 CPU 时间的总和。
生成更多 Python 进程并在它们之间调整数据会产生一些开销因此并不总是能获得如此大的速度提升。 如果正在处理巨大的数据集那么设置 chunksize 参数的技巧可以提供很大帮助。 当有要处理的数据列表并且每条数据都可以独立处理时使用进程池是一个很好的解决方案。
以下是适合多处理的一些示例
从一组单独的 Web 服务器日志文件中获取统计信息从一堆 XML、CSV 或 json 文件中解析数据预处理大量图像以创建机器学习数据集
但进程池并不总是答案。使用进程池需要在单独的 Python 进程之间来回传递数据。如果正在使用的数据无法在进程之间有效传递那么这将不起作用。 如果你需要处理上一条数据的结果来处理下一条数据这也是行不通的。 这种情况下适合用Python 有一个全局解释器锁Global Interpreter Lock即 GIL。这意味着即使程序是多线程的任何线程一次也只能执行一条 Python 代码指令。换句话说多线程Python代码无法真正并行运行。 但进程池可以解决这个问题 因为运行的是真正独立的 Python 实例所以每个实例都有自己的 GIL。
可以获得 Python 代码的真正并行执行以一些额外开销为代价。 不要害怕并行处理 借助concurrent.futures 库Python提供了一种简单的方法来调整脚本以同时使用计算机中的所有 CPU 核心。
参考
https://medium.com/ageitgey/quick-tip-speed-up-your-python-data-processing-scripts-with-process-pools-cf275350163a