微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Microsoft 中的 C++ 标准库文件流操作是否瘫痪?

如何解决Microsoft 中的 C++ 标准库文件流操作是否瘫痪?

我问这个问题是因为我一直在从事一个需要根据场景快速收集大量数据的项目。 5.7GBytes,大写 BYTE/s 或 11.4GBytes/s。

我们正在使用 3 个 Samsung Pro NVME(对于 11.4GB/s,我们有一个更大的阵列)来处理一个小型条带化raid 阵列。

目前该项目是在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 位值,不像 Windows SDK WriteFile 只接受 DWORD 的设置,最大写入大小是 512 的最大倍数,可以挤进一个 uint32_t 并且你必须管理你的如果您的文件超过 4GB(我的),则循环写入。

这只是提出了一个问题,微软是否根本不让 C++ 标准库开发人员访问必要的操作系统级系统调用以利用超高速驱动器阵列?或者我在如何充分发挥 C++ 标准库的潜力方面遗漏了一些东西?

解决方法

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

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

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

,

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

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。