我正在尝试编写一个程序,根据每个序列的某个段内的值将大量基因序列分成许多文件。例如,序列可能看起来像
AGCATGAGAG...
GATCAGGTAA...
GATGCGATAG...
... 100 million more
然后,目标是根据位置2到7(6个碱基)的序列将读取分成单个文件。所以我们得到像
这样的东西AAAAAA.txt.gz
AAAAAC.txt.gz
AAAAAG.txt.gz
...4000 more
现在天真地我实现了一个
的C ++程序像
这样的东西#include <zlib.h>
void main() {
SeqFile seq_file("input.txt.gz");
string read;
while (read = seq_file.get_read) {
string tag = read.substr(1, 6);
output_path = tag + "txt.gx";
gzFile output = gzopen(output_path.c_str(), "wa");
gzprintf(output, "%s", read);
gzclose(output);
}
}
与将整个内容写入单个其他文件相比,这是无法忍受的缓慢。
这种情况有什么瓶颈?如果由于系统限制而无法同时打开所有文件,我将如何提高性能?
答案 0 :(得分:1)
由于打开文件很慢,您需要减少打开的文件数。实现此目的的一种方法是对输入进行多次传递。打开输出文件的子集,对输入进行传递,只将数据写入这些文件。完成后,关闭所有这些文件,重置输入,打开一个新子集,然后重复。
答案 1 :(得分:1)
瓶颈是打开和关闭输出文件。如果你可以以某种方式将其移出循环,例如通过同时打开多个输出文件,您的程序应该显着加快。在最好的情况下,可以同时打开所有4096个文件,但如果你遇到一些系统障碍,即使打开较少数量的文件,并且通过文件进行多次传递也应该更快打开和关闭文件紧紧的循环。
答案 2 :(得分:0)
压缩可能会减慢写入速度,写入文本文件然后压缩可能值得一试。
打开文件是一个瓶颈。有些数据可以存储在容器中,当达到一定大小时,将最大的数据集写入相应的文件中。
答案 3 :(得分:0)
我实际上无法回答这个问题 - 因为要做到这一点,我需要访问您的系统(或合理精确的副本)。磁盘的类型及其连接方式,内存的数量和类型以及CPU的型号/数量都很重要。
然而,有一些不同的事情需要考虑,这可能会有所帮助(或者至少告诉你“你不能做得比这更好”)。
首先找出占用时间的内容:CPU或磁盘I / O?
使用top
或system monitor
或其他类似内容来衡量应用程序使用的CPU使用情况。
编写一个简单的程序,将单个值(零?)写入文件,而不是压缩文件,其大小与文件中的大小相似。将其与编写gzip文件所需的时间进行比较。如果时间大致相同,那么你就受I / O限制了,你所做的事情可能并不重要。
如果你有大量的CPU使用率,你可能想要将写作工作分成多个线程 - 你显然不能真正用读取来做,因为它必须是顺序的(在多个线程中读取gzip不是如果可能的话,很容易,所以我们不要试试。每个CPU核心使用一个线程,因此如果你有4个核心,则使用1来读取,使用3来写入。你可能没有达到4倍的表现,但你应该得到很好的改善。
当然,在某些时候,你将受到磁盘速度的限制。然后唯一的选择是购买更好的磁盘(如果你还没有!)