好的,所以我在编写图像到JPEG之前编写了一个(相当未优化的)程序,但是,现在我正在使用MPEG-2传输流和H.264编码视频。在我深入编程所有这些之前,我很好奇处理实际文件的最快方法是什么。
目前我正在将.mts文件文件映射到内存中以进行处理,虽然我不确定(例如)以块的形式将100 MB的文件读入内存并处理它会更快方式。
这些文件需要大量的位移和读取标志,所以我想知道当我引用一些内存时,如果一个整数读取4个字节或者作为一个字符读取1个字节更快。我以为我读过x86处理器优化到4字节粒度的地方,但我不确定这是不是真的......
谢谢!
答案 0 :(得分:6)
如果您需要同步提供文件,则内存映射文件通常是最快的可用操作。 (有些异步API允许O / S有时重新排序以略微提速,但听起来它对你的应用程序没有帮助)
您使用映射文件获得的主要优点是,当O / S仍在从磁盘读取文件时,您可以在文件的内存中工作,而您无需管理自己的锁定/线程文件读取代码。
内存参考方面,无论您实际使用什么,x86内存都将一次读取整行。与非字节粒度操作相关联的额外时间指的是整数不需要字节对齐的事实。例如,如果事物没有在4字节边界上对齐,则执行ADD将花费更多时间,但对于像存储器复制这样的东西,将没有什么区别。如果你正在处理固有的字符数据,那么保持这种方式比以整数读取所有内容并且改变位置更快。
如果你正在进行h.264或MPEG2编码,那么瓶颈可能是CPU时间而不是磁盘i / o。
答案 1 :(得分:2)
如果您必须访问整个文件,则将其读取到内存并在那里进行处理总是更快。当然,它也浪费内存,你必须以某种方式锁定文件,这样你就不会得到其他应用程序的并发访问,但无论如何优化都是妥协。如果您正在跳过(大)部分文件,则内存映射会更快,因为您根本不必阅读它们。
是的,以4字节(甚至8字节)粒度访问内存比以字节方式访问内存要快。再一次,这是一个妥协 - 取决于你之后对数据的处理方式,以及你在整理int中的位数方面的技巧,它总体上可能不会更快。
关于优化的一切:
答案 2 :(得分:1)
这些是连续的比特流 - 你基本上一次消耗它们一次而不进行随机访问。
在这种情况下,您不需要花费大量精力来显式缓冲读取操作:操作系统无论如何都会为您缓冲它们。我以前写过H.264解析器,时间完全由解码和操作支配,而不是IO。
我的建议是使用标准库并解析这些比特流。
Flavor 就是这样一个解析器,网站甚至包含了MPEG-2(PS)和M-Coder等各种H.264部分的示例。 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;
}
答案 3 :(得分:0)
关于从内存中读取的最佳大小,我相信您会喜欢阅读有关内存访问性能和缓存效果的this post。
答案 4 :(得分:0)
关于内存映射文件需要考虑的一件事是,大小大于可用地址范围的文件只能映射文件的一部分。要访问文件的其余部分,需要取消映射第一部分,并在其位置映射下一部分。
由于您正在解码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