c++ - 一次读取多行文件的有效方法?

标签 c++ c multithreading file-read

我现在正在尝试处理一个大文件(几 GB),所以我正在考虑使用多线程。该文件是多行数据,例如:

data1 attr1.1 attr1.2 attr1.3
data2 attr2.1 attr2.2 attr2.3
data3 attr3.1 attr3.2 attr3.3

我正在考虑使用一个线程首先将多行读取到缓冲区 1,然后另一个线程逐行处理缓冲区 1 中的数据,同时读取线程开始将文件读取到缓冲区 2。然后处理线程在buffer2准备好后继续,读取线程再次读取到buffer1。

现在我通过对小文件(几个 KB)使用 freads 完成了处理程序部分,但我不确定如何使缓冲区包含完整的行而不是在末尾拆分行的一部分缓冲区,就像这样:

data1 attr1.1 attr1.2 attr1.3
data2 attr2.1 att

另外,我发现 fgetsifstream getline 可以逐行读取文件,但是它有很多 IO 会不会非常昂贵?

现在我正在努力找出最好的方法是什么?有什么有效的方法可以一次读取多行?任何建议表示赞赏。

最佳答案

C stdio 和 C++ iostream 函数使用缓冲 I/O。小型读取只有函数调用和锁定开销,没有 read(2) 系统调用开销。

在事先不知道行长度的情况下,fgets 必须使用缓冲区或一次读取一个字节。幸运的是,C/C++ I/O 语义允许它使用缓冲,所以每个主流实现都这样做。 (根据文档,在底层文件描述符上混合 stdio 和 I/O 会产生未定义的结果。这就是允许缓冲的原因。)

你是对的,如果每个 fgets 都需要一个系统调用,那会是个问题。


您可能会发现一个线程读取行并将这些行放入某种对处理线程有用的数据结构中很有用。

如果您不必在每一行上做太多处理,那么在与处理相同的线程中执行 I/O 会将所有内容保存在该 CPU 的 L1 缓存中。否则数据将在 I/O 线程的 L1 结束,然后必须到达运行处理线程的内核的 L1。


根据您要对数据执行的操作,您可以通过就地内存映射文件来最大程度地减少复制。或者使用 fread 阅读,或者完全跳过 stdio 层并仅使用 POSIX open/read,如果你不需要你的代码作为可移植。扫描缓冲区中的换行符可能比 stdio 函数的开销更少。

您可以处理缓冲区末尾的剩余行,方法是将其复制到缓冲区的前面,并使用减小的缓冲区大小调用下一个 fread。 (或者,使您的缓冲区比您的 fread 调用的大小大 ~1k,因此您始终可以读取内存和文件系统页面大小(通常为 4kiB)的倍数,除非该行的尾部是> 1k.)

或者使用循环缓冲区,但是从循环缓冲区读取意味着每次触摸它时都要检查环绕。

关于c++ - 一次读取多行文件的有效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33441366/

相关文章:

java - 动态更改提交给Executor服务的命令列表

Java 测量线程的利用率

c++ - 创建频率数组

c++ - 等同于DirectX 9的DirectX 11错误

c++ - 使用 new(this) 重用构造函数

c++ - 类中的 std::vectors

c - 如何在 C 中监听方向键按下

c - 生成反向位查找表(8位)背后的算法

c - 在包含新行的字符串中搜索?

java - Java 线程的恼人行为