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

时间:2015-01-14 20:24:24

标签: c linux linux-kernel perf

修改:我使用基准测试的详细信息更新了我的问题

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

      Size  Minimum  Current  Maximum  Default
1073741824       10       10       10        *

我的内核启动参数被考虑在内。在我的基准测试中,我正在分配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文件系统),因此我认为AnonHugePages报告的/proc/meminfo字段代表了THP在停止之前分配的大页面。

此时我们可以认为一切都很好,但不幸的是我的工作台让我认为使用了许多2MiB页面,而不是一个1GiB页面。以下是解释:

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

导航内存。
pointer = *pointer;

使用perf_event_open系统调用,我只计算数据TLB读取未命中的第二步。当内存分配大小为64MiB时,我计算一个非常小的数字,即我的6400000内存访问的0.01%,数据TLB读取未命中。所有访问都保存在TLB中。换句话说,可以在TLB中保留64MiB的内存。一旦分配的内存大小大于64 MiB,我就会看到数据tlb读取未命中。对于内存大小等于128 MiB,我在TLB中错过了6400000次内存访问的50%。 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中可以缓存多少个这样的页面?

1 个答案:

答案 0 :(得分:20)

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进行多次测试并将其固定到核心3,这不是0(自举处理器)。

    • ./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未命中。

  7. 此时我下载了cpuid实用程序。它给了我这个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几何数据中,但有些是。我看到的唯一一个与你的cpuid打印输出完全相符(可能还有更多)的是Xeon Westmere-EP X5650; CPU-World没有明确说明数据TLB0有1GB页面的条目,但确实说处理器有“1 GB大页面支持”。

    然后我做了更多的研究,最后把它钉了下来。 RealWorldTech的一位作者在讨论Sandy Bridge的内存子系统时做了一个(不可否认,我必须找到一个这方面的资源)。它显示为as follows

      

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

    (强调补充)

    结论

    无论模糊概念“CPU支持1GB页面”表示,英特尔认为它并不意味着“TLB支持1GB页面条目”。我担心您无法在英特尔Westmere处理器上使用1GB页面来减少TLB未命中数。

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