Python中的多处理与线程
Posted
技术标签:
【中文标题】Python中的多处理与线程【英文标题】:Multiprocessing vs Threading in Python 【发布时间】:2021-06-26 01:42:21 【问题描述】:我正在学习python中的多处理和线程来处理和创建大量文件,图在这里显示diagram
每个输出文件都依赖于所有输入文件的分析。
程序的单次处理需要相当长的时间,所以我尝试了以下代码:
(a) 多处理
start = time.time()
process_count = cpu_count()
p = Pool(process_count)
for i in range(process_count):
p.apply_async(my_read_process_and_write_func, args=(i,w))
p.close()
p.join()
end = time.time()
(b) 线程
start = time.time()
thread_count = cpu_count()
thread_list = []
for i in range(0, thread_count):
t = threading.Thread(target=my_read_process_and_write_func, args=(i,))
thread_list.append(t)
for t in thread_list:
t.start()
for t in thread_list:
t.join()
end = time.time()
我在具有 8 个内核的 Windows PC 上使用 Python 3.6 运行这些代码。但是Multiprocessing方法与单处理方法的时间差不多,而Threading方法大约是单处理方法的75%。
我的问题是:
我的代码正确吗?
有没有更好的方法/代码来提高效率? 谢谢!
【问题讨论】:
【参考方案1】:您的处理受 I/O 限制,而不是 CPU 限制。结果,您拥有多个进程这一事实几乎没有帮助。多处理中的每个 Python 进程都在等待输入或输出,而 CPU 什么也不做。增加多处理中的池大小应该会提高性能。
【讨论】:
感谢 Tarik,您的回答帮了大忙! 答案已接受,我在下面提供了我当前的解决方案。如果有更好的方法请赐教,谢谢。【参考方案2】:按照 Tarik 的回答,由于我的处理受 I/O 限制,我制作了输入文件的多个副本,然后每个处理读取并处理这些文件的不同副本。 现在我的代码运行速度快了 8 倍。
【讨论】:
您的意思是您拥有相同的输入文件副本?您是否以只读模式打开输入文件? 是的。我试图在多处理中增加池大小,但没有太大区别。由于我的任务是I/O绑定的,所以我复制了输入文件,每个进程读取输入文件的对应副本,生成不同的输出文件。 你让我对“我制作了多个输入文件的副本”感到好奇,因为它不应该有任何影响,原因是一旦被操作系统读取,文件块将被缓存在系统内存中, 除非输入文件太大以至于不允许缓存。在多个进程正在处理同一个大输入文件的情况下,我会让主进程按顺序读取文件,并为工作进程提供已读取的数据。如果输入文件很小,那么它很可能一直都在缓存中。 输入文件在我看来相当大(330MB x 超过 100 个文件),我已经用图表发布了我当前的解决方案。【参考方案3】:现在我的处理图是这样的。 我的输入文件包括一个索引文件(大约 400MB)和 100 个其他文件(每个大小=330MB,可以认为是一个文件池)。 为了生成一个输出文件,需要读取文件池中的索引文件和所有文件。 (例如,索引文件的第一行是 15,然后需要读取文件池中每个文件的第 15 行以生成输出 file1。) 以前我在不复制的情况下尝试了多处理和线程,代码非常慢。然后我通过只为每个处理复制索引文件来优化代码,因此每个处理单独读取索引文件的副本,然后读取文件池以生成输出文件。 目前,使用 8 个 cpu 内核,poolsize=8 的多处理需要最少的时间。
【讨论】:
这让我很困惑:为什么同一个文件的多个副本比单个副本执行得更好,因为单个副本在读取时会被操作系统缓存在内存中。您是否以只读模式打开索引文件?很抱歉打扰,但我真的很想知道为什么,我可能会理解一些我不知道的事情。 是的,我使用“with open(index_file) as index_reader”来读取索引文件,我认为默认是只读模式。 我对内存缓存了解不多。您是否建议如果我使用多处理读取单个索引文件,多个进程能够同时读取缓存的索引文件?以上是关于Python中的多处理与线程的主要内容,如果未能解决你的问题,请参考以下文章