mic*_*mic 10 c++ text file getline
我写了一个处理GPU上数据的应用程序.代码运行良好,但我有一个问题,输入文件的读取部分(~3GB,文本)是我的应用程序的瓶颈.(从HDD读取速度很快,但逐行处理很慢).
我用getline()读取一行,将第1行复制到向量,将第2行复制到向量,并跳过第3和第4行.依此类推其余11条mio行.
我尝试了几种方法来尽可能地获取文件:
我发现最快的方法是使用boost :: iostreams :: stream
其他人是:
任何建议如何让它运行得更快?
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++;
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:
源文件可从https://docs.google.com/open?id=0B5bvyb427McSMjM2YWQwM2YtZGU2Mi00OGVmLThkODAtYzJhODIzYjNhYY2下载
我更改了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++;
}
}
}
Run Code Online (Sandbox Code Playgroud)
首先,不是将文件读入内存,您可以使用文件映射.您只需将程序构建为64位以适应3GB的虚拟地址空间(对于32位应用程序,只能在用户模式下访问2GB).或者,您也可以按部件映射和处理文件.
接下来,听起来你的瓶颈是"将一条线复制到一个矢量".处理向量涉及动态内存分配(堆操作),这在关键循环中非常严重地影响性能.如果是这种情况 - 要么避免使用向量,要么确保它们在循环外声明.后者有帮助,因为当你重新分配/清除向量时,它们不会释放内存.
发布您的代码(或其中的一部分)以获取更多建议.
编辑:
似乎所有瓶颈都与字符串管理有关.
std::getline(in, seqtemp);阅读std::string动态内存分配的处理._names.push_back(name);这更糟糕.首先将std::string其放入vectorby 值.均值 - 复制字符串,因此发生另一个动态分配/释放.此外,当最终vector内部重新分配时 - 所有包含的字符串将被再次复制,并带来所有后果.我建议既不使用标准格式化文件I/O功能(Stdio/STL)也不使用std::string.为了获得更好的性能,您应该使用指向字符串的指针(而不是复制的字符串),这可以映射整个文件.另外,您必须实现文件解析(划分为行).
喜欢这段代码:
class MemoryMappedFileParser
{
const char* m_sz;
size_t m_Len;
public:
struct String {
const char* m_sz;
size_t m_Len;
};
bool getline(String& out)
{
out.m_sz = m_sz;
const char* sz = (char*) memchr(m_sz, '\n', m_Len);
if (sz)
{
size_t len = sz - m_sz;
m_sz = sz + 1;
m_Len -= (len + 1);
out.m_Len = len;
// for Windows-format text files remove the '\r' as well
if (len && '\r' == out.m_sz[len-1])
out.m_Len--;
} else
{
out.m_Len = m_Len;
if (!m_Len)
return false;
m_Len = 0;
}
return true;
}
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15223 次 |
| 最近记录: |