【发布时间】:2022-01-21 16:27:03
【问题描述】:
这是一个定时示例,多个不同大小的图像数组被保存在一个循环中以及同时使用线程/进程:
import tempfile
from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor, as_completed
from pathlib import Path
from time import perf_counter
import numpy as np
from cv2 import cv2
def save_img(idx, image, dst):
cv2.imwrite((Path(dst) / f'{idx}.jpg').as_posix(), image)
if __name__ == '__main__':
l1 = np.random.randint(0, 255, (100, 50, 50, 1))
l2 = np.random.randint(0, 255, (1000, 50, 50, 1))
l3 = np.random.randint(0, 255, (10000, 50, 50, 1))
temp_dir = tempfile.mkdtemp()
workers = 4
t1 = perf_counter()
for ll in l1, l2, l3:
t = perf_counter()
for i, img in enumerate(ll):
save_img(i, img, temp_dir)
print(f'Time for {len(ll)}: {perf_counter() - t} seconds')
for executor in ThreadPoolExecutor, ProcessPoolExecutor:
with executor(workers) as ex:
futures = [
ex.submit(save_img, i, img, temp_dir) for (i, img) in enumerate(ll)
]
for f in as_completed(futures):
f.result()
print(
f'Time for {len(ll)} ({executor.__name__}): {perf_counter() - t} seconds'
)
我在 i5 mbp 上获得这些持续时间:
Time for 100: 0.09495482999999982 seconds
Time for 100 (ThreadPoolExecutor): 0.14151873999999998 seconds
Time for 100 (ProcessPoolExecutor): 1.5136184309999998 seconds
Time for 1000: 0.36972280300000016 seconds
Time for 1000 (ThreadPoolExecutor): 0.619205703 seconds
Time for 1000 (ProcessPoolExecutor): 2.016624468 seconds
Time for 10000: 4.232915643999999 seconds
Time for 10000 (ThreadPoolExecutor): 7.251599262 seconds
Time for 10000 (ProcessPoolExecutor): 13.963426469999998 seconds
难道线程/进程不需要更少的时间来完成同样的事情吗?在这种情况下为什么不呢?
【问题讨论】:
-
用ex.map代替submit会一样吗?
-
进程和线程持续时间提高到与 for 循环持续时间完全相同,这几乎是相同的问题。
-
i/o 绑定计算一般不会被多线程加速。线程为多个 cpu 提供同时提供周期的潜力。但是保持 i/o 通道完全充满需要很少的 cpu 工作。因此,提高 CPU 功率的潜力并没有帮助。
-
那么在这个特定的用例中,你的意思是多线程和多处理方法都不是必需的,最好使用 for 循环吗?如果是这样,那么加快速度的正确方法是什么?同时与否
-
正在写入 100、1000 和 10000 个图像,您会混淆图像大小的第一个维度。我在一些文本生成代码中使用相同的逻辑,将文本呈现为图像并保存它们。该示例只是一个简化版本。我提到在 i5 macbook pro 上运行示例。
标签: python multithreading image multiprocessing