>我在具有多处理的巨大数据集上运行图像处理,我想知道在池中运行 ThreadPoolExecutor 是否比简单地在所有项目上运行 Pool 有任何好处。
数据集包含多个文件夹,每个文件夹包含图像,所以我最初的想法是将每个文件夹拆分为一个进程,将该文件夹中的每个图像拆分为一个线程。另一种方法是获取每个图像并将其作为一个进程运行。
例如,每个文件夹作为一个进程,每个图像作为一个线程
from concurrent import futures
from multiprocessing import Pool
from pathlib import Path
def handle_image(image_path: Path):
pass
def handle_folder(folder_path: Path):
with futures.ThreadPoolExecutor() as e:
e.map(handle_image, folder_path.glob("*"))
e.shutdown()
if __name__ == '__main__':
dataset_folder = Path("Folder")
with Pool() as p:
p.imap_unordered(handle_folder, dataset_folder.iterdir())
p.close()
p.join()
与每个图像作为一个过程
from multiprocessing import Pool
from pathlib import Path
def handle_image(image_path: Path):
if not image_path.is_file():
return
if __name__ == '__main__':
dataset_folder = Path("Folder")
with Pool() as p:
p.imap_unordered(handle_image, dataset_folder.glob("**/*"), 100)
p.close()
p.join()
您的任务(图像处理(听起来受 CPU 限制,因此线程将没有足够的空闲时间来让彼此执行,除非您委托给某个 C 库来释放大多数处理的 GIL。
但是,如果处理时间与 I/O 时间相当,则每个进程最多可以加速几个线程(参见,在执行 I/O 绑定任务时,20 个进程中的 400 个线程的性能优于 4 个进程中的 400 个线程,因为时间与更多的 I/O 绑定任务相比(。
作为旁注,对于大规模分布式工作,您可以查看 Python 分布式任务队列的第三方实现之一,而不是内置的池和map
。