在Cpp中处理大型文本文件(> 50 GB)

时间:2017-10-25 04:41:26

标签: c++ openmp bioinformatics

我想处理的文本文件大小超过>主要包含DNA序列的50 GB。我想按块处理这个文件块,如下所述 -

  1. 将X MB(比方说100 MB)的数据读入数组(存储桶)(读取数据 没有将最后一个字符串分成一个块)
  2. 创建线程来处理此数组(存储桶)(使用open mp:schedule static)
  3. 我有以下问题:

    1. How to read a file chunk by chunk efficiently?
    2. Alternative approach that i should follow.
    3. Any algo/framework that i should go for.
    

    由于

3 个答案:

答案 0 :(得分:0)

假设您在读取数据时没有对数据进行大量计算,那么您的程序几乎肯定会受到I / O限制 - 也就是说,CPU和RAM的运行速度会快得多而不是硬盘驱动器的带宽,操作的总速度几乎完全取决于硬盘的数据读取速度。

因此,我建议做的第一件事就是计算读取整个文件需要多长时间(而不是对所产生的内存数据做任何事情)。这将为您提供“最佳情况” - 即如果您的非I / O代码如此高效以至于不花时间,您可以期待什么样的性能。然后,您的目标是尝试让您的实际程序尽可能接近该性能。

至于如何从磁盘读取数据,它可能无关紧要,因为像fread()和fgets()这样的调用在C标准库和文件系统层都使用缓冲,所以即使你正在少量读取(例如,一次一行文本),当请求到达实际I / O硬件时,它是一个更大(更有效)的预读请求,无论如何都将有效地使用硬件。也就是说,你可以尝试在单个fread()调用中以兆字节(或100兆字节)读取(如果你想要(然后通过巨型缓冲区来解析各行文本),但我认为你会发现它不会明显快于在循环中调用fgets()直到你到达文件的末尾。

(并且对于不可避免的C ++纯粹主义者抱怨说因为这个问题被标记为C ++,OP应该使用iostreams ...确定,这也值得尝试,尽管我发现iostream难以使用和一些实现众所周知,iostream是低效的。幸运的是,像这样的问题很简单,测试多种方法并测量哪种方法提供最佳性能是切实可行的。

就替代方法而言 - 如果你想要比上面提到的更快的加速,你将要开始考虑改变问题的参数。由于您(可能)I / O受限,因此加快速度的最佳方法是读取较少的数据。您的文件格式是否真的需要是未压缩的ASCII文本?是否可以将其更改为更紧凑的二进制格式(例如,如果我记得我的遗传学正确的话,每个碱基对2位),那么文件大小可能是12GB而不是50GB?和/或它是否可以存储zlib压缩,进一步减小文件大小?由于CPU现在与磁盘相比如此之快,因此读取较小的文件然后对其进行zlib膨胀可能比读取更大的文件并逐字使用(!)

更快

答案 1 :(得分:0)

此主题似乎与阅读文件有关 multithread read from disk?

看来,由于您只是在阅读,最好的方法是按顺序读取,直到最后,每次有一个X字节的本地缓冲区时,就会产生一个计算线程。

这当然只有在每个块计算是独立的时才可行。

答案 2 :(得分:0)

如果磁盘容量不是问题,我建议使用split命令(或类似命令)对文件进行分块。

例如,使用-l命令的split选项生成~100MB的文件。如果文件采用多行FASTA格式,请确保FASTA标头和序列均在一行中,然后为-l的值指定偶数。

然后编写一个处理单个块的程序。根据需要并行化此工作流程(批处理调度程序等)以处理所有块。