在 Compute Engine 上运行紧密耦合的 HPC 应用的最佳做法

本文档介绍调节 Google Cloud 资源以实现消息传递接口 (MPI) 最优性能的最佳做法。紧密耦合的高性能计算 (HPC) 工作负载通常使用 MPI 在进程和实例之间进行通信。正确调节底层系统和网络基础架构是实现 MPI 最优性能的关键所在。如果您在 Google Cloud 中运行基于 MPI 的代码,请使用这些做法以获得最优性能。

假设和要求

通常,SlurmHTCondor 等工作负载调度器用于管理实例。本文档中的建议和最佳做法适用于所有调度器和工作流管理器。

具体如何使用各种调度器或工作流工具实现这些最佳做法不在本文档的探讨范围之内。实现工具以及这些工具的使用准则在其他文档和教程中提供。

本文档中提供的准则属于通用性质,可能并不适用于所有应用。我们建议您对应用进行基准测试,以便找到最高效或最具成本效益的配置。

使用预配置的 HPC 虚拟机映像

您可以使用针对紧密耦合的工作负载和 MPI 工作负载优化的 HPC 虚拟机 (VM) 映像(基于 CentOS),而不是手动应用本文档中介绍的最佳做法。HPC 虚拟机映像包含了这些最佳做法,可通过 Google Cloud Marketplace 获取,无需支付额外的费用。如需了解详情,请参阅创建支持 HPC 的虚拟机实例

使用 Bash 或 Ansible 应用配置

Google 允许您使用 Bash 脚本或 Ansible 脚本在 Compute Engine 实例上应用任意或全部优化和最佳做法。这些脚本位于 Google HPC-Tools GitHub 代码库中。这些脚本支持多个选项,可让您应用单个配置或同时应用多个配置。

Compute Engine 配置

本部分介绍使应用实现最优计算性能的最佳做法。在系统中使用正确的机器类型和设置会对 MPI 性能产生重大影响。

使用紧凑放置政策

通过放置政策,您可以控制虚拟机在数据中心的放置。紧凑放置政策可以为单个可用性区域中的虚拟机放置提供低延迟拓扑。当前 API 可让您创建最多 22 个经过计算优化 (C2) 的虚拟机,这些虚拟机的物理位置彼此接近。如果您需要 22 个以上的 C2 实例(660 多个物理核心),请将您的实例划分进多个放置政策中。我们建议您使用满足工作负载要求的最低放置政策数量。

如需使用放置政策,请首先在给定地区创建与所需数量的虚拟机搭配的放置政策:

gcloud compute resource-policies create group-placement \
    PLACEMENT_POLICY_NAME --collocation=collocated \
    --vm-count=NUMBER_OF_VMS

然后使用该政策在所需区域创建实例:

gcloud compute instances create instance-1 \
    instance-2...instance-n --zone=us-central1-a \
    --resource-policies=PLACEMENT_POLICY_NAME \
    --maintenance-policy=TERMINATE ...

某些情况下,您可能无法直接控制虚拟机的创建方式。例如,您可以使用一些未集成的第三方工具来创建虚拟机。如需将放置政策应用于现有虚拟机,请先关停虚拟机,然后运行以下命令:

gcloud compute instances add-resource-policies \
    instance-1 instance-2...instance-n --zone=us-central1-a \
    --resource-policies=PLACEMENT_POLICY_NAME

使用计算优化实例

我们建议您使用 C2 实例运行 HPC 应用。这些实例具有虚拟核心到物理核心的固定映射,并向客机操作系统公开 NUMA 单元架构,这两种特性对于紧密耦合的 HPC 应用性能至关重要。

C2 实例最多可拥有 60 个 vCPU(30 个物理核心)和 240 GB RAM。它们还可以拥有高达 3 TB 的本地 SSD 存储空间,并支持高达 32 Gbps 的网络吞吐量。C2 实例还利用第 2 代 Intel Xeon 可扩缩处理器 (Cascade Lake),与其他实例类型相比,可提供更多内存带宽和更高的时钟速度(高达 3.8 GHz)。 C2 实例的性能通常比 N1 实例类型高达 40%。

为了减少机器之间的通信开销,我们建议您将工作负载整合到数量较少的 C2-standard-60 虚拟机中(总核心数相同),而不是启动数量更大的小型 C2 虚拟机。

停用超线程

通过在客机操作系统中停用超线程,某些 MPI 应用可以获得更好的性能。超线程为节点上的每个物理核心分配两个虚拟核心 (vCPU)。对于许多常规计算任务或需要大量 I/O 的任务来说,超线程可以显著提高应用吞吐量。对于两个虚拟核心均受计算限制的计算限制型作业来说,超线程可能会影响应用的总体性能,并可能会增加作业的不确定性。关闭超线程有助于使性能更具预测性,并且可以减少作业时间。

您可以在 C2、N1-Ultramem 和 N2 实例上停用超线程,在线或通过重新启动均可。

如需在线停用超线程,请使用 Manage_Hyperthreading.sh 等脚本,它将活动 CPU 设为离线状态。

如需通过重新启动来停用超线程,请将以下内容添加到 /etc/default/grub 中的 GRUB_CMDLINE_LINUX 字符串,其中 NUM_CPU 是实例中的 vCPU 数量除以 2。例如,如果是 C2-standard-60 实例,NUM_CPU 为 30。

noht nosmt nr_cpus=NUM_CPU

更改 grub 文件后,请运行以下命令以更新 GRUB 系统配置文件,然后重新启动系统:

sudo grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg

如果您的系统采用的是旧式 BIOS 启动模式,请运行以下命令:

sudo grub2-mkconfig -o /boot/grub2/grub.cfg

如需验证重新启动后系统中是否停用了 SMP(超线程),请使用以下命令:

lscpu | grep -e Socket -e Core -e Thread

输出类似于以下内容,其中,停用超线程时 Thread(s) per core1,启用超线程时为 2

Thread(s) per core:    1
Core(s) per socket:    15
Socket(s):             2

调整用户限制

Unix 系统对系统资源(例如开放文件和任何用户可以使用的进程数量)进行了默认限制。这些限制可防止一个用户独占系统资源并影响其他用户工作。但是,HPC 环境中通常没有必要进行这些限制,因为用户之间不会直接共享集群中的计算节点。

您可以通过修改 /etc/security/limits.conf 文件并再次登录到节点来调整用户限制。如果是自动操作,您可以将这些更改引入虚拟机映像中,或在部署时通过使用 Deployment Manager、Terraform 或 Ansible 等工具调整限制。

调整用户限制时,请更改以下限制的值:

  • nproc - 进程数上限
  • memlock - 最大锁定内存地址空间 (KB)
  • stack - 堆栈大小上限 (KB)
  • nofile - 最大打开文件数
  • cpu - 最大 CPU 时间(分钟)
  • rtprio - 非特权进程允许的最大实时优先级(Linux 2.6.12 及更高版本)

这些限制在大多数 Unix 和 Linux 系统(包括 Debian,CentOS 和 Red Hat)的 /etc/security/limits.conf 系统配置文件中进行配置。

如需更改用户限制,请使用文本编辑器更改以下值:

  • /etc/security/limits.conf 中:

    *            -     nproc     unlimited
    *            -     memlock   unlimited
    *            -     stack     unlimited
    *            -     nofile    1048576
    *            -     cpu       unlimited
    *            -     rtprio    unlimited
    
  • /etc/security/limits.d/20-nproc.conf 中:

    *            -    nproc      unlimited
    

设置 SSH 主机密钥

Intel MPI 要求执行 mpirun 的节点的 ~/.ssh/known_hosts 文件中提供所有集群节点的主机密钥。您还必须将 SSH 密钥保存在 authorized_keys 中。

如需添加主机密钥,请运行以下命令:

ssh-keyscan -H 'cat HOSTFILE' >> ~/.ssh/known_hosts

另一种方法是运行以下命令,将 StrictHostKeyChecking=no 添加到 ~/.ssh/config 文件中:

Host *
StrictHostKeyChecking no

存储

许多 HPC 应用的性能主要取决于底层存储系统的性能。对于读取或写入大量数据或者创建或访问多个文件或对象的应用来说尤其如此。当多个等级同时访问存储系统时也是如此。

选择 NFS 文件系统或并行文件系统

以下是紧密耦合应用的主要存储方案。 每种方案都有自己的费用、性能配置文件、API 和一致性语义:

  • 基于 NFS 的解决方案(如 Filestore 和 NetApp Cloud Volumes)是部署共享存储方案的最简单方式。这两种方案都在 Google Cloud 上完全代管,在以下情况下为最佳方案:当应用对单个数据集没有极致的 I/O 要求,并且在应用执行期间和更新期间计算节点之间没有数据共享时。如需了解性能限制,请参阅 FilestoreNetApp Cloud Volumes 文档。
  • MPI 应用较常使用基于 POSIX 的并行文件系统。基于 POSIX 的方案包含开源 Lustr和完全受支持的 Luster 产品 DDN Storage EXAScaler Cloud。计算节点生成和共享数据时,它们通常依赖并行文件系统提供的极致性能,并支持完整的 POSIX 语义。Luster 等并行文件系统将数据传送到最大的超级计算机,并且可以支持数千个客户端。Luster 还支持 NetCDFHDF5 等数据和 I/O 库,以及 MPI-IO,支持将并行 I/O 应用于一系列广泛的应用领域。

选择存储基础架构

您应根据应用性能要求选择文件系统的存储基础架构或存储层级。例如,如果您为不需要每次 I/O 操作次数 (IOPS) 很高的应用部署 SSD,则可能会增加成本,但收效不大。

代管式存储服务 FilestoreNetApp Cloud Volumes 提供几个根据容量进行扩缩的性能层级。

为了确定适合开源 LustreDDN Storage EXAScaler Cloud 的正确基础架构,您必须先了解使用标准永久性磁盘、SSD 永久性磁盘或本地 SSD 实现所需性能需要的 vCPU 和容量。如需详细了解如何确定正确的基础架构,请参阅块存储性能信息优化永久性磁盘性能。例如,如果您使用 Luster,则可以通过用于元数据服务器 (MDS) 的 SSD 永久性磁盘和用于存储服务器 (OSS) 的标准永久性磁盘部署低成本、高带宽的解决方案。

网络设置

对于许多 HPC 应用而言,MPI 网络性能至关重要。对于 MPI 进程在不同节点上频繁通信或具有大量数据的紧密耦合应用来说,尤其如此。本部分介绍调节网络设置以实现最优 MPI 性能的最佳做法。

提高 tcp_*mem 设置

C2 机器可支持高达 32 Gbps 带宽,所需的 TCP 内存大于默认 Linux 设置。为提高网络性能,请提高 tcp_mem 值。

如需提高 TCP 内存限制,请在 /etc/sysctl.conf 中更新以下值:

net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 16384 16777216

如需在 /etc/sysctl.conf 中加载新值,请运行 sysctl -p

使用网络延迟配置文件

您可以通过启用频繁轮询来提高某些应用的性能。 频繁轮询通过允许套接字层代码轮询网络设备的接收队列并停用网络中断,帮助减少网络接收路径中的延时。评估应用的延迟时间,以查看频繁轮询是否有所帮助。

网络延时配置文件会在重新启动后依然存在。如果您的系统已安装 tuned-adm,您可以通过在 CentOS 中运行以下命令来启用网络延时配置文件:

tuned-adm profile network-latency

如果您的系统未安装 tuned-adm,您可以通过将以下内容添加到 /etc/sysctl.conf 来启用频繁轮询:

net.core.busy_poll = 50
net.core.busy_read = 50

如需在 /etc/sysctl.conf 中加载新值,请运行 sysctl -p

MPI 库和用户应用

MPI 库设置和 HPC 应用配置会影响应用性能。为了使 HPC 应用具有最佳性能,请务必微调这些设置或配置。本部分介绍调节 MPI 库和用户应用以实现最优 MPI 性能的最佳做法。

使用 Intel MPI

为了获得最优性能,我们建议您使用 Intel MPI

如果是 Intel MPI 2018 版本,在 Google Cloud 上运行时,请指定通过共享内存专用服务使用 TCP 的底层通信结构:

mpirun -hostfile HOSTFILE -np NUM_PROCESSES \
    -ppn PROCESSES_PER_NODE -genv I_MPI_FABRICS "shm:tcp" APPLICATION

如果是 Intel MPI 2019+ 版本,请指定通过 RxM OFI 服务使用 TCP 的底层通信结构,以提高性能:

mpirun -hostfile HOSTFILE -np NUM_PROCESSES \
    -ppn PROCESSES_PER_NODE -genv I_MPI_FABRICS "ofi_rxm;tcp" APPLICATION

使用 mpitune 进行 MPI Collective 调节

Intel MPI 和 OpenMPI 等 MPI 实现有许多会影响通信性能的内部配置参数。这些参数与 MPI Collective 通信尤其相关,MPI Collective 通信可让您指定在 Google Cloud 环境中执行方式截然不同的算法和配置参数。我们强烈建议您根据应用的特征调节配置参数。

如需手动指定 MPI Collective 通信的算法和配置参数,我们建议您使用 mpitune。 如需运行 mpitune 命令,您必须拥有该目录的写入权限或以 root 身份运行该命令。

使用 mpitune 时,您可以针对虚拟机数量和每虚拟机进程数量的各个组合进行调节。举例来说,如果您使用的是 Intel MPI 2018 版本,则可以通过运行以下命令针对 22 个虚拟机和每虚拟机的 30 个进程进行调节:

mpitune -hf HOSTFILE -fl 'shm:tcp' -pr 30:30 -hr 22:22

上述 mpitune 命令会在 Intel MPI 目录中生成一个配置文件,您稍后可以使用该文件来运行应用。

如需使用应用的调节配置,请将 -tune 选项添加到 mpirun 命令:

mpirun -tune -hostfile HOSTFILE -genv I_MPI_FABRICS 'shm:tcp' -np 660 -ppn 30 ./app

如需启用调节功能,您必须明确提供 I_MPI_FABRICS 环境变量,同时每个虚拟机的节点数和每个节点的进程数必须与调节期间使用的值相匹配。

您可以在 Intel MPI 安装目录 intel/mpi/2018.1/etc64 中找到生成的调节文件。

如下所示,文件名采用设备、节点数和其他信息编码而成:

mpiexec_shm-tcp_nn_22_np_660_ppn_30.conf

您可以在配置类似的其他组虚拟机上重复使用该文件,只需将该文件复制到相应目录并向 mpirun 命令添加 -tune 选项即可。您还可以选择将配置文件添加为 -tune 参数后面的参数。

使用 MPI OpenMP 混合模式

许多 MPI 应用都支持混合模式,您可以使用该模式在 MPI 应用中启用 OpenMP。在混合模式下,每个 MPI 进程都可以使用固定数量的线程来加快某些循环结构的执行。

如果您想优化应用性能,建议您使用混合模式选项。使用混合模式可以降低每个虚拟机的 MPI 进程,从而减少进程间通信并缩短总通信时间。

启用混合模式还是 OpenMP 取决于应用。许多情况下,您可以通过设置以下环境变量来启用混合模式:

export OMP_NUM_THREADS=NUM_THREADS

使用此混合方法时,我们建议线程总数不超过虚拟机中的物理核心数。C2-standard-60 虚拟机具有 2 个 NUMA 套接字,每个套接字包含 15 个核心和 30 个 vCPU。我们建议您的任何 MPI 进程都不要具有跨多个 NUMA 节点的 OpenMP 线程。

使用矢量指令和 Math Kernel Library 编译应用

C2 虚拟机支持 AVX2, AVX512 矢量指令。您可以使用 AVX 指令对许多 HPC 应用进行编译,从而提高其性能。如果使用 AVX2 而不是 AVX512,则某些应用的性能会更好。我们建议您针对工作负载尝试这两个 AVX 指令。为了获得更好的科学计算性能,我们还建议您使用 Intel Math Kernel Library (Intel MKL)

使用适当的 CPU 编号

C2-standard-60 具有两个 NUMA 套接字,且 CPU 根据 NUMA 节点编号,如下所示:

NUMA node0 CPU(s):     0-14,30-44
NUMA node1 CPU(s):     15-29,45-59

下图演示如何将 CPU 编号分配给 C2-standard-60 实例所在 NUMA 节点上的每个 CPU。套接字 0 对应 NUMA node0,CPU 0-14 和 30-44。套接字 1 对应 NUMA node1,CPU 15-29 和 45-59。

C2-standard-60 节点的虚拟核心编号。

与该虚拟机中的单个核心对应的超线程 siblings 是 (0,30)(1,31)..(29,59)

Intel MPI 使用 NUMA CPU 编号来固定 MPI 作业的处理器。如果要在运行过程中一致的所有节点上使用一个核心一个超线程,请使用 CPU 编号 0-29。

Open MPI 使用 Portable Hardware Locality (hwloc) 报告的逻辑 CPU 编号。 如果使用 Open MPI,则超线程 siblings 按如下方式连续进行编号:

  • 套接字 0:0 (core 0 HT 0), 1 (core 0 HT 1), 2 (core 1 HT 0) ,...,28 (core 14 HT 0), 29 (core 14, HT 1)

  • 套接字 1:30 (core 0 HT 0), 31 (core 0 HT 1), 2 (core 1 HT 0) ,...,58 (core 14 HT 0), 59 (core 14, HT 1)

输出如下所示:

lstopo-no-graphics
Machine (240GB total)
  NUMANode L#0 (P#0 120GB) + Package L#0 + L3 L#0 (25MB)
    L2 L#0 (1024KB) + L1d L#0 (32KB) + L1i L#0 (32KB) + Core L#0
      PU L#0 (P#0)
      PU L#1 (P#30)
    L2 L#1 (1024KB) + L1d L#1 (32KB) + L1i L#1 (32KB) + Core L#1
      PU L#2 (P#1)
      PU L#3 (P#31)

使用 Open MPI 时,您可以通过使用 CPU 编号 0,2,4,..58,在运行过程中一致的所有节点上使用一个核心一个超线程。如需强制 MPI 将进程固定到核心,请在运行 openMPI 时使用选项 --bind-to core,然后使用 --report-bindings 选项验证绑定是否正确。

安全设置

您可以通过停用一些内置的 Linux 安全功能来提高 MPI 性能。停用每种功能带来的性能优势各不相同。 如果您确信自己的系统受到妥善保护,则可以评估停用以下安全功能的利弊。

停用 Linux 防火墙

对于 Google Cloud CentOS Linux 映像,防火墙默认处于启用状态。如需停用防火墙,请运行以下命令来停止并停用 firewalld 守护程序:

sudo systemctl stop firewalld
sudo systemctl disable firewalld
sudo systemctl mask --now firewalld

停用 SELinux

CentOS 中的 SELinux 默认处于启用状态。如需停用 SELinux,请修改 /etc/selinux/config 文件,并将 SELINUX=enforcingSELINUX=permissive 行替换为 SELINUX=disabled

为了使此更改生效,您必须进行重启。

关闭 Meltdown 和 Spectre 缓解措施

默认情况下,以下安全补丁程序在 Linux 系统上处于启用状态:

  • 变体 1,Spectre:CVE-2017-5753
  • 变体 2,Spectre:CVE-2017-5715
  • 变体 3,Meltdown:CVE-2017-5754
  • 变体 4,Speculative Store Bypass:CVE-2018-3639

您可能会在现代微处理器(包括在 Google Cloud 中部署的处理器)中发现上述 CVE 中所述的安全漏洞。您可以通过在启动时使用内核命令行(重启后依然存在)或在运行时中使用 debugfs(重启后不再存在),停用一项或多项上述缓解措施,但这会引起相关安全风险。

如需永久停用上述安全缓解措施,请按以下步骤操作:

  1. 修改文件 /etc/default/grub

    sudo sed -i 's/^GRUB_CMDLINE_LINUX=\"\(.*\)\"/GRUB_CMDLINE_LINUX=\"\1 spectre_v2=off nopti spec_store_bypass_disable=off\"/' /etc/default/grub
    
  2. 更改 grub 文件后,请运行以下命令以更新 GRUB 系统配置文件,然后重新启动系统:

    sudo grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
    

    如果您的系统采用的是旧式 BIOS 启动模式,请运行以下命令:

    sudo grub2-mkconfig -o /boot/grub2/grub.cfg
    
  3. 重新启动。

如果系统已在运行,您可以通过运行以下命令停用上述安全缓解措施。重启后不再存在。

echo 0 > /sys/kernel/debug/x86/pti_enabled
echo 0 > /sys/kernel/debug/x86/retp_enabled
echo 0 > /sys/kernel/debug/x86/ibrs_enabled
echo 0 > /sys/kernel/debug/x86/ssbd_enabled

如需了解不同的缓解措施如何影响您的系统以及如何控制它们,请参阅 Red Hat 文档:控制微码和安全补丁程序对性能的影响使用推测性旁路漏洞的内核侧信道攻击

如需查找受影响的 CPU 漏洞,请运行以下命令:

grep . /sys/devices/system/cpu/vulnerabilities/*

如需查找已启用的缓解措施,请运行以下命令:

grep . /sys/kernel/debug/x86/*_enabled

核对清单摘要

下表汇总在 Compute Engine 上使用 MPI 的最佳做法。

范围 任务
Compute Engine 配置
存储
网络设置
MPI 库和用户应用
安全设置

后续步骤