5

我想提出一个看似简单的问题,但我无处可寻。是否有一种用于文件输入和/或输出的FAST现代算法,可以使用所有符合标准的 C++ 编译器进行编译,并且适用于所有操作系统,而无需外部库?

  1. 我发现最快的方法是使用内存映射文件,但这不会因为我们希望同一段代码在所有平台上都工作
  2. 我们不能使用像 Win32 API 这样的 api,因为这会使其特定于平台
  3. 我不想使用 c,如果可行,我希望算法只是带有 stl 的纯 c++ 代码,而不是带有混合 asm hack/trick 的丑陋 c
  4. 不应使用不属于标准 c++ 的框架或外部库,如 wxWidgets、Qt、MFC 等。
  5. 整个问题的最大重点是该算法尽可能,类似于使用内存映射文件执行此操作的速度,甚至更快会很棒,但我知道这是不可能的

你有没有见过除了我以外的其他人研究过如此疯狂的东西吗?这样的算法甚至可能吗?

感谢您的任何建议

4

7 回答 7

9

具有以下限制:

可以使用所有符合标准的 C++ 编译器进行编译,并适用于所有操作系统,而无需外部库?

您几乎将自己限制在标准库文件 IO 函数中。也许是 POSIX 函数(取决于您正在考虑的“所有符合标准的 C++ 编译器”的子集)。

如果它们对您来说不够快,您将不得不开始放弃一些限制。

于 2010-01-26T00:33:46.963 回答
9

这与“算法”无关。

在将数据写入文件时,您将受到操作系统的支配 - 内存映射文件“很快”,因为您只是在写入内存,并且操作系统会在自己的时间将其同步回来。如果操作系统不支持它,那么你在这方面就不走运了——除非你想实现自己的内存映射层。

顺便说一句,POSIX 有mmap,所以如果您将自己限制在符合 POSIX 的系统中,那也没关系。

于 2010-01-26T00:34:48.910 回答
4

换个角度来看“操作系统的怜悯”,复制文件的大部分开销都在于操作系统。读取碎片文件比碎片整理文件需要更多时间。没有用于检测碎片文件的通用或标准 C++ 函数。

C++中最快的方法:

std::ifstream in_file;
std::ofstream out_file;

out_file << in_file.rdbuf();

您可以通过使用关键字“复制文件 rdbuf ”在 Web 上搜索来找到更多详细信息。上面的片段将复制留给操作系统,但可以跨所有平台移植。通过读入 C++ i/o 流,您可以设置读取缓冲区的大小,或者让它使用您自己的缓冲区。

更快的文件复制需要特定于平台的功能,例如 DMA 传输。使用线程和多缓冲,可以加快速度;但是 C++ 不支持线程(有一个事实上的标准 POSIX,它确实支持线程)。一个线程将读入缓冲区,而另一个线程从缓冲区写入。

于 2010-01-26T18:04:58.480 回答
2

几点:

  • 这与算法无关。
  • 想要针对所有操作系统并不是一个非常有成效的目标(而且这是不可能的
  • 在您测试之前,您的代码无法在特定平台上运行)。相反,我会专注于一些可行的操作系统——比如 POSIX + Win32。
  • 在这种情况下,您可以进行内存映射,例如通过为 Windows 实现 mmap()(在 MapViewOfFile() 等之上——如果您需要一些灵感,git 源代码有一个用于 Windows 的 mmap 实现)
  • 如果你不能使用内存映射,如果性能很重要,我建议使用普通的 C 文件 api 而不是 C++ 的文件流。尽管 C++ 的流对某些操作具有更高性能的潜力,但实际上它的速度要慢一些。
  • 但是,为了获得良好的性能,通常可以“足够好”,以确保您以理智的方式处理数据。按顺序读取数据,不要重新读取等。完美是好的敌人;)
于 2010-01-26T00:41:41.123 回答
1

快速 IO 通常归结为两件事:

  1. 最小化数据复制
  2. 最小化内核/用户上下文切换

大多数 IO 技术都试图解决其中一个问题。我所知道的最快的 IO 跨平台代码是 Perl IO 系统。我建议看一下source。Perl 黑客花了几十年的时间在尽可能多的平台上尽可能快地获取他们的 IO。

于 2010-01-26T05:46:23.717 回答
1

按文件系统块大小的倍数(或 2 的幂)顺序读取块可能会有所帮助。一旦块在内存中,然后将数据分开。在某处有一份白皮书,他们在其中测试了各种块大小的性能。我希望我能再次找到它。

您也可以尝试使用一个专用线程从文件中读取块,另一个在内存中进行数据操作(当然,使用适当的同步)。这允许您在阻塞文件读取调用时使用 CPU 处理数据。

无论如何,如果您尝试这些想法,请让我们知道您是否发现了差异。基准测试的实际结果会很有趣。

于 2010-01-26T03:36:35.997 回答
0

其他海报是正确的,因为性能总是与通用性(跨平台)不一致。

但是,一般来说,通过“缓冲”您的输入,您将获得最佳结果——使用 fread() 读取相对较大的数据块并处理这些数据。

我知道这是一个非常基本和一般的答案,但这是尽可能具体的,而不是更特定于平台,或者更多地了解你正在处理的特定输入。

于 2010-01-26T02:07:41.293 回答