2010-04-23 55 views
2

我目前正在使用替换选择和k路合并来处理涉及外部合并排序的项目。我用C++ [在Linux上运行]实现了该项目。它非常简单,现在只处理固定大小的记录。提高C++程序的I/O性能[外部合并排序]

对于阅读&写我使用(I/O)fstream类。执行该程序几次后,我注意到

  • 对于大于4K(典型块大小)的请求,I/O读取块。事实上,缓冲区大小超过4K会导致性能下降。
  • 输出操作似乎不需要缓冲,linux似乎照顾缓冲输出。所以我发出一个写(记录),而不是保持特殊的写入缓冲区,然后使用write(records [])立即清除它们。

但是,应用程序的性能似乎不是很好。我怎么能改善表现?我应该维护特殊的I/O线程来处理读取块或者是否存在提供此抽象的现有C++类?(类似于Java中的BufferedInputStream)

+2

简介第一!对于大于最佳块大小的性能,性能只会缓慢下降,因此可能不会成为第一个问题。 – Potatoswatter 2010-04-23 01:49:05

+0

对于> 4096字节的缓冲区,它们是512的精确倍数吗? – wallyk 2010-04-23 01:51:13

+0

4k的东西是有道理的。这通常是许多文件系统的本地块大小,也是x86的本地页面大小。 – 2010-04-23 03:53:51

回答

3

如此高性能的I/O最容易在mmap下完成。这为内核提供了更多的自由来执行I/O并为您的应用程序计划CPU时间。例如,当您使用ifstream读入1 MB时,内核只能在读取所有数据时返回。但使用mmap()时,数据可以在可用时递增返回。

但是,你应该明白这是怎么发生的。仅仅因为数据似乎在RAM中并不意味着您应该将其视为随机访问。不要喂它到std::sort。这会触及mmap的区域的随机部分,导致页面错误向左和向右移动。因此,您将导致繁重的磁盘寻求解决随机页面错误。相反,mmap()两个输入并合并它们。由于mmap命令将内核告诉内核将来需要的数据,因此内核将尽可能快地为您提供数据,并且您的合并排序将在暂时无法使用数据时导致页面错误(即暂停)。

+0

谢谢。我会尝试mmap,很快就会收到结果! – Ajay 2010-04-24 08:23:09

1

与普通C I/O.事实上,它们“易于使用且适合不同情况”,但性能不足。在你的情况下,我会做的是切换到C风格的I/O,分析然后根据分析结果采取行动。