目录
- 背景
- 单个输入参数
- 多个输入参数
背景
在工作或者生活中,可能会遇到大量的for循环处理逻辑,这些逻辑完全可以并行(比如读取一个文件夹中的所有图片,然后将其resiz到最长边不超过960),此时我们可以使用多进程的方法,并行处理这些逻辑,从而大幅降低程序运行时间。
我们使用官方的multiprocessing库就可以完成这些操作。下面直接给出具体示例。
单个输入参数
下面是单进程和多进程的演示demo,将process_num
参数修改为8,即表示进程数为8去处理。
import time
import cv2
import os
import numpy as np
from multiprocessing import Pooldef resize(img_path):# 这里使用假数据进行测试if not os.path.exists(img_path):img = np.zeros([1920, 1080, 3]).astype(np.uint8)else:img = cv2.imread(img)new_img = cv2.resize(img, [320, 480])return new_imgdef test_mp_resize():img_paths = ["fake_path"] * 10000start_time = time.time()process_num = 1with Pool(process_num) as pool:res = pool.map(resize, img_paths)cost_time = time.time() - start_timeprint(f"process num: {process_num}, cost time: {cost_time} s")if __name__ == "__main__":test_mp_resize()
不同进程数下的耗时对比如下。可以看出多进程在速度方面还是有优势的,不过受到我自己的机器CPU kernel数以及传参的影响,这里并没有线性的加速的效果。
(py38) ➜ mp_demo python test_mp.py
process num: 1, cost time: 52.58454394340515 s
(py38) ➜ mp_demo python test_mp.py
process num: 2, cost time: 39.837116956710815 s
(py38) ➜ mp_demo python test_mp.py
process num: 4, cost time: 36.69755434989929 s
(py38) ➜ mp_demo python test_mp.py
process num: 8, cost time: 34.3617799282074 s
多个输入参数
下面的代码展示了怎么对于多个输入传参的情况使用多进程。步骤有:
- 使用zip构建参数列表,见下面
test_mp_resize
函数的input_args
生成过程。 - 新建一个函数,用于参数解析与传递,见下面的
resize_one_input
,他的作用就是将一个输出列表转化为多输入*args
的形式。 - 使用多进程。
import time
import cv2
import os
import numpy as np
from multiprocessing import Pooldef resize(img_path, shape):# 这里使用假数据进行测试if not os.path.exists(img_path):img = np.zeros([1920, 1080, 3]).astype(np.uint8)else:img = cv2.imread(img)new_img = cv2.resize(img, shape)return new_imgdef resize_one_input(inputs):return resize(*inputs)def test_mp_resize():img_paths = ["fake_path"] * 10000shapes = [[320, 480]] * len(img_paths)input_args = zip(img_paths, shapes)start_time = time.time()process_num = 2with Pool(process_num) as pool:res = pool.map(resize_one_input, input_args)cost_time = time.time() - start_timeprint(f"process num: {process_num}, cost time: {cost_time} s")if __name__ == "__main__":test_mp_resize()