正在分析非二进制(Python或C++)的大文件



作为免责声明,我几乎不是一名计算机科学家,但我一直在阅读关于高效文件I/o的所有内容,试图解决我正在进行的项目的这一方面。

我有一个非常大(10-100GB)的日志文件,其中包含逗号分隔的值,我需要解析这些值。第一个值将其标记为"A"或"B";对于每一个"A"行,我需要检查它之前的行和之后的行,如果它之前或之后的行符合标准,我想将其存储在内存中或写入文件。线条大小不一致。

这就是我的具体问题:我似乎找不到在非二进制文件中实现这一点的高效方法。对于二进制文件,我只需在文件上迭代一次,然后通过逻辑检查来回倒带。我研究过内存映射,但它似乎是为二进制文件构建的;我目前的代码是Python代码,运行需要数周时间[参见免责声明]。

我的另一个问题是——在这里调用并行性有多容易?我知道如何一次将文件映射出三行,并将每个块发送到每个节点[第1、2、3行到一个节点;第3、4、5行到另一个节点…],但我不知道如何实现这一点。

如有任何帮助,我们将不胜感激。

只需读取循环中的行即可。跟踪内存中的前一行,并在需要时对其进行检查。

伪码:

for each line:
previousLine := currentLine
read currentLine from file
do processing...

假设您已经将每一行读取到内存中,并且使用适当的缓冲方案读取文件(一次将大块读取到内存),那么这是有效的。

我认为在这种情况下,并行性不会有帮助。如果写得正确,程序的瓶颈应该是磁盘I/O,多个线程/进程从磁盘读取的速度不能比单个线程快。并行性只会改善CPU绑定问题。

值得一提的是,您可以像处理二进制文件一样在ASCII文件中"查找"。每次开始读取一行时,您只需跟踪文件偏移量,并存储该偏移量,这样您就知道以后要查找的位置。不过,根据实现方式的不同,它的性能永远不会比上述更好,有时甚至更糟(您希望将文件数据缓冲在内存中,以便"查找"是一种内存操作,而不是磁盘操作;您肯定希望按顺序读取文件内容,以最大限度地提高提前缓存的优势)。

这是第一步。假设文本行格式正确。

from itertools import chain
with open('your-file') as f:
prev_line = None
cur_line = f.readline()
for next_line in chain(f, [None]):
pieces = cur_line.split(',')
if pieces[0] == 'A':
check_against_criterion_if_not_none(prev_line)
check_against_criterion_if_not_none(next_line)
prev_line, cur_line = cur_line, next_line

一个绝妙的技巧是使用itertools.chain在文件末尾添加额外的"None",这样代码就可以根据倒数第二行正确地检查文件的最后一行。

最新更新