如何在Linux上使用英特尔Westmere 1GB页面?

编辑 :我更新了我的问题与我的基准的细节

为了进行基准testing,我试图在运行在两个Intel Xeon 56xx(“Westmere”)处理器之上的Linux 3.13系统中安装1GB页面。 为此,我修改了我的启动参数,添加了对1GB页面(10页)的支持。 这些引导参数只包含1GB的页面,而不包含2MB的页面。 运行hugeadm --pool-list会导致:

  Size Minimum Current Maximum Default 1073741824 10 10 10 * 

我的内核启动参数被考虑在内。 在我的基准testing中,我正在分配1GiB的内存,我想用1GiB的巨大页面来支持:

 #define PROTECTION (PROT_READ | PROT_WRITE) #define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB) uint64_t size = 1UL*1024*1024*1024; memory = mmap(0, size, PROTECTION, FLAGS, 0, 0); if (memory == MAP_FAILED) { perror("mmap"); exit(1); } sleep(200) 

看看/proc/meminfo而板凳睡觉(上面的sleep呼叫),我们可以看到,一个巨大的页面已经分配:

 AnonHugePages: 4096 kB HugePages_Total: 10 HugePages_Free: 9 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 1048576 kB 

注意:在运行工作台之前,我禁用了THP(通过/sys文件系统),所以我猜测/proc/meminfo报告的AnonHugePages字段代表了THP在停止之前分配的巨大页面。

在这一点上,我们可以认为一切都很好,但不幸的是,我的板凳让我觉得有很多2MiB的页面,而不是一个1GiB的页面。 这里是解释:

这个工作台通过指针的追逐随机地访问分配的内存:第一步填充内存以启用指针追逐(每个单元格指向另一个单元格),然后在第二步中通过内存使用内存

 pointer = *pointer; 

使用perf_event_open系统调用,我只计算了数据库TLB读取错过的第二步。 当内存分配的大小是64MiB时,我计算一个非常小的数字,我的6400000内存访问的0,01%,数据TLB读取错过。 所有的访问都保存在TLB中。 换句话说,内存的64MiB可以保存在TLB中。 一旦分配的内存大小大于64 MiB,我看到数据tlb读取错过。 对于内存大小等于128 MiB,我有我的6400000内存访问的50%,在TLB中错过了。 64MiB似乎是可以装入TLB和64MiB = 32个条目(如下面报告的)* 2MiB页面的大小。 我的结论是,我不使用1GiB页面,但2MiB的。

你能看到这种行为的任何解释吗?

此外, cpuid工具,在我的系统上报告以下关于tlb:

  cache and TLB information (2): 0x5a: data TLB: 2M/4M pages, 4-way, 32 entries 0x03: data TLB: 4K pages, 4-way, 64 entries 0x55: instruction TLB: 2M/4M pages, fully, 7 entries 0xb0: instruction TLB: 4K, 4-way, 128 entries 0xca: L2 TLB: 4K, 4-way, 512 entries L1 TLB/cache information: 2M/4M pages & L1 TLB (0x80000005/eax): L1 TLB/cache information: 4K pages & L1 TLB (0x80000005/ebx): L2 TLB/cache information: 2M/4M pages & L2 TLB (0x80000006/eax): L2 TLB/cache information: 4K pages & L2 TLB (0x80000006/ebx): 

正如你所看到的,没有关于1GiB页面的信息。 TLB中可以caching多less个这样的页面?

TL; DR

在这种情况下, 您(特别是您的处理器)无法从1GB页面中受益,但是您的代码在没有可以修改的系统上是正确的。

长版

我遵循这些步骤来尝试重现您的问题。

 My System: Intel Core i7-4700MQ, 32GB RAM 1600MHz, Chipset H87 
  1. svn co https://github.com/ManuelSelva/c4fun.git
  2. cd c4fun.git/trunk
  3. make 。 发现了一些依赖需要。 安装它们。 构建失败,但mem_load确实建立和链接,所以没有进一步追求休息。
  4. 重新引导系统,在GRUB时间追加引导参数如下:

     hugepagesz=1G hugepages=10 default_hugepagesz=1G 

    它保留了10个1GB的页面。

  5. cd c4fun.git/trunk/mem_load
  6. 在随机访问模式模式下使用memload几次测试,并将其固定到不是0的引导处理器(core 3)。

    • ./mem_load -a rand -c 3 -m 1073741824 -i 1048576

      这导致大约零TLB未命中。

    • ./mem_load -a rand -c 3 -m 10737418240 -i 1048576

      这导致了大约60%的TLB未命中。 在我的预感上,我做到了

    • ./mem_load -a rand -c 3 -m 4294967296 -i 1048576

      这导致了大约零TLB未命中。 在我的预感上,我做到了

    • ./mem_load -a rand -c 3 -m 5368709120 -i 1048576

      这导致了大约20%的TLB失误。

在这一点上,我下载了cpuid实用程序。 它给了我这个cpuid -1 | grep -i tlb cpuid -1 | grep -i tlb

  cache and TLB information (2): 0x63: data TLB: 1G pages, 4-way, 4 entries 0x03: data TLB: 4K pages, 4-way, 64 entries 0x76: instruction TLB: 2M/4M pages, fully, 8 entries 0xb5: instruction TLB: 4K, 8-way, 64 entries 0xc1: L2 TLB: 4K/2M pages, 8-way, 1024 entries L1 TLB/cache information: 2M/4M pages & L1 TLB (0x80000005/eax): L1 TLB/cache information: 4K pages & L1 TLB (0x80000005/ebx): L2 TLB/cache information: 2M/4M pages & L2 TLB (0x80000006/eax): L2 TLB/cache information: 4K pages & L2 TLB (0x80000006/ebx): 

正如你所看到的,我的TLB有4个1GB页面的条目。 这很好地解释了我的结果:对于1GB和4GB的场合,TLB的4个插槽完全足以满足所有访问。 对于5GB竞技场和随机访问模式,只有5个页面中的4个可以通过TLB映射,所以追逐一个指针到剩下的一个会导致错过。 将指针追加到未映射页面的概率是1/5,所以我们期望1/5 = 20%的遗漏率,我们可以得到这个结果。 对于10GB,4/10页被映射,6/10不是这样,错过率将是6/10 = 60%,我们得到了。

所以你的代码至少可以在我的系统上无需修改。 你的代码似乎没有问题,那么。

然后我对CPU-World进行了一些研究,虽然并不是所有的CPU都与TLB几何数据一起列出,但有些是。 Xeon Westmere-EP X5650是我看到的唯一一个与cpuid打印输出完全匹配的(可能更多) CPU-World没有明确地说数据TLB0有1GB页面的条目,但是确实说处理器有“1GB大页面支持”。

然后我做了更多的研究,并最终确定了它。 RealWorldTech的一位作者在讨论Sandy Bridge的内存子系统时做出了一个(不可否认的是,我还没有找到这方面的资料)。 内容如下 :

地址生成之后,uops将访问DTLB,以便从一个虚拟地址转换为一个物理地址,与缓存访问的开始并行。 DTLB大部分保持不变,但1GB页面的支持有所改善。 在此之前,Westmere增加了对1GB页面的支持,但是由于TLB没有任何1GB页面条目,因此将1GB页面分割成许多2MB页面。 Sandy Bridge为DTLB中的1GB页面添加了4个专用条目。

(强调添加)

结论

无论“CPU支持1GB页面”这个含糊不清的概念,英特尔认为这并不意味着“TLB支持1GB页面条目” 。 恐怕您将无法使用英特尔Westmere处理器上的1GB页面来减少TLB未命中的数量。

或者,英特尔通过将大页面 (在TLB中)与大页面区分开来,正在蒙骗我们。