gpt4 book ai didi

c++ - 非常快速的文本文件处理(C++)

转载 作者:可可西里 更新时间:2023-11-01 15:50:21 24 4
gpt4 key购买 nike

我编写了一个在 GPU 上处理数据的应用程序。代码运行良好,但我的问题是输入文件的读取部分(~3GB,文本)是我的应用程序的瓶颈。 (从硬盘读取速度快,但逐行处理速度慢)。

我使用 getline() 读取一行并将第 1 行复制到一个 vector ,将第 2 行复制到一个 vector 并跳过第 3 行和第 4 行。其余 11 行 mio 行依此类推。

我尝试了几种方法来尽可能在最佳时间获取文件:

我发现最快的方法是使用 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 来读取文件。因此,如果您调用 readfastqblocksize(以行为单位)必须大于要读取的行数。

解决方案:

我找到了一个解决方案,它将读取文件的时间从 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++;
}
}
}

最佳答案

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

接下来,在我看来,您的瓶颈是“将线复制到 vector ”。处理 vector 涉及动态内存分配(堆操作),这在关键循环中会非常严重地影响性能)。如果是这种情况 - 要么避免使用 vector ,要么确保它们在循环之外声明。后者有帮助,因为当您重新分配/清除 vector 时,它们不会释放内存。

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

编辑:

看来你所有的瓶颈都与字符串管理有关。

  • std::getline(in, seqtemp); 读入 std::string 处理动态内存分配。
  • _names.push_back(name); 这更糟。首先,std::string 通过value 放入vector。意味着 - 字符串被复制,因此发生另一个动态分配/释放。此外,当 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;
}

};

关于c++ - 非常快速的文本文件处理(C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8123094/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com