昇腾社区首页
中文
注册

glibc动态库大页

在应用程序执行过程中,许多动态库默认使用4KB小页,进程iTLB miss高,导致CPU执行效率低下。开源的代码段大页方案需要浪费额外的内存,同时影响进程启动速度,而OpenEuler提供的glibc加载动态库方案默认映射大页则可以减少内存开销,同时加快进程启动速度,最终能达到降低iTLB cache miss以提升性能的结果。该方法需要预先分配标准大页内存池,请先参考使能OS开启标准大页内存,确保有足够的标准大页内存空间。

安装方法

  1. 该特性需安装对应版本的glibc和glibc-devel包,详细对应版本要求见如下表格说明。
  2. glibc为Linux核心软件包,不推荐直接安装,容易造成软件兼容性问题,建议安装OpenEuler后使用,也可以通过OpenEuler的docker镜像使用(

    openeuler源地址:https://repo.openeuler.org/,选择下面表格中符合要求的OpenEuler版本,例如:openEuler-22.03-LTS-SP4/docker_img/aarch64/openEuler-docker.aarch64.tar.xz)。

  3. EulerOS使用该特性需要额外配置启动项参数exec_hugepages,具体修改启动项配置可参考“使能OS开启标准大页内存”中的“永久启用标准大页内存池”章节。
    表1 软件版本要求

    操作系统名称

    软件版本要求

    OpenEuler

    操作系统版本:openEuler-22.03-LTS-SP1、openEuler-22.03-LTS-SP3、openEuler-22.03-LTS-SP4

    上述OS版本对应软件版本要求均为,glibc版本和glibc-devel版本大于等于2.34-h157 。

    EulerOS

    操作系统版本:eulerosv2r10、eulerosv2r11、eulerosv2r12、eulerosv2r13

    eulerosv2r10对应glibc和glibc-devel的版本号为大于等于2.28-63.h52。

    eulerosv2r11对应glibc和glibc-devel的版本号为大于等于2.34-70.h8。

    eulerosv2r12对应glibc和glibc-devel的版本号为大于等于2.34-105.h1。

    eulerosv2r13对应glibc和glibc-devel的版本号为大于等于2.34-143.h3。

    建议采用rpm -qa glibc或者rpm -qa glibc-devel命令查询当前glibc版本,使用ldd --version只能看到glibc上游社区的版本,无法看到OpenEuler发行的h版本号。

使用方法

确认glibc和glibc-devel是否安装,版本是否符合要求。
rpm -qa glibc
rpm -qa glibc-devel 

若glibc-devel未安装,可以使用下面命令安装:
yum install glibc-devel 
若glibc版本低于要求,可通过如下命令更新glibc版本:
yum upgrade glibc glibc-devel
  • 方法一(推荐使用):

    使用LD_HUGEPAGE_LIB环境变量,会让可执行程序依赖的所有动态库都尝试映射大页。变量值为动态库的大页模式(当前仅支持0或1,其他值未定义):

    • 配置为1,使用动态库大页模式。
    • 配置为0,动态库不使用大页。

    该环境变量不会被复制到子进程,建议在运行程序入口配置,在外部shell脚本(非程序入口)设置不会生效,例如脚本训练入口:

    export LD_HUGEPAGE_LIB=1
    torchrun --nnodes=1 --nproc_per_node=8 --master-port 61888 scripts/train.py \
    configs/opensora-v1-1/train/stage1.py 
  • 方法二(不推荐使用,使用方法较复杂,需要细粒度控制标准大页分配时可以尝试此方法):本方法支持更细粒度地控制哪些动态库使用标准大页,并且支持标记指定的段。
    1. 首先确认当前待运行程序会使用到的动态库。

      使能动态库大页,并非动态库的所有PT_LOAD段的映射都会使用大页,只有PT_LOAD段映射的区间覆盖了至少一个完整的2MB大页,才会尝试映射2MB大页。

      可以通过readelf -l xxx.so来判断当前动态库LOAD段是否超过2M,下面以libtorch_npu.so为例:

      上面图中,LOAD段对应VirtAddr和MemSiz分别为0x0000000000000000和0x0000000001bc47e4,段大小即MemSize为十六进制的0x0000000001bc47e4,转换为十进制之后为29116388字节,进一步计算为27M,超过了2M,因此libtorch_npu.so使用动态库大页可生效。

      • libtorch_npu.so为Python软件包torch_npu提供,请先确认当前应用程序是否会使用到该动态库。
      • conda环境下,请确保标记的动态库文件为应用程序所使用的动态库文件。
    2. 标记动态库。

      hugepageedit工具为glibc-devel包提供的二进制程序,若无此命令请参考上面使用方法中安装glibc-devel包命令。

      • 标记所有段。
        hugepageedit <file>
      • 只标记代码段。
        hugepageedit -x <file>
      • 标记动态库中的指定段。
        hugepageedit -i <index> <file>
        • index:类型为LOAD的段在ELF格式文件中的索引,从0开始,可以通过readelf -l file查看ProgramHeaders表,索引值对应表中段的顺序。
        • hugepageedit -i选项一次只能指定一个段,可以执行多次。
        • hugepageedit -i选项不能指定非LOAD段,索引值不能超过ELF可执行文件的段的数量。
      • 清除所有标记。
        hugepageedit -d <file>
    3. 使能HUGEPAGE_PROBE环境变量,仅支持配置为1,其他值未定义。该环境变量支持在外部shell脚本中使用,环境变量的值会传递到程序中。配置为1时动态库中被hugepageedit工具标记的段使用大页。
      hugepageedit libtorch_npu.so
      export HUGEPAGE_PROBE=1