我有一个非常大的文本文件(27GB),我试图通过删除在第二个数据库中复制的行来缩小,这个数据库有几个更合理的文件(500MB-2GB)。我有一些功能代码,我想知道的是有什么方法可以优化这段代码来运行更快,人类的时钟时间?目前,在1.5GB输入和500MB过滤器的小型测试运行中,这需要75秒才能完成。
我已经经历了这个想法的多次迭代,这个目前最好的时间,如果有人有想法为过滤器做出更好的逻辑结构我很乐意听到它,过去的尝试都变得更糟比这一个:将过滤器加载到一个集合中并循环通过输入搜索重复项(大约是此速度的一半),将输入加载到一个集合中并通过difference_update运行过滤器(几乎与此一样快但也在执行反转我想要的东西,并将输入和过滤器加载到块中的集合并进行设置差异(这是一个可怕的,可怕的想法,可能会工作(也许?)如果我的过滤器较小,所以我不必拆分它们也是。)
所以,这些都是我尝试过的。所有这些进程都在CPU上最大化,我的最终版本运行在大约25-50%的磁盘I / O,过滤器和输出在一个物理磁盘上,输入在另一个物理磁盘上。我正在运行双核心,并且不知道这个特定的脚本是否可以被线程化,之前从未进行任何多线程处理,如果可能的话,我希望能指向正确的方向。
有关数据的信息!如前所述,输入比滤波器大许多倍。我期待重复的比例非常小。数据在行中,所有行都长度不超过20个ASCII字符。这些文件都已排序。
我已经改变了三个逻辑语句的顺序,基于期望独特的输入行将是大多数行,然后是唯一的过滤器,然后是重复的,这是在“没有重复”的“最佳”情况下在任何时候,我节省了大约10%的时间。
有什么建议吗?
def sortedfilter(input,filter,output):
file_input = open(input,'r')
file_filter = open(filter,'r')
file_output = open(output,'w')
inline = file_input.next()
filterline = file_filter.next()
try:
while inline and filterline:
if inline < filterline:
file_output.write(inline)
inline = file_input.next()
continue
if inline > filterline:
filterline = file_filter.next()
continue
if inline == filterline:
filterline = file_filter.next()
inline = file_input.next()
except StopIteration:
file_output.writelines(file_input.readlines())
finally:
file_filter.close()
file_input.close()
file_output.close()
答案 0 :(得分:1)
通过执行cmp(inline, filterline)
:
-1
表示inline < filterline
0
表示inline == filterline
+1
表示inline < filterline
。这可能会让你获得额外的百分比。如下所示:
while inline and filterline:
comparison = cmp(inline, filterline)
if comparison == -1:
file_output.write(inline)
inline = file_input.next()
continue
if comparison == 1:
filterline = file_filter.next()
continue
if comparison == 0:
filterline = file_filter.next()
inline = file_input.next()
答案 1 :(得分:1)
看到您的输入文件已排序,以下内容应该有效。 heapq的合并从groupby操作的已排序输入生成一个已排序的流;长度大于1的组将被丢弃。这种基于流的方法应具有相对较低的内存要求
from itertools import groupby, repeat, izip
from heapq import merge
from operator import itemgetter
with open('input.txt', 'r') as file_input, open('filter.txt', 'r') as file_filter, open('output.txt', 'w') as file_output:
file_input_1 = izip(file_input, repeat(1))
file_filter_1 = izip(file_filter, repeat(2))
gen = merge(file_input_1, file_filter_1)
gen = ((k, list(g)) for (k, g) in groupby(gen, key=itemgetter(0)))
gen = (k for (k, g) in gen if len(g) == 1 and g[0][1] == 1)
for line in gen:
file_output.write(line)
答案 2 :(得分:1)
我有兴趣知道这是如何比较的;它基本上只是在尝试迭代次序。
def sortedfilter(in_fname, filter_fname, out_fname):
with open(in_fname) as inf, open(filter_fname) as fil, open(out_fname, 'w') as outf:
ins = inf.next()
try:
for fs in fil:
while ins < fs:
outf.write(ins)
ins = inf.next()
while ins == fs:
ins = inf.next()
except StopIteration:
# reached end of inf before end of fil
pass
else:
# reached end of fil first, pass rest of inf through
file_output.writelines(file_input.readlines())
答案 3 :(得分:0)
考虑将文件打开为二进制文件,因此不需要转换为unicode:
with open(in_fname,'rb') as inf, open(filter_fname,'rb') as fil, open(out_fname, 'wb') as outf: