2

我问这个问题是因为我一直在从事一个需要真正快速收集大量数据的项目,具体取决于场景。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++ 标准库方面遗漏了什么?

4

2 回答 2

3

“微软是不是根本不给 C++ 标准库开发人员……”

您可能会注意到您正在使用的产品称为Microsoft Visual Studio。Visual Studio 的标准库开发人员在 Microsoft 工作,尽管与 Windows 开发人员在不同的团队中。

原因更简单一点:Visual C++ 开发人员不可能知道并针对所有可能的使用场景进行优化。以如此高的速度进行文本格式化有点不寻常。请记住,重点ostream是提供operator<<. ofstream用于格式化输出到文件。但是对于高速 I/O,无论如何您都需要二进制输出。

于 2021-07-23T08:05:23.650 回答
2

坦率地说,您的目标带宽在当前商品硬件的物理限制范围内(16×PCIe.4 约为 24GByte/s),在我自己的工作中,我发现达到单- 在不使用“黑魔法”(又名手工组装和优化的系统调用代码)的情况下,核心内存传输速率超过 8GByte/s,它涉及仔细对齐内存访问和利用向量扩展。但最重要的是,要达到这些优化级别,需要了解正在处理的数据类型以及预期的访问模式类型和/或构建缓存中介以适应底层硬件。

这种优化很简单,完全超出了通用标准库的范围。标准库在其实现中必须遵守规范中记录的行为,其中一些要求往往与充分利用底层硬件所必须做的事情相冲突。

所以我很抱歉地告诉你,但你可能不得不硬着头皮直接使用低级系统 API,绕过标准库。

于 2021-07-23T08:28:45.643 回答