我写了一个在GPU上处理数据的应用程序。代码能够正常运行,但是读取输入文件的部分(大约3GB,文本)是我应用程序的瓶颈。(从硬盘读取很快,但逐行处理缓慢)。
我使用getline()读取一行并将第1行复制到一个vector中,将第2行复制到另一个vector中,跳过第3和第4行。接下来对剩下的1100万行做同样的操作。
我尝试了几种方法来以最快的时间获取文件:
我发现最快的方法是使用boost::iostreams::stream
其他方法包括:
- 以gzip格式读取文件,以最小化IO,但比直接读取要慢。
- 使用read(filepointer, chararray, length)将文件复制到RAM中,并使用循环区分行(也比boost慢)
有什么建议可以使它运行得更快吗?
void readfastq(char *filename, int SRlength, uint32_t blocksize){
_filelength = 0; //total datasets (each 4 lines)
_SRlength = SRlength; //length of the 2. line
_blocksize = blocksize;
boost::iostreams::stream<boost::iostreams::file_source>ins(filename);
in = ins;
readNextBlock();
}
void readNextBlock() {
timeval start, end;
gettimeofday(&start, 0);
string name;
string seqtemp;
string garbage;
string phredtemp;
_seqs.empty();
_phred.empty();
_names.empty();
_filelength = 0;
//read only a part of the file i.e the first 4mio lines
while (std::getline(in, name) && _filelength<_blocksize) {
std::getline(in, seqtemp);
std::getline(in, garbage);
std::getline(in, phredtemp);
if (seqtemp.size() != _SRlength) {
if (seqtemp.size() != 0)
printf("Error on read in fastq: size is invalid\n");
} else {
_names.push_back(name);
for (int k = 0; k < _SRlength; k++) {
//handle special letters
if(seqtemp[k]== 'A') ...
else{
_seqs.push_back(5);
}
}
_filelength++;
}
}
编辑:
源文件可在https://docs.google.com/open?id=0B5bvyb427McSMjM2YWQwM2YtZGU2Mi00OGVmLThkODAtYzJhODIzYjNhYTY2 下载。
由于存在一些指针问题,我更改了函数 readfastq
以读取文件。因此,如果调用readfastq
,则 blocksize
(按行计的块大小)必须大于要读取的行数。
解决方案:
我找到了一个解决方案,将读取文件的时间从60秒减少到16秒。我删除了内部循环处理特殊字符,并在GPU上处理该操作。这样可以减少读入时间,并仅对GPU运行时间进行轻微增加。
感谢您的建议。
void readfastq(char *filename, int SRlength) {
_filelength = 0;
_SRlength = SRlength;
size_t bytes_read, bytes_expected;
FILE *fp;
fp = fopen(filename, "r");
fseek(fp, 0L, SEEK_END); //go to the end of file
bytes_expected = ftell(fp); //get filesize
fseek(fp, 0L, SEEK_SET); //go to the begining of the file
fclose(fp);
if ((_seqarray = (char *) malloc(bytes_expected/2)) == NULL) //allocate space for file
err(EX_OSERR, "data malloc");
string name;
string seqtemp;
string garbage;
string phredtemp;
boost::iostreams::stream<boost::iostreams::file_source>file(filename);
while (std::getline(file, name)) {
std::getline(file, seqtemp);
std::getline(file, garbage);
std::getline(file, phredtemp);
if (seqtemp.size() != SRlength) {
if (seqtemp.size() != 0)
printf("Error on read in fastq: size is invalid\n");
} else {
_names.push_back(name);
strncpy( &(_seqarray[SRlength*_filelength]), seqtemp.c_str(), seqtemp.length()); //do not handle special letters here, do on GPU
_filelength++;
}
}
}
string::empty()
和vector::empty()
是对容器状态的只读测试。也许你想使用.clear()
方法? - André Caron_seqs.empty();
只会返回true
。默认构造函数会创建一个空字符串,而bool std::string::empty() const
和void std::string::clear()
是不同的。 - MSalters