随机播放大量项目而不加载到内存中
问题内容:
我有一个包含约20亿行文本(约200gigs)的文件。我想产生一个包含相同文本行的新文件,但按行随机随机排列。我无法将所有数据保存在内存中。是否有一个好的方法可以在python
/命令行中执行此操作,而这需要花费相当长的时间(几天)?
我当时想我可以触摸50个空文件。流过20亿行文件,并将每行随机分配到50个空文件之一。然后整理50个文件。这种方法是否会有重大的系统性偏见?
问题答案:
如果您可以为该程序保留16
GB的内存,则我编写了一个名为的程序,该程序sample
通过读取文件的各行的字节偏移量,对偏移量进行混排,然后通过搜索文件至经过混洗的偏移量来打印输出。每个64位偏移量使用8个字节,因此20亿行输入使用16
GB。
它不会很快,但是在具有足够内存的系统上,sample
将洗排足以导致GNUshuf
失败的文件。此外,它使用mmap例程来尝试最小化第二次通过文件的I
/ O开销。它还有其他一些选择。请参阅--help
参考资料。
默认情况下,该程序将采样而不进行替换,并且按行随机播放。如果要通过替换进行混洗,或者输入的格式为FASTA,FASTQ或其他多行格式,则可以添加一些选项来调整采样方式。(或者,您可以应用一种替代方法,我在下面的Perl要点中链接了该方法,但sample
解决了这些情况。)
如果您的FASTA序列在每两行上,也就是说,它们在一行的序列头和下一行的序列数据之间交替,则您仍然可以使用sample
,一半的内存进行混洗,因为您只需要偏移量的一半。查看--lines- per-offset
选项;2
例如,您可以指定随机排列几对线。
对于FASTQ文件,它们的记录每四行分割一次。您可以指定--lines-per- offset=4
使用随机播放单行文件所需内存的四分之一来随机播放FASTQ文件。
另外,我这里有一个用Perl编写的要点,它将对序列进行采样,而无需从FASTA文件中进行替换,而无需考虑序列中的行数。请注意,这与改组整个文件并不完全相同,但是您可以以此为起点,因为它会收集偏移量。您无需删除一些偏移量,而是删除对经过改组的索引进行排序的第47行,然后使用文件查找操作直接使用改组后的索引列表来读取文件。
再说一次,它不会很快,因为您会无序地跳过一个非常大的文件,但是存储偏移量比存储整行要便宜得多,并且添加mmap例程实际上可以解决一系列随机问题访问操作。而且,如果您使用FASTA,则存储的偏移量将更少,因此,内存使用量(除了相对微不足道的容器和程序开销之外)最多应为8
GB,并且可能更少,具体取决于其结构。