我的程序并行读取几十个非常大的文件,一次只读一行.似乎主要的性能瓶颈是HDD在文件之间寻找时间(虽然我不完全确定如何验证这一点),所以我认为如果我可以缓冲输入会更快.
我正在使用这样的C++代码通过boost :: iostreams"过滤流"来读取我的文件:
input = new filtering_istream;
input->push(gzip_decompressor());
file_source in (fname);
input->push(in);
Run Code Online (Sandbox Code Playgroud)
根据文档,file_source没有任何方法来设置缓冲区大小,但filtering_stream :: push似乎:
void push( const T& t,
std::streamsize buffer_size,
std::streamsize pback_size );
Run Code Online (Sandbox Code Playgroud)
所以我尝试了input->push(in, 1E9),确实我的程序的内存使用量大了,但速度根本没有变化.
我认为读取缓冲会改善性能是错误的吗?或者我做错了吗?我可以直接缓冲file_source,还是需要创建filtering_streambuf?如果是后者,那怎么办?文档并不完全是示例.
您也应该对其进行分析,看看瓶颈在哪里。
也许它在内核中,也许是你的硬件限制。直到你分析它才发现你在黑暗中跌跌撞撞。
编辑:
好吧,这次的答案更加彻底。根据 Boost.Iostreams 文档,basic_file_source它只是一个包装器std::filebuf,而它又是建立在std::streambuf. 引用文档:
以只读模式打开的 std::basic_filebuf 的可复制构造和可分配包装器。
streambuf确实提供了一种方法pubsetbuf(也许不是最好的参考,但第一个谷歌出现),显然,您可以使用它来控制缓冲区大小。
例如:
#include <fstream>
int main()
{
char buf[4096];
std::ifstream f;
f.rdbuf()->pubsetbuf(buf, 4096);
f.open("/tmp/large_file", std::ios::binary);
while( !f.eof() )
{
char rbuf[1024];
f.read(rbuf, 1024);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在我的测试中(虽然优化关闭),实际上,4096 字节缓冲区的性能比 16 字节缓冲区的性能更差,但是 YMMV —— 这是为什么您应该始终首先分析的一个很好的例子:)
但是,正如您所说,它basic_file_sink不提供任何访问它的方法,因为它将底层隐藏filebuf在其私有部分中。
如果您认为这是错误的,您可以:
filebuf包装器,它会公开缓冲区大小。本教程中有一个部分解释了编写自定义源代码,这可能是一个很好的起点。请记住,您的硬盘驱动器和内核已经对文件读取进行了缓存和缓冲,我认为您不会从缓存中获得更多的性能提升。
最后,谈谈分析。Linux 有大量强大的分析工具,我什至不知道其中一半的名称,但例如iotop,它很简洁,因为它使用起来超级简单。它与 top 非常相似,但显示了与磁盘相关的指标。例如:
Total DISK READ: 31.23 M/s | Total DISK WRITE: 109.36 K/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
19502 be/4 staffan 31.23 M/s 0.00 B/s 0.00 % 91.93 % ./apa
Run Code Online (Sandbox Code Playgroud)
告诉我我的程序花费了超过 90% 的时间等待 IO,即它是 IO 绑定的。如果您需要更强大的东西,我相信谷歌可以帮助您。
请记住,对热缓存或冷缓存进行基准测试会极大地影响结果。
| 归档时间: |
|
| 查看次数: |
2779 次 |
| 最近记录: |