【问题标题】:Fastest way to write data stream to disk将数据流写入磁盘的最快方法
【发布时间】:2012-06-01 23:54:10
【问题描述】:

我有一个以大约 100 帧/秒的速度从相机传入的图像流,每张图像大约 2 MB。现在仅仅因为磁盘写入速度,我知道我无法写入每一帧,所以我只尝试每秒保存大约三分之一的帧。

流是大型字符数组的循环缓冲区。现在我正在使用 fwrite 将每个数组转储到一个临时文件,因为它被缓冲,但它似乎只以大约 20-30 MB/s 的速度写入,而硬盘驱动器理论上应该达到 80-100 MB/ s

有什么想法吗?有没有比 fwrite() 更快的编写方法或优化它的方法? 更一般地说,将大量数据转储到标准硬盘驱动器的最快方法是什么?

【问题讨论】:

  • 在 *nix 系统上使用特定于操作系统的调用(例如 write)来获得无缓冲的调用?
  • 只是一个提示,但预分配文件可能会有所帮助;将几 GB 的 NUL 字节写入文件(不要只是 fseek() 并在最后写入,那将是 sparse),因此文件系统不需要为块找到位置当您从相机接收数据时。
  • @dirkgently 除非您传递的数据块正好是扇区大小的倍数,否则使用没有缓冲的原语会不会降低效率?
  • @SJuan76:那太理想了。但是一般的FILE/ofstream 可能不会针对任何特定系统进行优化。至少,对于一个原语,OP 有一定的机会提取相当多的系统特定优势。
  • fwrite 调用的第二个和第三个参数的值是多少? fwriteing 一次 1 个字节会比fwriteing 一次 64K 慢很多。另外,您是否为 每个 帧调用 fopen?将所有帧写入单个文件可能会更快。

标签: c++


【解决方案1】:

fwrite 被缓冲,这是你想要的。尽管有了这么大的文件/写入,它不应该有太大或任何区别。或许可以通过 setbuf 调用尝试更大的流缓冲区。

由于您受到物理磁盘 i/o 速度的限制,只要您尽可能简单地让系统有效地使用每个可用的磁盘 io,您就无能为力了。

Linux 上的vmstat(其他系统上的其他类似工具)可以告诉您磁盘正在执行多少磁盘 i/os,因此您可以测试您的更改是否有帮助。

【讨论】:

    【解决方案2】:

    如果您将使用限制为(例如,每个 1GB)的内存映射文件怎么办?这应该提供足够的速度和缓冲区来处理所有帧,尤其是在您设法执行零拷贝帧分配的情况下。

    【讨论】:

    • 从我所读到的内存映射文件最适合多次读取和写入同一个文件。但是文件必须足够小以适合内存对吗?我需要写几十到几百千兆字节。
    • 好吧,如果您使用的是 POSIX 系统,请检查 mmap 限制。据我所知,同时映射到内存的最大字节数是有限制的。对于使用CreateFileMapping 的Windows 系统,您可以创建一个无限大小的文件,但是当您使用内存本身时,您应该使用MapViewOfFile 保留它,这仅限于应用程序的空间地址。注意:两个系统都喜欢与页面大小对齐的大小。
    【解决方案3】:

    在您的案例中,异步非缓冲输出是成功的关键。缓冲 IO 只会造成双缓冲开销,而同步 IO 会使硬盘磁头丢失顺序扇区。

    Boost.Asio 为流行平台提供了相对较好的系统特定 API 封装。

    有几件事要记住:

    • 在大多数非 Windows 平台上,您将不得不写入原始分区,以消除系统的缓冲和内部线程。
    • 始终保持写入队列非空,这样 SATA 控制器可以通过 NCQ 帮助您。
    • 请注意系统特定的要求,以确保异步非缓冲 IO 正常工作的缓冲区对齐和大小。
    • 文件打开模式对于让系统做你想做的事情也很重要。

    【讨论】:

    • 异步 I/O 是否适用于此?我以前研究过它,但它似乎总是让人不知所措,尤其是 Boost.Asio,它几乎没有文档。似乎只有在写入之间要进行处理时才会有所帮助,这样就可以在写入发生时进行。但既然我们所做的只是写缓冲区,这会有帮助吗?
    • @user1359341 - 好吧,如果您的缓冲区相对较大(数百 MB),那么即使阻塞 IO,您也可以达到 HD 的最高写入速度(假设您在任何给定的情况下只执行一次写入片刻)。但是你如何让你的系统自平衡呢?例如,您想让丢帧率成为输出流速度的函数。 HDD 的这个速度可能会根据您写入的磁道而有所不同,或者如果您设置 RAID 或升级到 SSD 等,它可能会发生显着变化。因此,中型 AIO 事件驱动架构是正确的选择。跨度>
    猜你喜欢
    • 2017-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    • 2011-04-03
    • 1970-01-01
    • 2018-04-20
    • 1970-01-01
    相关资源
    最近更新 更多