Chinaunix首页 | 论坛 | 博客
  • 博客访问: 186333
  • 博文数量: 51
  • 博客积分: 689
  • 博客等级: 上士
  • 技术积分: 525
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-03 13:05
文章分类

全部博文(51)

文章存档

2014年(1)

2013年(2)

2012年(7)

2011年(11)

2010年(30)

分类:

2010-03-04 14:38:55

巨大的页面第1部分(导言)

2010年2月16日

此文章由梅尔戈尔曼

[ 编者按:这篇文章是关于Linux的巨大的页面使用的在五个部分系列的第一篇。我们非常有幸能看到核心VM黑客梅尔戈尔曼撰写 的这些文章!其余的几篇 将出现在未来的LWN版。]

虚拟内存(VM)背后的发展的动力之一是减少编 程负担,把程序放到有限的内存执行。一个虚拟内存的基本属性是CPU引用一个虚拟地 址,通过软件和硬件的组合翻译为物理地址。这使得信息只需要到按需分页内存(按需分页)改 善内存的使用情况,允许模块在链接运行时放置在任意内存中,并提供了一个保护机制,并控制进程之间的数据共享。虚拟内存的使用是如此普遍,它已被视为电脑时代 “工程的胜利”一[denning96],但这种间接并不是没有代价的。

通常,一个程序需要在其生命周期内需要的转换总 数必须将页表保存在主内存中。由于翻译,一个虚拟内存就必须参考多个到物理内 存的访问,乘以根据页表格式的一个普通内存引用的成本因子。为了减少与翻译有关的费用,虚拟内存实现利用了 局部性的主要优点[denning71]存储最近翻译在高速缓存称为后备缓冲区(TLB)[casep78,smith82,henessny90]。可以通过此缓存翻译的内存量称为“TLB命中” 且这依赖于页的大小和TLB的项数。不可避免地,一定百分比的程序的执行时间会用于 访问TLB和TLB失误服务。

花在翻译上的地址上的时间量取决于负载情况,因 为访问模式确定了如果TLB可达足以存储应用程序所需的所有翻译。一旦失误,准确的成本信息取决于需要依赖翻译的 地址是否在CPU缓存。为了计算出该为TLB的失误服务所花费的时间, 也有一些简单的公式:

Cyclestlbhit = TLBHitRate * TLBHitPenalty

Cyclestlbmiss_cache = TLBMissRatecache * TLBMissPenalty cache

Cyclestlbmiss_full = TLBMissRate full * TLBMissPenalty full

TLBMissCycles =Cyclestlbmiss_cache + Cycles_ tlbmiss_full

TLBMissTime =(TLB失误时钟周期)/(时钟率)

如果失误时间在总体规划执行时间中占是一个很大 的的比例,那么应该检查以减少失误率和实现更好的性能。要达到这个目标的手段是采用比基本页面大的地址 翻译单位,正如许多现代处理器所支持的。

早在20世纪90年代就发现使用一个以上的页面 大小是减少TLB失误花费的时间,增加TLB命中的方式。巨大的网页的好处是双重的。最明显的性能增益是更少周期的翻译需求。一个不太明显的好处是,地址转换信息通常在二级缓存 中。巨大的 页面,更多的缓存空间用于应用数据意味着更少的周期花在了访问主内存。一般来说,使用大的页面,数据库负载将获得约 2-7%的性能提升,为科学的工作负载提升范围可以在1%和45%。

巨大的页面不是一个普遍益处,所以在主流操作系 统,如此巨大的页的透明的支持是有限。在某些TLB的实现,可能有不同数量的表项针对 小型和巨大的页面。如果 CPU支持的巨大网页TLB项数量较小,有可能大的页会慢一些,如果工作负载参考模式是非常离散的,且每大页引用很少。也可能会有限制在构架的巨大的页面都可以使用的 虚拟地址空间。

许多现代操作系统,包括Linux,更明确地支 持庞大页,尽管这并不必授权应用程序的变化。Linux自从2003年左右就有了的巨大的页 的支持,主要是用于大型共享数据库服务器内存中,如Oracle和DB2领域使用。早期的支持需要修改应用,一些人认为这是一个主 要问题。为了 克服困难,调整Linux系统使用庞大的页被认为是一项艰巨的任务。多年来在Linux中作出的巨大页支持显著改 善,如本文将显示的,今天使用大的页可能是一个相当轻松的演习,不涉及源码修改。

这第一篇文章从安装一些大页的相关工具和支持库 开始,使巨大的页的调整和使用相对无痛的工作。然后,它涵盖了Linux下的大的页如何表现的 基础知识和在NUMA关心的一些细节。第二篇涵盖了在Linux中存在的巨大的页的不同的接口。在第三篇,在作出微调系统的研究时不同的考虑, 以及如何监督大页的相关系统中的活动。第四条显示了不同类型的应用程序很容易的基准可以使用无源修改巨大的网页。对于很好奇的人,在总结前,讨论了一些深层次 TLB细节和测量在应用程序的成本。

1巨型页工具与支持库

有很多支持巨型页的工具 和,打包成的 集体支持库。发布 版可能有安装该包,但本文假定安装libhugetlbfs 2.7。最新版本可以使用下面的指令从GIT中克隆

$git clone git://libhugetlbfs.git.sourceforge.net/gitroot/libhugetlbfs/libhugetlbfs
$cd libhugetlbfs
$ git checkout - b next origin/next
$make PREFIX=/usr/local

有一个目标来安装库和所有支 持实用工具,但有-bin , -stat和-man的目标选项,在现有的库在安装过程中应保存 所提供的事件。

该库提供了支持自动支持文本,数据,堆和共享巨 大的网页和内存段。此外,该软 件包还提供了一个编程API和手册。库的行为是受环境变量(如libhugetlbfs.7手 册页的所述)hugectl知道如何配置,几乎所有的变量。hugeadm,hugeedit和 pageSize提供有关系统的信息,并提供支持系统管理。tlbmiss_cost.sh自动计算的平均TLB失误开销。cpupcstat和oprofile_start.sh提 供监测系统的当前行为的帮助。可通过手册进一步了解每个实用详细描述。

2巨大的页错 误行为

在下面的文章,将讨论会有怎样的不同类型的内存 区域可以创建,并拥有巨大的页支持。他们之间的一个重要的共同点是巨大的页如何缺 页,何时庞大的页分配。此外,根据具体使用的内核版本不同,私有和共享 映射之间的有着重要的区别。

在早期基于Linux的巨大页支持重,巨大的页 在mmap()被调用的同一时间缺页。这保证了一旦映射mmap()的成 功返回,所有应用成功的共享映射。私有映射是安全的,直到fork()被 调用。一旦 调用,其孩子尽快调用exec()是很重要的或庞大的页面映射都提前用madvise()标注有 MADV_DONTFORK。否则,复制写时(全体)故障可能会导致应用程序 故障,父母或孩子一方在分配失败时。

前缺页大幅增加了mmap的 成本(),并可以在NUMA执行优化。 2.6.18以来,巨大的页和普通页使用相同的缺页当页面第一次被引用时。为了保证缺页会成功,大的页是在共享的映射创建 时保留的但私人映射不作任何保留。这是很不幸的,因为这意味着应用程序可以失败, 当fork()不被调用。libhugetlbfs使用readv处理的旧核心的私人映射问题(),以 确保映射是安全的访问,但这种做法不理想。

自从2.6.29,两个共享的和私人的映射都保 留了。无论 什么进程访问的映射,共享映射都保证成功缺页。

对于私人映射,其子进程数目难于确定,创建映射mmap() 的进程才是保证成功的缺页的。当这一进程fork()时, 两个进程正在访问相同的页。如果孩子在COW,将试图分配一个新的一页。如果成功,成功完成了缺页。如果缺页失败,孩子在终止后信息记录到日志中指 出,内核没有足够大的页。如果是父进程执行COW,也将试图分配一个巨大 的页面。如果 分配失败,孩子的页面将取消映射并记录事件。父成功地完成了缺页,但如果孩子访问取消映射的 页,它将会被终止。

3 巨大页和交换

没有巨额页分页支持存储。

4巨大页和NUMA

在NUMA,内存可以是本 地或远程给CPU,远程访问将出现严重性能的处罚。默认情况下,缺页时,Linux使用节点的地方 政策进行内存分配。这项政策适用于基本页和巨大的页页面。当同时实现并行的工作负载时,这就导致了一个重 要的考虑因素。

处理一些数据的线程,应该是导致该数据的原始页 面错误相同的线程。一般在NUMA模式是当父线程设置并初始化所有 的工作量的内存区,然后创建线程来处理数据。在一个NUMA系统这会导致一些正在中央处理器 中工作线程将访问远程方面的内存。虽然这适用于所有的NUMA系统,不论页面大 小,工作线程之间的分裂的系统中效果可以预期,将招致巨大的页发生更多的远程存取,相比其他情况下发生。

这种情况可能会出现例如,当使用OpenMP的 庞大的页,因为OpenMP的不一定以页上的边界划分的数据。使用基本的页时,这可能会导致问题,但使用更加 庞大的页很可能问题更大,因为一个巨大的页面将超过基本页覆盖更多的数据,从而使之更有可能使得巨大的页面覆盖的数据由不同的线程处理。考虑下面的情况:第一个线程触摸页面时,会缺页完整的页面的数据 到线程运行的本地CPU上的内存。当数据没有按大页对齐的边界划分,这样的线程将 数据缺页,或许还包括由另一个线程处理一些数据是,因为两个线程的数据在同一巨大页面范围内的。第二个线程将缺页,其余的数据到本地内存,但仍 然有部分其数据远程访问的。作为大型的性能标准,这个问题表现偏差时,当做 了相同的输入数据相同的工作量,多次运行。在这种情况下性能分析可能显示庞大的页比基数页 面有更多的交叉访问节点。在极端情况下,巨大的页的效果,甚至可能会慢于 基础的页。由于 这个原因,重要的是要考虑的是,NUMA系统上使用大的页面时如何划分边界数据。

在这方面的一般问题的实例解决办法是组合使用 OpenMP 和MPI。使用的MPI允许按每一个MPI进程一个NUMA节点划分工作量。每个MPI的进程绑定到CPU列表当地一个节点。使用OpenMP实现节点内并行计算,从而减轻 了远程访问的问题。

5总结

在本文中,介绍了巨大的页 面背景,有什么性能优势,和在Linux上庞大的页面一些基本的行为。下一篇文章(出现在不久的将来)讨论了接口,用 于访问庞大的页面。

这片文章是基于由美国国防高级研究计划局的支持下根据其协定第HR0011 - 07 - 9 - 0002的工作。任何意见,结果和结论或在本材料中提出的建议是作者的观点并不一定代表美国国防部高级研究计划局的意见。

阅读(1051) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~