【问题标题】:How to allocate "huge" pages for C++ application on Linux如何在 Linux 上为 C++ 应用程序分配“巨大”页面
【发布时间】:2015-12-15 15:37:36
【问题描述】:

我在 Linux 上有一个 C++ 应用程序,它对延迟非常敏感。我的内存使用量约为 2GB,因此对于 4kb 页面和 64 个 TLB 条目,我将遇到 TLB 未命中。

我在英特尔开发人员手册中阅读了 2MB(或 4MB?)“巨大”页面只会将 TLB 条目的数量减少一半,因此内存范围的增加抵消了 TLB 条目的减少,并且会更好地提高性能.

如何在 C++ 应用程序中使用“巨大”页面分配内存?有什么我应该注意的取舍吗?

我的 Linux 是 Red Hat 发行版。

【问题讨论】:

  • IIRC 你不能混合分配类型。您必须配置您的操作系统以使用其中一种。我没有完全通读它,但linuxgazette.net/155/krishnakumar.html 似乎做了你想做的事。
  • @RedX:不,您可以在“正常”系统上拥有一些 2M 的大页面。 grep Huge /proc/meminfo 显示正在使用的数量。在我的桌面(Ubuntu 15.04)上,大约 400MB 的常规 malloc 分配目前由 HugePages 支持,这要归功于内核注意到一堆连续的 4k 页面都在使用中。 developerblog.redhat.com/2014/03/10/… 请注意,大多数台式机 CPU 甚至不支持 1G HugePages,即使支持,固定这么多内存也是一个更小众的用例。
  • @OP:“减少 TLB 条目的数量”。你在这里捣乱。 TLB 对 4k 页面有有限数量的条目,对 HugePages 有一个单独的、较小的、有限数量的条目。因此,为您的某些数据设置 HugePages,为所有常规内容设置常规页面,实际上增加了可用的 TLB 条目总数,并极大地增加了所有 TLB 条目可以覆盖的地址空间量.

标签: c++ linux performance optimization memory-management


【解决方案1】:

我假设您只需要针对用 C++ 编写的特定应用程序的大页面,否则您只需更改系统的页面大小。以下方法适用于以任何语言编写的应用程序。

  1. 为了在特定应用程序中使用大页面,您需要构建内核以支持大页面支持。您必须使用 CONFIG_HUGETLBFS 选项构建内核

  2. 通过指定来指定页面大小

    hugepagesz=<size>
    

    在启动命令行上

  3. 查看如何设置启动参数:http://www.cyberciti.biz/tips/10-boot-time-parameters-you-should-know-about-the-linux-kernel.html

  4. 设置大页面使用的数量

    # echo 20 > /proc/sys/vm/nr_hugepages
    
  5. 检查大页面(可用、总计、...)

    # cat /proc/meminfo
    
  6. 当一切顺利后,现在您必须处理“如何将这些页面用于特定应用程序”:将hugetlbfs 类型的文件系统挂载为

    # mount -t hugetlbfs -o uid=<value>,gid=<value>,mode=<value>,pagesize=<value>,size=<value>,min_size=<value>,nr_inodes=<value> none /mnt/huge
    

    将您的应用程序放置在此挂载上/mnt/huge boom 现在您的应用程序将使用您设置的页面大小!

更多详情请查看https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt

大页面的优缺点:

优点:由于减少了 TLB 未命中、减少了页面错误、减少了页表大小以及减少了转换而提高了效率

缺点:更多内部碎片:内存丢失,交换延迟更长(HUGETLBFS 页面不会交换出它们的映射是永久性的) 更多详情请查看https://lwn.net/Articles/359158/

编辑 也有 API 可用于分配大页面请检查它也许有帮助

https://github.com/libhugetlbfs/libhugetlbfs/blob/master/HOWTO

https://lwn.net/Articles/375096/

【讨论】:

  • "将您的应用程序放在这个挂载 /mnt/huge boom 上,现在您的应用程序将使用您设置的页面大小!" - 不打算将可执行文件复制到挂载点,实际上很难或不可能做到这一点。相反,想要使用大页面的程序应该将文件映射到挂载点。
  • 是的,当我重新审视您的问题时,我意识到了这种复杂性。我更新了我的答案以添加 api 也许可以解决您的问题,但我不知道它的用法
【解决方案2】:

"hugetlb" documentation from the kernel 应该在这里提供帮助。

用户可以通过 mmap 系统调用或标准 SYSV 共享内存系统调用(shmget、shmat)来使用 Linux 内核中的大页面支持。

还有:

例子

1) map_hugetlb:见 tools/testing/selftests/vm/map_hugetlb.c

2) hugepage-shm:参见 tools/testing/selftests/vm/hugepage-shm.c

3) hugepage-mmap:参见 tools/testing/selftests/vm/hugepage-mmap.c

4) libhugetlbfs (https://github.com/libhugetlbfs/libhugetlbfs) 库 提供广泛的用户空间工具来帮助提高大页面的可用性, 环境设置和控制。

(这些路径指的是 linux 源代码树)。

所以基本上可以归结为:

  • 使用mmapMAP_HUGETLB 标志
  • 或者,从已安装的hugetlb 文件系统映射一个文件(如果存在)

【讨论】:

    【解决方案3】:

    您也可以尝试使用transparent huge page support,它可用于过去几年的任何内核(至少是 3.x 和 4.x 范围内的任何内核以及各种 2.6.x 内核)。

    主要好处是您不需要设置任何特殊的“hugetlbfs”,它“可以正常工作”。缺点是不能保证:内核可能满足您对大页面的分配如果满足某些条件并且某些条件可用。与hugetlbfs 在启动时保留固定数量的巨页不同,这些巨页只能通过特定的调用获得,透明巨页从通用内存池中切出巨页。这需要连续的 2MB 物理内存块,由于物理内存碎片导致系统保持正常运行时间,这可能会变得很少。

    此外,有多种内核可调参数会影响您是否获得大页面,其中最重要的是/sys/kernel/mm/transparent_hugepage/enabled

    你最好的选择是用posix_memalign在2MB边界上分配块,然后在分配的区域上执行madvise(MADV_HUGEPAGE)之前第一次接触它.它也适用于aligned_alloc 等变体。根据我的经验,在将/sys/kernel/mm/transparent_hugepage/enabled 设置为always 的系统上,这通常会导致大页面。但是,我主要在具有大量可用内存且正常运行时间不太长的系统上使用。

    如果您使用 2GB 内存,您可能会从大页面中获得显着的好处。如果您将所有这些都分配在小块中,例如通过malloc 很有可能透明的大页面不会启动,因此您还可以考虑以 THP 感知方式分配正在使用大量内存的任何内容(通常是单个对象类型)。

    我还写了a library 来确定您是否实际上从任何给定的分配中获得了大页面。这在生产应用程序中可能没有用,但如果您尝试使用 THP,它可能是一个有用的诊断,因为至少您可以确定您是否获得了它们。

    【讨论】:

    • 我想你的意思是说不能保证?
    • @user997112 - 是的,已修复。谢谢!
    猜你喜欢
    • 2012-02-12
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    • 2017-03-21
    • 1970-01-01
    • 1970-01-01
    • 2021-07-03
    相关资源
    最近更新 更多