非常快的文本文件处理(C)

前端之家收集整理的这篇文章主要介绍了非常快的文本文件处理(C)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我写了一个在GPU上处理数据的应用程序.代码工作得很好,但我有一个问题,即输入文件(〜3GB,文本)的阅读部分是我的应用程序的瓶颈. (从HDD读取的速度很快,但逐行处理慢).

我使用getline()读取一行,并将第1行复制到一个向量,line2到一个向量,并跳过第3行和第4行.对于11条mio行的其余部分,我们依次类推.

我尝试了几种方法来尽可能地获取文件

发现最快的方法是使用boost :: iostreams :: stream

其他的是:

>将文件读为gzip,以尽量减少IO,但是比直接慢
阅读它.
>通过读取将文件复制到ram(filepointer,chararray,length)
并用循环进行处理以区分行(也比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,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++;
        }
    }
}

解决方法

首先,不要将文件读入内存,您可以使用文件映射.您只需要将程序构建为64位,以适应3GB的虚拟地址空间(对于32位应用程序,只有2GB可在用户模式下访问).或者你可以映射&按部件处理您的文件.

接下来,对我来说,你的瓶颈是“将一行复制到一个向量”.处理向量涉及到动态内存分配(堆操作),这在一个关键循环中非常重视性能.如果是这种情况 – 要么避免使用向量,要么确保它们被声明在循环之外.后者有助于因为当您重新分配/清除向量时,它们不会释放内存.

发布您的代码(或其一部分)以获得更多建议.

编辑:

似乎所有的瓶颈都与字符串管理有关.

> std :: getline(in,seqtemp);读入std :: string处理动态内存分配.
> _names.push_back(name);这更糟糕首先将std :: string按值放入向量中.意思是 – 字符串被复制,因此会发生另一个动态分配/释放.此外,当最终向量在内部被重新分配时 – 所有包含的字符串被再次复制,并带来所有后果.

我建议不要使用标准格式的文件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;
    }

};
原文链接:https://www.f2er.com/c/116293.html

猜你在找的C&C++相关文章