使用 Compute Engine 客户端进行性能测试

本页面介绍了如何使用 Compute Engine 客户端测试 Google Cloud Managed Lustre 实例的性能。它提供了有关如何使用 fio 衡量单客户端性能以及使用 IOR 基准测试工具衡量多客户端总体性能的说明。

衡量单客户端性能

如需测试单个 Compute Engine 客户端的读取和写入性能,请使用 fio灵活的 I/O 测试工具)命令行工具。

  1. 安装 fio:

    Rocky 8

    sudo dnf install fio -y
    

    Ubuntu 20.04 和 22.04

    sudo apt update
    sudo install fio
    
  2. 运行以下命令:

    fio --ioengine=libaio --filesize=32G --ramp_time=2s \
    --runtime=5m --numjobs=16 --direct=1 --verify=0 --randrepeat=0 \
    --group_reporting --directory=/lustre --buffer_compress_percentage=50 \
    --name=read --blocksize=1m --iodepth=64 --readwrite=read
    

测试大约需要 5 分钟才能完成。完成后,系统会显示结果。根据您的配置,您可以获得高达虚拟机的最大网络速度的吞吐量,以及每 TiB 数千 IOPS。

衡量多客户账号的表现

如需测试多个 Compute Engine 客户端的 Managed Lustre 读取和写入性能,请使用 IOR 基准测试工具。以下说明介绍了如何自动执行客户端设置,以及如何使用 IOR 测试来自多个客户端计算机的聚合 I/O。IOR 使用 MPI(一种消息传递协议)来使多个客户端机器能够相互协调。

在开始之前,请确保网络的 mtu 值已设置为 8896

设置环境变量并生成 SSH 密钥

在部署集群之前,请在本地机器上生成 SSH 密钥。此密钥将在创建期间分发到客户端计算机,以实现 MPI 的无密码通信。

export SSH_USER="lustre-user"
export CLIENT_PREFIX="lustre-client"

# Generate an SSH key for the specified user
ssh-keygen -t rsa -b 4096 -C "${SSH_USER}" -N '' -f "./id_rsa"
chmod 600 "./id_rsa"

# Create a metadata file formatted for Google Cloud
echo "${SSH_USER}:$(cat "./id_rsa.pub") ${SSH_USER}" > "./keys.txt"

创建启动脚本

将以下内容保存到本地计算机上名为 install-ior.sh 的文件中。此脚本可检测操作系统、等待启动锁释放、安全地安装 Lustre 客户端和依赖项、编译稳定的 IOR 版本,并装载 Managed Lustre 文件系统。

LUSTRE_IP 替换为您的 Managed Lustre 实例的 IP 地址,并将 FS_NAME 替换为您的文件系统名称。

#!/bin/bash
source /etc/os-release

if [[ "$ID" == "ubuntu" ]]; then
    # Ubuntu
    # Wait for apt lock
    while fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1; do sleep 5; done

    # Configure Artifact Registry repo for Ubuntu
    curl -fsSL https://us-apt.pkg.dev/doc/repo-signing-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/us-apt-pkg-dev.gpg

    if [[ "$VERSION_ID" == "22.04" ]]; then
        REPO_NAME="lustre-client-ubuntu-jammy"
    elif [[ "$VERSION_ID" == "24.04" ]]; then
        REPO_NAME="lustre-client-ubuntu-noble"
    fi

    echo "deb [signed-by=/usr/share/keyrings/us-apt-pkg-dev.gpg] https://us-apt.pkg.dev/projects/lustre-client-binaries $REPO_NAME main" | sudo tee /etc/apt/sources.list.d/lustre-client.list

    sudo apt-get update
    while ! sudo apt-get install -y lustre-client-modules-$(uname -r) lustre-client-utils openmpi-bin libopenmpi-dev make gcc g++ wget git automake autoconf libaio-dev; do
        sleep 5
    done
    sudo modprobe lustre
else
    # Red Hat / Rocky Linux
    while systemctl is-active --quiet dnf-makecache.service; do sleep 5; done

    if [[ "$ID" == "rocky" && "$VERSION_ID" == 8* ]]; then
        REPO="lustre-client-rocky-8"
    elif [[ "$ID" == "rocky" && "$VERSION_ID" == 9* ]]; then
        REPO="lustre-client-rocky-9"
    elif [[ "$ID" == "rhel" && "$VERSION_ID" == 9* ]]; then
        REPO="lustre-client-rocky-9"
    fi

    gcloud beta artifacts print-settings yum --repository=$REPO --location=us --project=lustre-client-binaries | sudo bash

    while ! sudo dnf -y --enablerepo=$REPO install kmod-lustre-client lustre-client; do sleep 5; done
    sudo modprobe lustre

    while ! sudo dnf install -y openmpi openmpi-devel make gcc gcc-c++ wget git automake autoconf libaio-devel; do sleep 5; done

    export PATH=$PATH:/usr/lib64/openmpi/bin
fi

# Build IOR from source
echo "Cloning repo: https://github.com/hpc/ior.git and building IOR"
pushd /tmp
git clone -b 4.0.0 https://github.com/hpc/ior
cd ior
./bootstrap
./configure --disable-dependency-tracking --with-aio
make clean
make -j"$(nproc)"
sudo make install
popd
echo "Finished building IOR"

# Mount the Managed Lustre file system
mkdir -p /lustre

if ! grep -q "/lustre" /etc/fstab; then
    echo "LUSTRE_IP@tcp:/FS_NAME /lustre lustre defaults,_netdev 0 0" >> /etc/fstab
fi

mount -a

部署客户端机器

运行以下命令以批量创建 Compute Engine 客户端机器。

gcloud compute instances bulk create \
  --name-pattern="${CLIENT_PREFIX}-####" \
  --zone="ZONE" \
  --machine-type="MACHINE_TYPE" \
  --scopes="https://www.googleapis.com/auth/cloud-platform" \
  --network-interface=subnet=SUBNET,nic-type=GVNIC \
  --network-performance-configs=total-egress-bandwidth-tier=TIER_1 \
  --metadata-from-file=ssh-keys=./keys.txt,startup-script=install-ior.sh \
  --create-disk=auto-delete=yes,boot=yes,\
image-family=IMAGE_FAMILY,\
image-project=IMAGE_PROJECT,\
mode=rw,size=100,type=DISK_TYPE \
  --count NUM_NODES
  • ZONESUBNET 替换为您的具体部署值。

  • 选择一个 MACHINE_TYPE。基准的整体性能取决于客户端机器类型。如需了解如何选择机器类型以获得最佳吞吐量,请参阅性能注意事项

  • 如果您的机器类型不支持 TIER_1 网络,请从命令中删除 --network-performance-configs 行。

  • DISK_TYPE 设置为 hyperdisk-balanced(对于世代名称中包含 4 的机器类型,例如 c4an4)或 pd-balanced

  • 指定 IMAGE_FAMILYIMAGE_PROJECT。 支持的值包括:

    操作系统 映像系列 (x86) 映像系列 (ARM) 映像项目
    HPC Rocky Linux 8 hpc-rocky-linux-8 不支持 cloud-hpc-image-public
    Rocky Linux 9 rocky-linux-9 rocky-linux-9-arm64 rocky-linux-cloud
    RHEL 9 rhel-9 rhel-9-arm64 rhel-cloud
    Ubuntu 22.04 LTS ubuntu-2204-lts ubuntu-2204-lts-arm64 ubuntu-os-cloud
    Ubuntu 24.04 LTS 不支持 ubuntu-2404-lts-arm64 ubuntu-os-cloud
  • 指定 NUM_NODES。为了使文件系统达到饱和状态,集群的总体网络容量应比文件系统的预配吞吐量高出约 20%。

    对于启用了 Tier 1 网络的机器,单个机器可以推送 25 Gbps 到 200 Gbps(约 3,000 到 25,000 MBps)之间的流量,具体取决于虚拟机系列和 CPU 数量。对于标准实例,出站流量通常限制为每个 vCPU 大约 2 Gbps。

    例如,如果您的 Managed Lustre 实例容量可实现 100,000 MBps 的理论吞吐量,则需要 120,000 MBps (100,000 * 1.2) 的客户端总出站流量才能达到饱和状态:

    • 使用标准实例:如果每台客户端机器的公布出站流量为 2,000 MBps,您应至少预配 60 个客户端 (120,000 / 2,000)。
    • 使用 Tier 1 网络:如果每台客户端机器的公布出站流量为 10,000 MBps(约 80 Gbps),您应至少预配 12 台客户端 (120,000 / 10,000)。

复制密钥和文件

在等待客户端计算机完成其启动脚本的过程中,在本地运行以下命令,以自动配置所有节点进行节点间通信。

  1. 保存客户端计算机的专用 IP 地址以用于 MPI 主机文件,并保存公共 IP 地址以用于 SSH 和 SCP 访问客户端计算机:

    gcloud compute instances list --filter="name ~ '^${CLIENT_PREFIX}*'" --format="csv[no-heading](INTERNAL_IP)" > hosts.txt
    gcloud compute instances list --filter="name ~ '^${CLIENT_PREFIX}*'" --format="csv[no-heading](EXTERNAL_IP)" > external_ips.txt
    
  2. 将私钥复制到所有客户端。这样,工作器节点便可在基准测试期间彼此安全地通信:

    while IFS= read -r IP || [[ -n "$IP" ]]
    do
      [[ -z "$IP" ]] && continue
      echo "Preparing and copying to ${SSH_USER}@${IP}..."
      # Ensure the .ssh directory exists
      ssh -i ./id_rsa -o StrictHostKeyChecking=no "${SSH_USER}@${IP}" "mkdir -p ~/.ssh && chmod 700 ~/.ssh"
      # Copy the file
      scp -i ./id_rsa -o StrictHostKeyChecking=no ./id_rsa "${SSH_USER}@${IP}:~/.ssh/id_rsa"
    done < "./external_ips.txt"
    
  3. 指定头节点并将主机文件复制到该节点。这将是您运行基准比较的机器。

    export HEAD_NODE=$(head -n 1 ./external_ips.txt)
    scp -i ./id_rsa -o "StrictHostKeyChecking=no" -o UserKnownHostsFile=/dev/null ./hosts.txt ${SSH_USER}@${HEAD_NODE}:~/hostfile
    

连接并验证

  1. 连接到头节点:

    ssh -i ./id_rsa -o "StrictHostKeyChecking=no" -o UserKnownHostsFile=/dev/null ${SSH_USER}@${HEAD_NODE}
    
  2. 在运行基准测试之前,请验证启动脚本是否已完成,以及文件系统是否已成功装载。

    如需查看启动脚本日志,请执行以下操作:

    sudo journalctl -u google-startup-scripts.service -f
    

    如需验证文件系统是否已装载,请执行以下操作:

    df -h | grep lustre
    

    如果未列出文件系统,请再等待几分钟,让后台安装脚本完成。装载后,它将位于绝对路径 /lustre 中。

运行 IOR 基准测试

  1. 仅限 Rocky Linux 和 RHEL:从头节点加载 OpenMPI 模块。

    if [ -f /etc/profile.d/modules.sh ]; then
        source /etc/profile.d/modules.sh
        module load mpi/openmpi-$(arch)
    fi
    
  2. 创建测试目录并获取所有权:

    sudo mkdir -p /lustre/test
    sudo chown -R $USER:$USER /lustre/test
    
  3. 定义测试变量:

    export NUM_NODES="NUM_NODES"
    export PROCESSES_PER_NODE="PROCESSES_PER_NODE"
    export NUM_PROCESSES=$(( NUM_NODES * PROCESSES_PER_NODE ))
    

    其中:

    • NUM_NODES:参与测试的客户端机器总数。
    • PROCESSES_PER_NODE:要在每个客户端机器上运行的 MPI 级数。建议您先将此值设置为与客户端计算机上的物理核心数(或 vCPU 数的一半)相同。对于高性能机器类型,将此值设置为介于 816 之间通常可获得最佳网络吞吐量。如果此设置过高,可能会导致上下文切换开销,并降低基准性能。
  4. 运行命令以启动基准测试:

    Rocky Linux 和 RHEL

    写入吞吐量

    此命令会持续写入 60 秒,以测试峰值稳态吞吐量。每个任务的文件大小上限随意设置为 50 TiB,以确保任务在 60 秒计时器到期之前一直处于写入状态。

    mpirun \
      --allow-run-as-root \
      --mca plm_rsh_no_tree_spawn 1 \
      --mca opal_set_max_sys_limits 1 \
      --mca plm_rsh_num_concurrent ${NUM_NODES} \
      --mca plm_rsh_args "-o StrictHostKeyChecking=no" \
      --prefix /usr/lib64/openmpi \
      --npernode ${PROCESSES_PER_NODE} \
      --np ${NUM_PROCESSES} \
      --hostfile ~/hostfile \
      /usr/local/bin/ior \
      -a AIO \
      --posix.odirect \
      -F -g -v -w -k \
      -t 4m -b 50t \
      -D 60 \
      -O stoneWallingWearOut=1 \
      -O stoneWallingStatusFile=/lustre/test/ior-easy.stonewall \
      -o /lustre/test/ior_file

    读取吞吐量

    此阶段会回读在 60 秒写入吞吐量测试期间成功写入的数据量。虽然每个任务的文件大小 (-b) 设置为 50 TiB 以匹配写入阶段的几何形状,但 -O stoneWallingWearOut=1 标志会指示 IOR 在达到 stonewall 状态文件中记录的确切数据边界时立即停止读取。

    mpirun \
      --allow-run-as-root \
      --mca plm_rsh_no_tree_spawn 1 \
      --mca opal_set_max_sys_limits 1 \
      --mca plm_rsh_num_concurrent ${NUM_NODES} \
      --mca plm_rsh_args "-o StrictHostKeyChecking=no" \
      --prefix /usr/lib64/openmpi \
      --npernode ${PROCESSES_PER_NODE} \
      --np ${NUM_PROCESSES} \
      --hostfile ~/hostfile \
      /usr/local/bin/ior \
      -a AIO \
      --posix.odirect \
      -F -g -v -r -k \
      -t 4m -b 50t \
      -D 60 \
      -O stoneWallingWearOut=1 \
      -O stoneWallingStatusFile=/lustre/test/ior-easy.stonewall \
      -o /lustre/test/ior_file

    写入 IOPS

    此测试使用较小的 4 KiB 传输大小和 8 GiB 的每任务文件大小来测量文件系统可处理的最大每秒输入/输出操作次数 (IOPS)。

    mpirun \
      --allow-run-as-root \
      --mca plm_rsh_no_tree_spawn 1 \
      --mca opal_set_max_sys_limits 1 \
      --mca plm_rsh_num_concurrent ${NUM_NODES} \
      --mca plm_rsh_args "-o StrictHostKeyChecking=no" \
      --prefix /usr/lib64/openmpi \
      --np ${NUM_PROCESSES} \
      --oversubscribe \
      --map-by node \
      --bind-to socket \
      --hostfile ~/hostfile \
      /usr/local/bin/ior \
      -e \
      -t 4k \
      -b 8g \
      -s 1 \
      -a AIO \
      --posix.odirect \
      --aio.max-pending=256 \
      -w \
      -F \
      -z \
      -Q 1 \
      -G 1745405099 \
      -D 45 \
      -O stoneWallingWearOut=1 \
      -o /lustre/test/ior-random

    读取 IOPS

    为防止从稀疏文件中读取,此测试使用两个命令:一个写入命令,用于创建使用 4 MiB 传输大小和 8 GiB 每任务文件大小的实心文件;另一个命令是实际的 4 KiB 随机读取 IOPS 测试。

    1. 创建要读取的文件:

      mpirun \
        --allow-run-as-root \
        --mca plm_rsh_no_tree_spawn 1 \
        --mca opal_set_max_sys_limits 1 \
        --mca plm_rsh_num_concurrent ${NUM_NODES} \
        --mca plm_rsh_args "-o StrictHostKeyChecking=no" \
        --prefix /usr/lib64/openmpi \
        --npernode ${PROCESSES_PER_NODE} \
        --np ${NUM_PROCESSES} \
        --oversubscribe \
        --map-by node \
        --bind-to socket \
        --hostfile ~/hostfile \
        /usr/local/bin/ior \
        -a AIO \
        --posix.odirect \
        -w \
        -F \
        -k \
        -t 4m \
        -b 8g \
        -s 1 \
        -Q 1 \
        -G 1745405099 \
        -o /lustre/test/ior_rand_read
    2. 运行 IOR 读取测试:

      mpirun \
        --allow-run-as-root \
        --mca plm_rsh_no_tree_spawn 1 \
        --mca opal_set_max_sys_limits 1 \
        --mca plm_rsh_num_concurrent ${NUM_NODES} \
        --mca plm_rsh_args "-o StrictHostKeyChecking=no" \
        --prefix /usr/lib64/openmpi \
        --oversubscribe \
        --map-by node \
        --bind-to socket \
        --npernode ${PROCESSES_PER_NODE} \
        --np ${NUM_PROCESSES} \
        --hostfile ~/hostfile \
        /usr/local/bin/ior \
        -a AIO \
        --posix.odirect \
        --aio.max-pending 256 \
        -r \
        -F \
        -z \
        -t 4k \
        -b 8g \
        -s 1 \
        -Q 1 \
        -G 1745405099 \
        -D 45 \
        -O stoneWallingWearOut=1 \
        -o /lustre/test/ior_rand_read

    Ubuntu

    写入吞吐量

    此命令会持续写入 60 秒,以测试峰值稳态吞吐量。每个任务的文件大小上限随意设置为 50 TiB,以确保任务在 60 秒计时器到期之前一直处于写入状态。

    mpirun \
      --allow-run-as-root \
      --mca plm_rsh_no_tree_spawn 1 \
      --mca opal_set_max_sys_limits 1 \
      --mca plm_rsh_num_concurrent ${NUM_NODES} \
      --mca plm_rsh_args "-o StrictHostKeyChecking=no" \
      --npernode ${PROCESSES_PER_NODE} \
      --np ${NUM_PROCESSES} \
      --hostfile ~/hostfile \
      /usr/local/bin/ior \
      -a AIO \
      --posix.odirect \
      -F -g -v -w -k \
      -t 4m -b 50t \
      -D 60 \
      -O stoneWallingWearOut=1 \
      -O stoneWallingStatusFile=/lustre/test/ior-easy.stonewall \
      -o /lustre/test/ior_file

    读取吞吐量

    此阶段会回读在 60 秒写入吞吐量测试期间成功写入的数据量。虽然每个任务的文件大小 (-b) 设置为 50 TiB 以匹配写入阶段的几何形状,但 -O stoneWallingWearOut=1 标志会指示 IOR 在达到 stonewall 状态文件中记录的确切数据边界时立即停止读取。

    mpirun \
      --allow-run-as-root \
      --mca plm_rsh_no_tree_spawn 1 \
      --mca opal_set_max_sys_limits 1 \
      --mca plm_rsh_num_concurrent ${NUM_NODES} \
      --mca plm_rsh_args "-o StrictHostKeyChecking=no" \
      --npernode ${PROCESSES_PER_NODE} \
      --np ${NUM_PROCESSES} \
      --hostfile ~/hostfile \
      /usr/local/bin/ior \
      -a AIO \
      --posix.odirect \
      -F -g -v -r -k \
      -t 4m -b 50t \
      -D 60 \
      -O stoneWallingWearOut=1 \
      -O stoneWallingStatusFile=/lustre/test/ior-easy.stonewall \
      -o /lustre/test/ior_file

    写入 IOPS

    此测试使用较小的 4 KiB 传输大小和 8 GiB 的每任务文件大小来测量文件系统可处理的最大每秒输入/输出操作次数 (IOPS)。

    mpirun \
      --allow-run-as-root \
      --mca plm_rsh_no_tree_spawn 1 \
      --mca opal_set_max_sys_limits 1 \
      --mca plm_rsh_num_concurrent ${NUM_NODES} \
      --mca plm_rsh_args "-o StrictHostKeyChecking=no" \
      --np ${NUM_PROCESSES} \
      --oversubscribe \
      --map-by node \
      --bind-to socket \
      --hostfile ~/hostfile \
      /usr/local/bin/ior \
      -e \
      -t 4k \
      -b 8g \
      -s 1 \
      -a AIO \
      --posix.odirect \
      --aio.max-pending=256 \
      -w \
      -F \
      -z \
      -Q 1 \
      -G 1745405099 \
      -D 45 \
      -O stoneWallingWearOut=1 \
      -o /lustre/test/ior-random

    读取 IOPS

    为防止从稀疏文件中读取,此测试使用两个命令:一个写入命令,用于创建使用 4 MiB 传输大小和 8 GiB 每任务文件大小的实心文件;另一个命令是实际的 4 KiB 随机读取 IOPS 测试。

    1. 创建要读取的文件:

      mpirun \
        --allow-run-as-root \
        --mca plm_rsh_no_tree_spawn 1 \
        --mca opal_set_max_sys_limits 1 \
        --mca plm_rsh_num_concurrent ${NUM_NODES} \
        --mca plm_rsh_args "-o StrictHostKeyChecking=no" \
        --npernode ${PROCESSES_PER_NODE} \
        --np ${NUM_PROCESSES} \
        --oversubscribe \
        --map-by node \
        --bind-to socket \
        --hostfile ~/hostfile \
        /usr/local/bin/ior \
        -a AIO \
        --posix.odirect \
        -w \
        -F \
        -k \
        -t 4m \
        -b 8g \
        -s 1 \
        -Q 1 \
        -G 1745405099 \
        -o /lustre/test/ior_rand_read
    2. 运行 IOR 读取测试:

      mpirun \
        --allow-run-as-root \
        --mca plm_rsh_no_tree_spawn 1 \
        --mca opal_set_max_sys_limits 1 \
        --mca plm_rsh_num_concurrent ${NUM_NODES} \
        --mca plm_rsh_args "-o StrictHostKeyChecking=no" \
        --oversubscribe \
        --map-by node \
        --bind-to socket \
        --npernode ${PROCESSES_PER_NODE} \
        --np ${NUM_PROCESSES} \
        --hostfile ~/hostfile \
        /usr/local/bin/ior \
        -a AIO \
        --posix.odirect \
        --aio.max-pending 256 \
        -r \
        -F \
        -z \
        -t 4k \
        -b 8g \
        -s 1 \
        -Q 1 \
        -G 1745405099 \
        -D 45 \
        -O stoneWallingWearOut=1 \
        -o /lustre/test/ior_rand_read

    mpirun 标志包括:

    • --mca plm_rsh_no_tree_spawn 1:停用基于树的守护程序生成,以提高跨节点的启动可靠性。
    • --mca opal_set_max_sys_limits 1:自动尝试将系统限制(例如最大打开文件数)设置为允许的最大值。
    • --mca plm_rsh_num_concurrent:设置启动工作器守护程序时 mpirun 将使用的并发 SSH 连接数上限。
    • --mca plm_rsh_args ...:绕过严格的主机密钥检查,以防止交互式 SSH 提示挂起 MPI 进程启动。
    • --prefix ...:明确定义了 Rocky Linux 和 RHEL 的 OpenMPI 安装路径,以便工作节点可以找到所需的守护程序 (orted)。
    • --allow-run-as-root:允许 mpirun 以根用户身份执行。
    • --oversubscribe:允许 MPI 在节点上调度比可用物理核心数更多的进程。
    • --map-by node:以轮循方式在可用节点之间均匀分配 MPI 进程。
    • --bind-to socket:将 MPI 进程绑定到物理 CPU 插槽,以优化内存访问和缓存性能。
    • --npernode:每个节点的进程数。
    • --np:要启动的 MPI 进程总数。
    • --hostfile:指定包含要运行的主机列表的文件。

    ior 标志包括:

    • -a AIO --posix.odirect:使用异步 I/O (AIO) 引擎与 POSIX 直接 I/O 相结合。这样可绕过客户端 RAM 页面缓存,并强制将并发的非阻塞写入直接发送到存储服务器,从而确保基准测试衡量的是真实的存储网络性能,而不是内存缓冲区。
    • --aio.max-pending=256:确定每个进程中正在进行的并发异步 I/O 操作的最大数量。
    • -C:重新排序任务以实现最佳读取性能。
    • -F:每个进程一个文件的模式。
    • -g:使用屏障来分隔测试的写入阶段和读取阶段。
    • -v:输出详细日志记录。
    • -w / -r:指示 IOR 运行写入 (-w) 或读取 (-r) 性能测试。
    • -k:防止 IOR 在写入后删除测试文件,从而使该文件可用于读取测试。
    • -e:在写入阶段之后执行 fsync,以保证数据已提交到存储驱动器。
    • -z:指示 IOR 执行随机访问 I/O,而不是顺序访问。
    • -s 1:将段数设置为 1。
    • -Q 1:设置每个节点的任务偏移量,对齐任务,以便基准在所有节点上正确协调。
    • -G 1745405099:对随机种子时间戳进行硬编码,以便读取阶段生成与写入阶段使用的完全相同的随机文件偏移量。
    • -t:为每个 I/O 操作设置传输大小(例如,4m 表示吞吐量,4k 表示 IOPS)。
    • -b:设置每个进程的目标块大小(例如,50t 表示吞吐量,8g 表示 IOPS),以确保测试在定时运行期间不会耗尽载荷数据。
    • -D:将测试运行时长限制为特定秒数(例如,6045)。这种“石墙”会均匀地终止基准测试,以捕获真实的稳态测量结果。
    • -O stoneWallingWearOut=1:强制所有并发线程在整个持续时间内持续生成写入负载,防止较快的线程提前完成并降低整体网络压力。
    • -O stoneWallingStatusFile=<path>:在写入阶段结束时写入状态验证文件。后续读取阶段会使用此文件仅读取已成功提交的块,从而防止在读取期间出现 null 指针错误。
    • -o:Managed Lustre 文件系统上测试文件的路径。

查看结果

基准测试完成后,它会直接在终端中显示所有客户端虚拟机或 pod 的汇总性能指标。在输出的底部查找结果表格,以找到最大吞吐量或 IOPS。

关键指标

  • aggregate filesize:测试期间所有参与的客户端写入或读取的数据总量。

  • bw(MiB/s) / Max Write / Max Read:顺序测试最重要的指标。此图显示了 Managed Lustre 文件系统实现的聚合带宽。

  • IOPS:随机 I/O 测试最重要的指标。这表示每秒输入/输出操作数的最大值。

将结果导出到文件

如果您想以程序化方式解析结果、将结果馈送到数据库,或保存结果以供日后分析,可以指示 IOR 以 JSON 和 CSV 格式导出摘要数据,而不是仅将它们打印到屏幕上。

为此,请将 -O 标志附加到 ior 命令字符串的末尾:

-O summaryFormat=JSON \
-O summaryFile=/lustre/test/perf-results/summary.json \
-O saveRankPerformanceDetailsCSV=/lustre/test/perf-results/details.csv

在运行基准比较之前,文件系统上必须已存在输出目录。

预期性能与实际性能对比

您可以根据文件系统的预配容量和性能层级计算其数学最大吞吐量。由于存储空间容量是以吉比字节 (GiB) 为单位预配的,而层级是以太比字节 (TiB) 为单位评定的,因此您必须先转换容量:

(Capacity GiB / 1024) * Tier MBps = 理论最大 MBps

例如,在每 TiB 500 MBps 层级中,一个 216,000 GiB 的实例在数学上可提供 105,469 MBps 的吞吐量 ((216000 / 1024) * 500)。

观测到的最大吞吐量始终会受到文件系统预配的吞吐量容量或客户端机器的总网络出站流量限制(以较低者为准)的限制。

基准测试结果可能无法达到理论速度的常见原因包括:

  • TCP/IP 开销:标准网络封装和数据包标头会占用大约 5-10% 的原始带宽。您的数学最大值包含此开销,但 IOR 基准仅测量写入磁盘的原始载荷。

  • 客户端网络限制:客户端机器的出站带宽上限非常严格。如果您使用的客户端或节点数量较少,或者使用的机器类型未启用 Tier 1 网络,那么在 Managed Lustre 文件系统达到其限制之前,客户端就会限制基准。

  • MPI 上下文切换:如果 PROCESSES_PER_NODE 设置的值高于客户端计算机上的物理核心数,CPU 争用和上下文切换开销会人为地降低基准的 I/O 性能。

  • 缺少直接 I/O:如果省略 --posix.odirect 标志,数据会通过客户端的 RAM 页面缓存。这会造成内存瓶颈和 CPU 开销,从而掩盖真实的联网存储性能。

清理

为避免因本页中使用的资源导致您的 Google Cloud 账号产生费用,请按照以下步骤操作:

  1. 从 Managed Lustre 卷中删除测试文件:

    ssh -i ./id_rsa -o "StrictHostKeyChecking=no" -o UserKnownHostsFile=/dev/null ${SSH_USER}@${HEAD_NODE} "rm -rf /lustre/test"
    
  2. 删除批量创建的 Compute Engine 客户端机器:

    gcloud compute instances delete $(gcloud compute instances list \
      --filter="name~'^${CLIENT_PREFIX}-'" --format="value(name)" --zones="ZONE") \
      --zone="ZONE"
    

    或者,如果您知道确切的名称,或者想要单独删除它们,请执行以下操作:

    gcloud compute instances delete CLIENT_PREFIX-0001 CLIENT_PREFIX-0002 ... --zone=ZONE
    
  3. 如果您创建了自定义映像,可以将其删除:

    gcloud compute images delete CUSTOM_IMAGE_NAME
    
  4. 如果您专门为此测试创建了 Managed Lustre 实例,但不再需要它,请将其删除:

    gcloud lustre instances delete INSTANCE_ID --location=LOCATION
    

排查常见的基准测试瓶颈问题

如果基准测试结果明显低于预期的存储性能层级,请参阅排查常见瓶颈