如何在 C++ 中最大化 SSD I/O?

Jae*_*Lee 3 c++ io operating-system solid-state-drive

我制作了一个程序来读取和写入二维阵列到 NVME SSD(三星 970EVO plus)。

我设计了程序来读取 N*M 就像

#pragma omp parallel for
for(int i=0;i<N;i++)
  fstream.read(...) // read M bytes
Run Code Online (Sandbox Code Playgroud)

但是,此代码显示的性能(KB/s)低于 SSD 规格(< GB/s)

我认为如果大小 M 大于块大小(可能是 4KB)并且是 2 的倍数,那么该代码将显示 GB/s 性能。

然而,事实并非如此。我想我错过了一些东西。

是否有一些 C++ 代码可以最大限度地提高 SSD 上的 I/O 性能?

Sam*_*hik 5

不管你告诉fstream读多少,它很可能在一个固定大小的 streambuf 缓冲区中完成。C++ 标准没有指定其默认大小,但 4kb 是相当常见的。因此,传递 4mb 大小read()很可能最终有效地将其减少到 1024 次读取 4kb 数据的调用。这可能解释了您观察到的表现。您不是一次读取大量数据,而是您的应用程序进行多次调用以读取较小的数据块。

C++ 标准确实提供了通过该pubsetbuf方法调整内部流缓冲区大小的方法,并将其留给每个 C++ 实现以准确指定何时以及如何配置具有非默认大小的流缓冲区。您的 C++ 实现可能只允许您在打开 之前调整流缓冲区的大小std::ifstream,或者它可能根本不允许您调整 astd::ifstream的默认流缓冲区大小;相反,您必须首先构造自定义流缓冲区实例,然后使用rdbuf()将其附加到std::ifstream. 有关详细信息,请参阅 C++ 库的文档。

或者,您可能希望考虑使用操作系统的本机文件输入/输出系统调用,并完全绕过流缓冲区库,这也会增加一些开销。很可能文件的内容首先被读入流缓冲区,然后复制到您在这里传递的缓冲区中。调用你的本地文件输入系统调用将消除这个冗余副本,挤压更多的性能。