【问题标题】:Which is faster in memory, ints or chars? And file-mapping or chunk reading?内存,整数或字符哪个更快?和文件映射或块读取?
【发布时间】:2010-04-07 05:09:55
【问题描述】:

好的,所以我之前编写了一个(相当未优化的)程序来将图像编码为 JPEG,但是,现在我正在使用 MPEG-2 传输流和其中的 H.264 编码视频。在我开始对所有这些进行编程之前,我很好奇处理实际文件的最快方法是什么。

目前我正在将 .mts 文件文件映射到内存中以进行处理,尽管我不确定(例如)将 100 MB 文件分块读取到内存中并处理它是否会更快方式。

这些文件需要大量的位移等来读取标志,所以我想知道当我引用一些内存时,一次读取 4 个字节作为整数或 1 个字节作为字符是否更快。我以为我在某处读到 x86 处理器已优化为 4 字节粒度,但我不确定这是否属实……

谢谢!

【问题讨论】:

    标签: c++ optimization memory file integer


    【解决方案1】:

    如果您需要文件同步可用,内存映射文件通常是最快的可用操作。 (有一些异步 API 有时允许 O/S 重新排序事物以稍微提高速度,但这听起来对您的应用程序没有帮助)

    您使用映射文件获得的主要优势是,您可以在文件仍被操作系统从磁盘读取时在内存中工作,并且您不必管理自己的锁定/线程文件读取代码。

    内存引用明智,在 x86 上,无论您实际使用什么,一次都会读取整行内存。与非字节粒度操作相关的额外时间是指整数不需要字节对齐的事实。例如,如果事情没有在 4 字节边界上对齐,则执行 ADD 将花费更多时间,但对于像内存副本这样的事情,差别不大。如果您使用的是固有的字符数据,那么保持这种方式会比将所有内容读取为整数和位移位更快。

    如果您正在执行 h.264 或 MPEG2 编码,无论如何,瓶颈可能是 CPU 时间而不是磁盘 i/o。

    【讨论】:

      【解决方案2】:

      如果您必须访问整个文件,将其读入内存并在那里进行处理总是更快。当然,这也是浪费内存,你必须以某种方式锁定文件,这样你就不会被其他应用程序并发访问,但无论如何优化都是关于妥协的。如果您跳过文件的(大)部分,内存映射会更快,因为您根本不必阅读它们。

      是的,以 4 字节(甚至 8 字节)粒度访问内存比按字节访问内存要快。这又是一个折衷方案 - 取决于您之后对数据所做的事情,以及您在处理 int 中的位方面的熟练程度,总体上可能不会更快。

      关于优化的一切:

      1. 测量
      2. 优化
      3. 测量

      【讨论】:

      • +1,不是'测量,测量,优化,再测量'吗?
      【解决方案3】:

      这些是顺序比特流 - 您基本上一次使用它们,而无需随机访问。

      在这种情况下,您无需花费大量精力来显式缓冲读取等:无论如何,操作系统都会为您缓冲它们。我之前写过H.264解析器,时间完全由解码和操作来控制,而不是IO。

      我的建议是使用标准库来解析这些比特流。

      Flavor 就是这样一个解析器,该网站甚至包括 MPEG-2 (PS) 和各种 H.264 部分(如 M-Coder)的示例。 Flavor 从类 c++ 语言构建原生解析代码;这是 MPEG-2 PS 规范的引述:

      class TargetBackgroundGridDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 7 
      {
          unsigned int(14) horizontal_size;
          unsigned int(14) vertical_size;
          unsigned int(4) aspect_ratio_information;
      }
      
      class VideoWindowDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 8 
      {
          unsigned int(14) horizontal_offset;
          unsigned int(14) vertical_offset;
          unsigned int(4) window_priority;
      }
      

      【讨论】:

        【解决方案4】:

        关于从内存中读取的最佳大小,我相信您会喜欢阅读 this post 关于内存访问性能和缓存效果的内容。

        【讨论】:

          【解决方案5】:

          关于内存映射文件需要考虑的一点是,大小大于可用地址范围的文件将只能映射文件的一部分。要访问文件的其余部分,需要取消映射第一部分并在其位置映射下一部分。

          由于您正在解码 mpeg 流,您可能希望使用双缓冲方法和异步文件读取。它的工作原理是这样的:

          blocksize = 65536 bytes (or whatever)
          currentblock = new byte [blocksize]
          nextblock = new byte [blocksize]
          read currentblock
          while processing
             asynchronously read nextblock
             parse currentblock
             wait for asynchronous read to complete
             swap nextblock and currentblock
          endwhile
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-05-27
            • 2011-09-14
            • 1970-01-01
            • 1970-01-01
            • 2020-11-06
            • 1970-01-01
            • 2017-11-21
            • 1970-01-01
            相关资源
            最近更新 更多