Anu*_*ush 19 python performance multiprocessing
我有一个大文件,我需要阅读并从中制作字典.我希望这个尽可能快.但是我在python中的代码太慢了.这是一个显示问题的最小示例.
首先制作一些假数据
paste <(seq 20000000) <(seq 2 20000001) > largefile.txt
Run Code Online (Sandbox Code Playgroud)
现在这里有一段最小的python代码来读取它并制作一本字典.
import sys
from collections import defaultdict
fin = open(sys.argv[1])
dict = defaultdict(list)
for line in fin:
parts = line.split()
dict[parts[0]].append(parts[1])
Run Code Online (Sandbox Code Playgroud)
时序:
time ./read.py largefile.txt
real 0m55.746s
Run Code Online (Sandbox Code Playgroud)
但是,可以更快地读取整个文件:
time cut -f1 largefile.txt > /dev/null
real 0m1.702s
Run Code Online (Sandbox Code Playgroud)
我的CPU有8个内核,是否有可能在python中并行化这个程序来加速它?
一种可能性是读入大块输入,然后在不同的非重叠子块上并行运行8个进程,使字典与内存中的数据并行,然后在另一个大块中读取.在某种程度上使用多处理的python中这是可能的吗?
更新.假数据不是很好,因为每个键只有一个值.更好的是
perl -E 'say int rand 1e7, $", int rand 1e4 for 1 .. 1e7' > largefile.txt
Run Code Online (Sandbox Code Playgroud)
(与大文件中的读取和制作字典相关.)
可以并行化以加快速度,但是并行进行多次读取不太可能有所帮助。
您的操作系统不太可能有效地并行执行多次读取(例外是类似条带化RAID阵列的情况,在这种情况下,您仍然需要知道跨步才能最佳利用它)。
您可以做的是与读取并行运行相对昂贵的字符串/字典/列表操作。
因此,一个线程读取(大)块并将其推入同步队列,一个或多个使用者线程从队列中拉出块,将其拆分为行,然后填充字典。
(如果您要使用多个使用者线程,如Pappnese所说,请为每个线程构建一个字典,然后将其加入)。
提示:
回覆。赏金:
C显然没有GIL可以与之抗衡,因此多个使用者可能会更好地扩展。读取行为不会改变。不利的一面是C缺乏对哈希映射(假设您仍然想要Python样式的字典)和同步队列的内置支持,因此您必须找到合适的组件或编写自己的组件。多个消费者各自建立自己的字典,然后在最后合并它们的基本策略可能仍然是最好的。
使用strtok_r
代替str.split
可能会更快,但是请记住,您还需要手动管理所有字符串的内存。哦,您也需要逻辑来管理线段。老实说,C为您提供了许多选择,我认为您只需要对其进行概要分析即可看到。
几年前,蒂姆·布雷 (Tim Bray) 的网站上有一篇关于此问题的博客文章系列“Wide Finder Project”[1]。您可以在那里找到由 ElementTree [3] 和 PIL [4] 的 Fredrik Lundh 提供的解决方案 [2]。我知道在这个网站上通常不鼓励发布链接,但我认为这些链接比复制粘贴他的代码给你更好的答案。
[1] http://www.tbray.org/ongoing/When/200x/2007/10/30/WF-Results
[2] http://effbot.org/zone/wide-finder.htm
[3] http ://docs.python.org/3/library/xml.etree.elementtree.html
[4] http://www.pythonware.com/products/pil/