我问这个问题是因为我一直在从事一个需要真正快速收集大量数据的项目,具体取决于场景。5.7GBytes,大写 BYTE/s 或 11.4GBytes/s。
我们正在使用 3 个三星 Pro NVME 处理一个小型条带化 RAID 阵列(对于 11.4GB/s,我们有一个更大的阵列)。
目前,该项目是在 Windows 上开发的,我想让东西尽可能便携,所以我专注于使用 C++ 标准库;但是,无论我做什么,我都无法破解传输速度超过 1.5GB/s 的文件
该策略很简单,即创建几个巨大的交换缓冲区,并将它们作为一个巨大的未格式化二进制文件直接写入磁盘。
通过以下方式手动使用std::ofstream
和基准测试设置不同的缓冲区大小:
rdbuf()->pubsetbuf(buffer, BUFFER_SIZE);
open(Filename, std::ios::binary|std::ios::trunc);
接下来是我的托管写入循环,我能够找到一个最佳位置,但永远无法破解 1.5GB/s
然后我找到了 Windows SDK 及其CreateFile函数
特别是使用FILE_FLAG_NO_BUFFERING标志的创建文件功能。
这改变了游戏规则,只要我确保向它提供扇区对齐的数据(在我的情况下,一切都需要是 512 字节的倍数),我突然能够充分利用 raid 阵列的吞吐量。
我重新审视了该std::ofstream
功能,以尝试使用更多与操作系统无关的功能;但是,即使可以为 指定零缓冲区std::ofstream
,似乎也没有任何文档说明在没有缓冲区的情况下使用该函数的任何警告。
std::ofstream
允许其写入大小为 64 位值,这与仅接受 DWORD 设置的 Windows SDK WriteFile 不同,最大写入大小是 512 的最大倍数,可以挤入 a uint32_t
,如果文件超过 4GB,则必须循环管理写入(我的) .
这只是提出了一个问题,微软是否根本没有让 C++ 标准库开发人员访问必要的操作系统级系统调用以利用超高速驱动器阵列?还是我在如何充分利用 C++ 标准库方面遗漏了什么?