如何在 Linux 上使用 Intel Westmere 1GB 页面?
How to use Intel Westmere 1GB pages on Linux?
编辑:我用我的基准更新了我的问题
出于基准测试目的,我尝试在两个 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
while the bench is sleeping (sleep
call above),我们可以看到已经分配了一个巨大的页面:
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 页面。解释如下:
该工作台通过指针追逐随机访问分配的内存:第一步填充内存以启用指针追逐(每个单元格指向另一个单元格),第二步工作台使用 [=24= 在内存中导航]
pointer = *pointer;
使用 perf_event_open
系统调用,我只计算工作台第二步的数据 TLB 读取未命中数。当分配的内存大小为 64MiB 时,我计算了一个非常小的数字,即我 6400000 次内存访问的 0.01%,数据 TLB 读取未命中。所有访问都保存在 TLB 中。也就是说,TLB中可以保留64MiB的内存。一旦分配的内存大小大于 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 中可以缓存多少这样的页面?
TL;DR
您(特别是您的处理器) 在这种情况下无法从 1GB 页面中获益,但您的代码是正确的,无需在可以的系统上进行修改。
长版
我按照这些步骤尝试重现您的问题。
My System: Intel Core i7-4700MQ, 32GB RAM 1600MHz, Chipset H87
svn co https://github.com/ManuelSelva/c4fun.git
cd c4fun.git/trunk
make
。发现需要一些依赖项。安装了它们。构建失败,但是 mem_load
构建了并且 link,所以没有进一步追求其余部分。
重新引导系统,在 GRUB 时将以下引导参数附加到引导参数:
hugepagesz=1G hugepages=10 default_hugepagesz=1G
保留 10 个 1GB 页面。
cd c4fun.git/trunk/mem_load
运行 在随机访问模式模式下使用 memload
进行多项测试并将其固定到核心 3,这不是 0(bootstrap处理器)。
./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
:
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 arena,TLB 的 4 个插槽完全足以满足所有访问。对于 5GB arenas 和随机访问模式模式,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:
After address generation, uops will access the DTLB to translate from a virtual to a physical address, in parallel with the start of the cache access. The DTLB was mostly kept the same, but the support for 1GB pages has improved. Previously, Westmere added support for 1GB pages, but fragmented 1GB pages into many 2MB pages since the TLB did not have any 1GB page entries. Sandy Bridge adds 4 dedicated entries for 1GB pages in the DTLB.
(强调)
结论
无论"CPU支持1GB页面"代表什么模糊的概念,英特尔认为它并不意味着"TLB支持1GB页面条目"。恐怕您将无法在 Intel Westmere 处理器上使用 1GB 页面来减少 TLB 未命中数。
那,或者英特尔通过区分 大页面(在 TLB 中)和 大页面.
来蒙蔽我们
编辑:我用我的基准更新了我的问题
出于基准测试目的,我尝试在两个 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
while the bench is sleeping (sleep
call above),我们可以看到已经分配了一个巨大的页面:
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 页面。解释如下:
该工作台通过指针追逐随机访问分配的内存:第一步填充内存以启用指针追逐(每个单元格指向另一个单元格),第二步工作台使用 [=24= 在内存中导航]
pointer = *pointer;
使用 perf_event_open
系统调用,我只计算工作台第二步的数据 TLB 读取未命中数。当分配的内存大小为 64MiB 时,我计算了一个非常小的数字,即我 6400000 次内存访问的 0.01%,数据 TLB 读取未命中。所有访问都保存在 TLB 中。也就是说,TLB中可以保留64MiB的内存。一旦分配的内存大小大于 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 中可以缓存多少这样的页面?
TL;DR
您(特别是您的处理器) 在这种情况下无法从 1GB 页面中获益,但您的代码是正确的,无需在可以的系统上进行修改。
长版
我按照这些步骤尝试重现您的问题。
My System: Intel Core i7-4700MQ, 32GB RAM 1600MHz, Chipset H87
svn co https://github.com/ManuelSelva/c4fun.git
cd c4fun.git/trunk
make
。发现需要一些依赖项。安装了它们。构建失败,但是mem_load
构建了并且 link,所以没有进一步追求其余部分。重新引导系统,在 GRUB 时将以下引导参数附加到引导参数:
hugepagesz=1G hugepages=10 default_hugepagesz=1G
保留 10 个 1GB 页面。
cd c4fun.git/trunk/mem_load
运行 在随机访问模式模式下使用
memload
进行多项测试并将其固定到核心 3,这不是 0(bootstrap处理器)。./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
:
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 arena,TLB 的 4 个插槽完全足以满足所有访问。对于 5GB arenas 和随机访问模式模式,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:
After address generation, uops will access the DTLB to translate from a virtual to a physical address, in parallel with the start of the cache access. The DTLB was mostly kept the same, but the support for 1GB pages has improved. Previously, Westmere added support for 1GB pages, but fragmented 1GB pages into many 2MB pages since the TLB did not have any 1GB page entries. Sandy Bridge adds 4 dedicated entries for 1GB pages in the DTLB.
(强调)
结论
无论"CPU支持1GB页面"代表什么模糊的概念,英特尔认为它并不意味着"TLB支持1GB页面条目"。恐怕您将无法在 Intel Westmere 处理器上使用 1GB 页面来减少 TLB 未命中数。
那,或者英特尔通过区分 大页面(在 TLB 中)和 大页面.
来蒙蔽我们