参考:https://blog.csdn.net/lucky_chaichai/article/details/123281048
Python与多进程multiprocessing
1、multiprocessing多进程模块
- pool( )类:指定进程池中同时执行的进程数为8,当一个进程执行完毕后,如果还有新进程等待执行,则会将其添加进去。
#创建并行处理池。max_tasks 参数指定了池中可以同时运行的最大进程数。
pool = multiprocessing.Pool(max_tasks)
-
pool.apply_async( ):为非阻塞,即不用等待当前运行的子进程执行完毕(各子进程并行执行,且主进程与子进程之间、各子进程之间都不会互相等待),随时根据系统调度来进行进程切换。
-
pool.apply( ):阻塞型,各子进程需依次执行,主进程会被阻塞直到函数执行结束
多进程执行过程中,子进程出错时,将直接跳出,执行主进程,且不会报错
主进程向子进程传递的参数不可以为类实例、导入的模块等(linux不可,windows则可以传递类实例);且注意传递的参数尽量不要太大(如大的模型、大的数据集),否则会占用很大内存,严重影响速度。
示例代码
使用128个进程检查10W级png图片并删除不正常的
不用多线程要跑34个小时,用多进程1-2分钟检查完成
'''
删除不正常的png图片
'''
from PIL import Image
import os
import cv2
import multiprocessing
from multiprocessing import Pool, Manager
from tqdm import tqdm
def is_valid_image(filename):
try:
img = Image.open(filename)
img.verify() # 验证图片是否损坏
return True
except (IOError, SyntaxError):
return False
def processing(split_img, idx):
clips_id = len(split_img)*idx + 1
print("clips_id",clips_id)
for image_name in tqdm(split_img):
if not is_valid_image(image_name):
print(f"\n\nDeleting invalid PNG file: {
image_name}")
os.remove(image_name)
# 调用函数检查指定文件夹中的图像文件
target_folder = '/xxx/xxx/xxx/train_data/xxxx/24_0416_train_118159/train/positive'
# 多进程处理图像的进程数量
num_processes=128
total_imgs = []
for root, dirs, files in os.walk(target_folder):
for file in files:
if file.lower().endswith('.png'):
file_path = os.path.join(root, file)
total_imgs.append(file_path)
print("total_imgs[0]=",total_imgs[0])
print("total_imgs size=",len(total_imgs))
#chunks() 函数将一个数组分成大小相等的部分。这里分成8份
def chunks(arr, p=num_processes):
n = int(len(arr) / p)
return [arr[i:i + n] for i in range(0, len(arr), n)]
split_imgs = chunks(total_imgs)
max_tasks = len(split_imgs)
print("max_tasks=",max_tasks)
#创建并行处理池。max_tasks 参数指定了池中可以同时运行的最大进程数。
pool = multiprocessing.Pool(max_tasks)
# 使用并行处理池来处理每个分块的图像。processing 是一个处理函数,
# 它需要四个参数:分块的图像、模型路径、保存路径和图像的索引。
# apply_async() 方法将 processing 函数添加到并行处理池中,并立即返回。
for idx, split_img in enumerate(split_imgs):
pool.apply_async(processing, ([split_img, idx]))
#pool.close() 方法关闭并行处理池,防止新的任务被添加到池中。pool.join() 方法等待所有任务完成。
pool.close()
pool.join()