Python逐行读取文件时多进程比单进程慢4000倍,问题出在哪?
嘿,我来帮你拆解下为什么多进程反而更慢,以及怎么搞定这个问题~
问题根源分析
你的多进程代码变慢的核心问题其实出在跨进程通信(IPC)的开销太大,完全抵消了并行处理的优势!你用Manager()创建的共享队列和列表,本质上是通过后台套接字在进程间同步数据——每往队列里塞一行、往共享列表里加一次结果,都要做序列化、跨进程传输、反序列化,还要处理锁来保证安全。而你的处理逻辑又特别简单(只是分割制表符),这种通信开销比你实际做的工作还重,自然比单进程慢,CPU也因为大部分时间在等通信而跑不满。
另外你的代码还有个小疏漏:没给工作进程发退出信号(也就是往队列里放None),导致子进程会一直卡在in_queue.get()那里,最后可能没法正常退出,但这不是性能差的主要原因。
优化方案
针对大文件的简单行处理,我们可以用multiprocessing.Pool来替代手动管理队列和共享列表,Pool内部的任务分发机制更高效,能减少很多不必要的通信开销。这里有两种更合适的方式:
方案一:用Pool.imap处理逐行数据
imap是迭代式的,适合处理大文件,它会自动把数据分块发送给子进程,减少进程间的通信次数:
from multiprocessing import Pool def process_line(line): # 你的处理逻辑,这里是分割制表符 return line.split("\t") if __name__ == "__main__": num_workers = 4 file_path = "your_large_file.txt" with Pool(num_workers) as pool: # 打开文件并逐行迭代,imap会自动分发任务 results = pool.imap(process_line, open(file_path, 'rt', newline="\n")) # 把结果收集到列表里(如果需要排序的话) sorted_results = sorted(results) print(sorted_results)
方案二:分块读取文件(更适合超大型文件)
如果文件特别大,可以先把文件分成几个大的块,每个进程处理一块,进一步减少IPC的次数:
from multiprocessing import Pool import os def process_chunk(chunk): results = [] for line in chunk.splitlines(): results.append(line.split("\t")) return results def split_file_into_chunks(file_path, chunk_size=1024*1024*100): # 100MB每块 chunks = [] with open(file_path, 'rt', newline="\n") as f: while True: chunk = f.read(chunk_size) if not chunk: break # 确保块结尾是完整的一行,避免分割到行中间 if not chunk.endswith("\n"): chunk += f.readline() chunks.append(chunk) return chunks if __name__ == "__main__": num_workers = 4 file_path = "your_large_file.txt" chunks = split_file_into_chunks(file_path) with Pool(num_workers) as pool: # 每个进程处理一个块 chunk_results = pool.map(process_chunk, chunks) # 合并所有结果 all_results = [] for res in chunk_results: all_results.extend(res) sorted_results = sorted(all_results) print(sorted_results)
额外优化建议
- 如果你不需要保留所有结果,而是可以边处理边输出,那就不要把所有结果都存在内存里,这样能节省内存,也避免最后排序的开销。
- Mac系统下,Python的
multiprocessing默认用spawn方式创建进程(而非Linux的fork),会有一点额外的启动开销,但核心问题还是IPC,上面的方案已经能解决。 - 测试的时候可以先拿小文件验证逻辑,再跑大文件,避免浪费时间。
内容的提问来源于stack exchange,提问作者Bethany Kok
相关产品推荐
相关产品推荐

