现代x86 CPU能够支持比传统4K更大的页面大小(即2MB或4MB),并且有操作系统(Linux,Windows)可以访问此功能.
上面的Microsoft链接声明大页面"提高了转换缓冲区的效率,这可以提高频繁访问的内存的性能".这对于预测大页面是否会改善任何特定情况并不是很有帮助.我对具体的,最好是量化的例子感兴趣,其中一些程序逻辑(或整个应用程序)移动使用大页面导致一些性能改进.有人有成功的故事吗?
我知道自己有一个特殊情况:使用大页面可以大大减少分支大型进程所需的时间(可能是因为需要复制的TLB记录数量减少了1000个数量级).我很感兴趣的是,在不那么奇特的场景中,大页面是否也可以带来好处.
当您对大范围的内存进行大范围的随机访问时,性能的最大差异将出现 - 其中"大"意味着比TLB中的所有小页面条目(通常是大的)可以映射的范围大得多在现代处理器中有多个级别).
为了使事情变得更复杂,4kB页面的TLB条目数通常大于2MB页面的条目数,但这种情况因处理器而异.Level 2 TLB中有多少"大页面"条目可用,也有很多变化.
例如,在AMD Opteron Family 10h Revision D("Istanbul")系统上,cpuid报告:
L1 DTLB:4kB页面:48个条目; 2MB页面:48个条目; 1GB页面:48个条目
L2 TLB:4kB页面:512个条目; 2MB页面:128个条目; 1GB页面:16个条目
在Intel Xeon 56xx("Westmere")系统上,cpuid报告:
L1 DTLB:4kB页面:64个条目; 2MB页面:32个条目
L2 TLB:4kB页面:512个条目; 2MB页面:无
在遭受2级TLB未命中之前,两者都可以使用小页面映射2MB(512*4kB),而Westmere系统可以使用其32个2MB TLB条目映射64MB,而AMD系统可以使用其L1和L2中的176个2MB TLB条目映射352MB TLB的.通过在大于2MB且小于64MB的内存范围内使用大页面进行随机访问,系统将获得显着的加速.对于更大的内存范围,AMD系统应该继续使用大页面显示出良好的性能.
在所有这些情况下,您要避免的是最糟糕的情况(注释1)遍历x86_64分层地址转换的所有四个级别的情况.
如果地址转换缓存机制(注释2)都不起作用,则需要:
5次访问内存以加载映射在4kB页面上的数据,
4次访问内存以加载映射在2MB页面上的数据,以及
3次访问内存以加载映射在1GB页面上的数据.
在每种情况下,最后一次到存储器的行程是获取所请求的数据,而其他行程则需要获得页面翻译信息的各个部分.我所看到的最好的描述是在AMD的"AMD64架构程序员手册第2卷:系统编程"(出版号24593)的第5.3节中http://support.amd.com/us/Embedded_TechDocs/24593.pdf
注1:上述数字并非真正的最坏情况.在虚拟机下运行会使这些数字变得更糟.在导致存储各种级别的页表的内存交换到磁盘的环境中运行会使性能更差.
注意2:遗憾的是,即使知道这种详细程度还不够,因为所有现代处理器都有额外的缓存用于页面翻译层次结构的上层.据我所知,这些在公共场合的记录非常糟糕.
我试图设计一些代码,这些代码可以最大化TLB与4k页面的颠簸,以便检查大页面可能获得的增益.当libhugetlbfs的malloc(Intel i7,64bit Debian Lenny)提供2MByte页面时,下面的内容运行速度比4K页面快了2.6倍 ; 希望明显发生了什么scoped_timer
和random0n
做.
volatile char force_result; const size_t mb=512; const size_t stride=4096; std::vectorsrc(mb<<20,0xff); std::vector idx; for (size_t i=0;i (stride),"MegaAccess"); char hash=0; for (size_t i=0;i 一个更简单的"直线"版本
hash=hash^src[i]
只从大页面上获得了16%,但是(疯狂猜测)英特尔花哨的预取硬件可能在访问可预测时帮助4K情况(我想我可以禁用预取来调查是否真的).
硬件预取不会跨越4K页边界,但你很可能看到在直线的情况是页表的访问是非常可预测的,所以当你在TLB未出现的页面走可能碰到这些都是网页L1(这些页面条目可能确实是通过预取引入的).