Python多进程统计多文本字符频率耗时增加的原因及优化方法
多进程耗时更高的原因及优化方案
一、耗时更高的根因
你遇到的多进程耗时更高的问题和IO无关,属于代码实现错误+进程开销未匹配计算量的计算相关问题,具体原因如下:
- 代码存在核心逻辑错误,未实现真正的并行
multiprocessing.Process初始化时要求target参数传入未执行的函数对象,你写的Process(countFreq(str1))会在主进程直接同步执行countFreq(str1),把返回的None作为target参数传入,后续启动的子进程根本没有执行统计逻辑。相当于你的多进程版本先串行跑了两次统计,还要额外承担进程创建、销毁的开销,耗时必然更高。 - 就算修正代码,小数据量下进程固定开销会超过并行收益
字符频率统计是纯CPU密集型任务,Python多进程本身有进程创建、内存拷贝(传入的字符串会完整复制到子进程空间)、调度的固定开销。如果你的文本文件总大小较小,统计本身耗时极短,多进程的开销会完全覆盖并行计算带来的收益。
二、正确优化方案
1. 优先优化统计逻辑,收益远高于盲目并行
你当前的countFreq实现时间复杂度为O(n²):先遍历一次字符串生成字符集合,再对每个字符遍历一次字符串统计次数,性能极低。优化为单次遍历的O(n)实现即可获得数倍到数十倍的性能提升:
# 方案1:单次遍历实现 def countFreq(data): res = {} for c in data: res[c] = res.get(c, 0) + 1 return res # 方案2:直接用内置的Counter,底层C实现,性能更高 from collections import Counter def countFreq(data): return Counter(data)
2. 修正多进程写法,仅在大数据量下使用
只有当单个文件大小在百MB级别以上,统计耗时足够长时,多进程才能体现加速效果,正确的多进程写法示例(用更简洁的ProcessPoolExecutor):
import time from collections import Counter from concurrent.futures import ProcessPoolExecutor def countFreq(data): return Counter(data) if __name__ == '__main__': # 此处替换为你读取的两个文本字符串 str1 = open("file1.txt", encoding="utf-8").read() str2 = open("file2.txt", encoding="utf-8").read() # 多进程版本 start = time.time() with ProcessPoolExecutor(max_workers=2) as pool: res1 = pool.submit(countFreq, str1) res2 = pool.submit(countFreq, str2) print(res1.result()) print(res2.result()) print(f"多进程耗时: {time.time() - start:.5f}s") # 串行对比版本 start = time.time() print(countFreq(str1)) print(countFreq(str2)) print(f"串行耗时: {time.time() - start:.5f}s")
3. 并行方案选型注意
该场景是CPU密集型任务,不要使用ThreadPoolExecutor:Python的全局解释器锁(GIL)会导致多线程无法并行执行CPU计算,不会有任何加速效果。
内容的提问来源于stack exchange,提问作者Parzival
相关产品推荐
相关产品推荐

