Pruebas de rendimiento con clientes de Compute Engine

En esta página, se describe cómo probar el rendimiento de una instancia de Google Cloud Managed Lustre con clientes de Compute Engine. Se proporcionan instrucciones para medir el rendimiento de un solo cliente con fio y el rendimiento agregado de varios clientes con la herramienta de comparativas IOR.

Cómo medir el rendimiento de un solo cliente

Para probar el rendimiento de lectura y escritura desde un solo cliente de Compute Engine, usa la herramienta de línea de comandos fio (verificador de E/S flexible).

  1. Instala fio:

    Rocky 8

    sudo dnf install fio -y
    

    Ubuntu 20.04 y 22.04

    sudo apt update
    sudo install fio
    
  2. Ejecuta el siguiente comando:

    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
    

La prueba tarda aproximadamente 5 minutos en completarse. Cuando finaliza, se muestran los resultados. Según tu configuración, puedes esperar una capacidad de procesamiento de hasta la velocidad de red máxima de tu VM y miles de IOPS por TiB.

Cómo medir el rendimiento de varios clientes

Para probar el rendimiento de lectura y escritura de Managed Lustre desde varios clientes de Compute Engine, usa la herramienta de comparativas IOR. En las siguientes instrucciones, se muestra cómo automatizar la configuración del cliente y usar IOR para probar la E/S agregada desde varias máquinas cliente. IOR usa MPI, un protocolo de transmisión de mensajes, para permitir que las varias máquinas cliente se coordinen entre sí.

Antes de comenzar, asegúrate de que el valor mtu de tu red esté establecido en 8896.

Establece variables de entorno y genera una clave SSH

Antes de implementar tu clúster, genera una clave SSH en tu máquina local. Esta clave se distribuirá a tus máquinas cliente durante la creación para habilitar la comunicación sin contraseña para 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"

Crea la secuencia de comandos de inicio

Guarda el siguiente contenido en un archivo llamado install-ior.sh en tu máquina local. Esta secuencia de comandos detecta el sistema operativo, espera a que se liberen los bloqueos de arranque, instala de forma segura el cliente y las dependencias de Lustre, compila una versión estable de IOR y activa el sistema de archivos Managed Lustre.

Reemplaza LUSTRE_IP por la dirección IP de tu instancia de Managed Lustre y FS_NAME por el nombre de tu sistema de archivos.

#!/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

Implementa las máquinas cliente

Ejecuta el siguiente comando para crear de forma masiva las máquinas cliente de 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
  • Reemplaza ZONE y SUBNET con los valores de implementación específicos.

  • Elige un MACHINE_TYPE. El rendimiento general de tu comparativa depende de los tipos de máquinas cliente. Consulta Consideraciones sobre el rendimiento para obtener información sobre cómo elegir tipos de máquinas para obtener la mejor capacidad de procesamiento.

  • Si tu tipo de máquina no admite redes TIER_1, borra la línea --network-performance-configs del comando.

  • Establece el DISK_TYPE en uno de hyperdisk-balanced (para un tipo de máquina con un 4 en su nombre de generación, como c4a o n4) o pd-balanced.

  • Especifica IMAGE_FAMILY y IMAGE_PROJECT. Los valores admitidos son los que se detallan a continuación:

    SO Familia de imágenes (x86) Familia de imágenes (ARM) Proyecto de imagen
    HPC Rocky Linux 8 hpc-rocky-linux-8 No compatible 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
    LTS de Ubuntu 22.04 ubuntu-2204-lts ubuntu-2204-lts-arm64 ubuntu-os-cloud
    LTS de Ubuntu 24.04 No compatible ubuntu-2404-lts-arm64 ubuntu-os-cloud
  • Especifica NUM_NODES. Para saturar tu sistema de archivos, la capacidad de red agregada de tu clúster debe superar la capacidad de procesamiento aprovisionada de tu sistema de archivos en un 20%.

    Para las máquinas con redes de nivel 1 habilitadas, una sola máquina puede enviar entre 25 Gbps y 200 Gbps (aproximadamente 3,000 y 25,000 MBps), según la familia de VM y la cantidad de CPU. Para las instancias estándar, la salida suele tener un límite de alrededor de 2 Gbps por CPU virtual.

    Por ejemplo, si la capacidad de tu instancia de Managed Lustre genera 100,000 MBps de capacidad de procesamiento teórica, necesitas una salida agregada del cliente de 120,000 MBps (100,000 * 1.2) para saturarla:

    • Con instancias estándar: Si cada máquina cliente tiene una salida publicada de 2,000 MBps, debes aprovisionar al menos 60 clientes (120,000 / 2,000).
    • Con redes de nivel 1: Si cada máquina cliente tiene una salida publicada de 10,000 MBps (aproximadamente 80 Gbps), debes aprovisionar al menos 12 clientes (120,000 / 10,000).

Copia claves y archivos

Mientras esperas a que las máquinas cliente terminen sus secuencias de comandos de inicio, ejecuta los siguientes comandos de forma local para configurar automáticamente todos los nodos para la comunicación entre nodos.

  1. Guarda las direcciones IP privadas de las máquinas cliente para el archivo de host MPI y las direcciones IP públicas para el acceso SSH y SCP a las máquinas cliente:

    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. Copia la clave privada en todos los clientes. Esto permite que los nodos de trabajador se comuniquen entre sí de forma segura durante la comparativa:

    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. Designa el nodo principal y copia el archivo de host en él. Esta será la máquina desde la que ejecutarás la comparativa.

    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
    

Conéctate y verifica

  1. Conéctate a tu nodo principal:

    ssh -i ./id_rsa -o "StrictHostKeyChecking=no" -o UserKnownHostsFile=/dev/null ${SSH_USER}@${HEAD_NODE}
    
  2. Verifica que la secuencia de comandos de inicio haya finalizado y que el sistema de archivos se haya activado correctamente antes de ejecutar la comparativa.

    Para verificar los registros de la secuencia de comandos de inicio, haz lo siguiente:

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

    Para verificar que el sistema de archivos esté activado, haz lo siguiente:

    df -h | grep lustre
    

    Si el sistema de archivos no aparece en la lista, espera unos minutos más para que se complete la secuencia de comandos de instalación en segundo plano. Una vez activado, estará disponible en la ruta de acceso absoluta /lustre.

Ejecuta la comparativa IOR

  1. Solo para Rocky Linux y RHEL: Carga el módulo OpenMPI desde el nodo principal.

    if [ -f /etc/profile.d/modules.sh ]; then
        source /etc/profile.d/modules.sh
        module load mpi/openmpi-$(arch)
    fi
    
  2. Crea un directorio de prueba y toma la propiedad:

    sudo mkdir -p /lustre/test
    sudo chown -R $USER:$USER /lustre/test
    
  3. Define las variables de prueba:

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

    Aquí:

    • NUM_NODES: Es la cantidad total de máquinas cliente que participan en la prueba.
    • PROCESSES_PER_NODE: Es la cantidad de rangos de MPI que se ejecutarán en cada máquina cliente individual. Te recomendamos que comiences por establecer esto para que coincida con la cantidad de núcleos físicos (o la mitad de la cantidad de CPU virtuales) en tus máquinas cliente. Para los tipos de máquinas de alto rendimiento, establecer esto entre 8 y 16 suele producir la mejor capacidad de procesamiento de red. Si estableces un valor demasiado alto, se puede generar una sobrecarga de cambio de contexto y degradar el rendimiento de la comparativa.
  4. Ejecuta el comando para iniciar la comparativa:

    Rocky Linux y RHEL

    Capacidad de procesamiento de escritura

    Este comando escribe de forma continua durante 60 segundos para probar la capacidad de procesamiento máxima en estado estable. El tamaño de archivo por tarea se establece en un límite superior de 50 TiB arbitrariamente grande para que las tareas sigan escribiendo hasta que venza el temporizador de 60 segundos.

    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

    Capacidad de procesamiento de lectura

    En esta fase, se vuelve a leer exactamente la cantidad de datos que se escribieron correctamente durante la prueba de capacidad de procesamiento de escritura de 60 segundos. Aunque el tamaño de archivo por tarea (-b) se establece en 50 TiB para que coincida con la geometría de la fase de escritura, la marca -O stoneWallingWearOut=1 le indica a IOR que deje de leer en cuanto alcance el límite de datos exacto registrado en el archivo de estado de 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 de escritura

    Esta prueba usa tamaños de transferencia pequeños de 4 KiB y tamaños de archivo por tarea de 8 GiB para medir las operaciones de entrada y salida por segundo (IOPS) máximas que puede controlar el sistema de archivos.

    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 de lectura

    Para evitar la lectura de un archivo disperso, esta prueba usa dos comandos: una escritura para crear un archivo sólido con tamaños de transferencia de 4 MiB y tamaños de archivo por tarea de 8 GiB, seguida de la prueba real de IOPS de lectura aleatoria de 4 KiB.

    1. Crea el archivo para leer:

      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. Ejecuta la prueba de lectura de 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

    Capacidad de procesamiento de escritura

    Este comando escribe de forma continua durante 60 segundos para probar la capacidad de procesamiento máxima en estado estable. El tamaño de archivo por tarea se establece en un límite superior de 50 TiB arbitrariamente grande para que las tareas sigan escribiendo hasta que venza el temporizador de 60 segundos.

    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

    Capacidad de procesamiento de lectura

    En esta fase, se vuelve a leer exactamente la cantidad de datos que se escribieron correctamente durante la prueba de capacidad de procesamiento de escritura de 60 segundos. Aunque el tamaño de archivo por tarea (-b) se establece en 50 TiB para que coincida con la geometría de la fase de escritura, la marca -O stoneWallingWearOut=1 le indica a IOR que deje de leer en cuanto alcance el límite de datos exacto registrado en el archivo de estado de 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 de escritura

    Esta prueba usa tamaños de transferencia pequeños de 4 KiB y tamaños de archivo por tarea de 8 GiB para medir las operaciones de entrada y salida por segundo (IOPS) máximas que puede controlar el sistema de archivos.

    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 de lectura

    Para evitar la lectura de un archivo disperso, esta prueba usa dos comandos: una escritura para crear un archivo sólido con tamaños de transferencia de 4 MiB y tamaños de archivo por tarea de 8 GiB, seguida de la prueba real de IOPS de lectura aleatoria de 4 KiB.

    1. Crea el archivo para leer:

      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. Ejecuta la prueba de lectura de 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

    Las marcas mpirun son las siguientes:

    • --mca plm_rsh_no_tree_spawn 1: Inhabilita la generación de daemons basados en árboles para mejorar la confiabilidad del lanzamiento en los nodos.
    • --mca opal_set_max_sys_limits 1: Intenta establecer automáticamente los límites del sistema (como la cantidad máxima de archivos abiertos) en sus valores permitidos más altos.
    • --mca plm_rsh_num_concurrent: Establece la cantidad máxima de conexiones SSH simultáneas que usará mpirun cuando inicie daemons de trabajador.
    • --mca plm_rsh_args ...: Omite la verificación estricta de la clave de host para evitar que las solicitudes interactivas de SSH cuelguen el inicio del proceso MPI.
    • --prefix ...: Define de forma explícita la ruta de instalación de OpenMPI para Rocky Linux y RHEL, de modo que los nodos de trabajador puedan encontrar el daemon requerido (orted).
    • --allow-run-as-root: Permite que mpirun se ejecute como el usuario raíz.
    • --oversubscribe: Permite que MPI programe más procesos en un nodo de los que hay núcleos físicos disponibles.
    • --map-by node: Distribuye los procesos MPI de forma rotativa de manera uniforme en los nodos disponibles.
    • --bind-to socket: Vincula los procesos MPI a los sockets de CPU físicos para optimizar el acceso a la memoria y el rendimiento de la caché.
    • --npernode: Es la cantidad de procesos por nodo.
    • --np: Es la cantidad total de procesos MPI que se iniciarán.
    • --hostfile: Especifica el archivo que contiene la lista de hosts en los que se ejecutará.

    Las marcas ior son las siguientes:

    • -a AIO --posix.odirect: Usa el motor de E/S asíncrona (AIO) combinado con la E/S directa de POSIX. Esto omite la caché de página de RAM del cliente y fuerza las escrituras simultáneas sin bloqueo directamente a los servidores de almacenamiento, lo que garantiza que la comparativa mida el rendimiento real del almacenamiento de red en lugar de los búferes de memoria.
    • --aio.max-pending=256: Determina la cantidad máxima de operaciones de E/S asíncronas simultáneas en tránsito por proceso.
    • -C: Reordena las tareas para obtener un rendimiento de lectura óptimo.
    • -F: Modo de archivo por proceso.
    • -g: Usa barreras para separar las fases de escritura y lectura de la prueba.
    • -v: Muestra el registro detallado.
    • -w / -r: Le indica a IOR que ejecute la prueba de rendimiento de escritura (-w) o lectura (-r) .
    • -k: Evita que IOR borre el archivo de prueba después de escribir, lo que lo hace disponible para la prueba de lectura.
    • -e: Realiza un fsync después de la fase de escritura para garantizar que los datos se confirmen en las unidades de almacenamiento.
    • -z: Le indica a IOR que realice E/S de acceso aleatorio en lugar de acceso secuencial.
    • -s 1: Establece la cantidad de segmentos en 1.
    • -Q 1: Establece el desplazamiento de tarea por nodo, alinea las tareas para que la comparativa se coordine correctamente en todos los nodos.
    • -G 1745405099: Codifica de forma rígida la marca de tiempo de la semilla aleatoria para que la fase de lectura genere los mismos desplazamientos de archivo aleatorios que usó la fase de escritura.
    • -t: Establece el tamaño de transferencia para cada operación de E/S (p.ej., 4m para la capacidad de procesamiento, 4k para IOPS).
    • -b: Establece el tamaño de bloque de destino por proceso (p.ej., 50t para la capacidad de procesamiento, 8g para IOPS) para garantizar que la prueba no se quede sin datos de carga útil durante la ejecución cronometrada.
    • -D: Restringe la duración del tiempo de ejecución de la prueba a una cantidad específica de segundos (p.ej., 60 o 45). Este "stonewalling" finaliza la comparativa de manera uniforme para capturar una medición real en estado estable.
    • -O stoneWallingWearOut=1: Fuerza a todos los subprocesos simultáneos a seguir generando una carga de escritura continua durante toda la duración, lo que evita que los subprocesos más rápidos se completen antes y disminuyan la presión general de la red. presión.
    • -O stoneWallingStatusFile=<path>: Escribe un archivo de verificación de estado al final de la fase de escritura. La fase de lectura posterior usa este archivo para leer solo los bloques que se confirmaron correctamente, lo que evita errores de puntero nulo durante las lecturas.
    • -o: Es la ruta de acceso al archivo de prueba en el sistema de archivos Managed Lustre

Vea los resultados

Cuando se completa la comparativa, se muestran las métricas de rendimiento agregadas de todas las VMs o los pods cliente directamente en tu terminal. Busca la tabla Results en la parte inferior del resultado para encontrar tu capacidad de procesamiento o IOPS máximas.

Métricas clave

  • aggregate filesize: Es la cantidad total de datos escritos o leídos durante la prueba en todos los clientes participantes.

  • bw(MiB/s) / Max Write / Max Read: Es la métrica más importante para las pruebas secuenciales. Muestra la capacidad de procesamiento agregada que logró el sistema de archivos Managed Lustre.

  • IOPS: Es la métrica más importante para las pruebas de E/S aleatorias. Muestra las operaciones de entrada y salida por segundo máximas.

Exporta los resultados a un archivo

Si deseas analizar tus resultados de forma programática, ingresarlos en una base de datos o guardarlos para su análisis posterior, puedes indicarle a IOR que exporte los datos de resumen en formatos JSON y CSV en lugar de solo imprimirlos en la pantalla.

Para ello, agrega las marcas -O al final de la cadena de comandos ior:

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

El directorio de salida debe existir en el sistema de archivos antes de ejecutar la comparativa.

Rendimiento esperado en comparación con el rendimiento real

Puedes calcular la capacidad de procesamiento máxima matemática de tu sistema de archivos en función de su capacidad aprovisionada y su nivel de rendimiento. Debido a que la capacidad de almacenamiento se aprovisiona en gibibytes (GiB) y los niveles se clasifican en tebibytes (TiB), primero debes convertir tu capacidad:

(Capacity GiB / 1024) * Tier MBps = Capacidad máxima teórica en MBps

Por ejemplo, una instancia de 216,000 GiB en el nivel de 500 MBps por TiB proporciona matemáticamente 105,469 MBps de capacidad de procesamiento ((216000 / 1024) * 500).

La capacidad de procesamiento máxima observada siempre estará limitada por la capacidad de procesamiento aprovisionada de tu sistema de archivos o por los límites de salida de red combinados de tus máquinas cliente, lo que sea menor.

Entre los motivos comunes por los que los números de tu comparativa no alcanzan las velocidades teóricas, se incluyen los siguientes:

  • Sobrecarga de TCP/IP: La encapsulación de red estándar y los encabezados de paquetes consumen aproximadamente el 5% al 10% del ancho de banda sin procesar. Tu máximo matemático incluye esta sobrecarga, pero la comparativa IOR solo mide la carga útil sin procesar escrita en el disco.

  • Límites de red del cliente: Las máquinas cliente tienen límites estrictos de ancho de banda de salida. Si usas una pequeña cantidad de clientes o nodos, o tipos de máquinas sin redes de nivel 1 habilitadas, los clientes acelerarán la comparativa antes de que el sistema de archivos Managed Lustre alcance su límite.

  • Cambio de contexto de MPI: Si PROCESSES_PER_NODE se establece en un valor superior a la cantidad de núcleos físicos en tus máquinas cliente, la contención de CPU y la sobrecarga de cambio de contexto degradarán artificialmente el rendimiento de E/S de la comparativa.

  • Falta de E/S directa: Si se omite la marca --posix.odirect, los datos pasan por la caché de página de RAM del cliente. Esto introduce cuellos de botella de memoria y sobrecarga de CPU que enmascaran el rendimiento real del almacenamiento de red.

Limpia

Sigue estos pasos para evitar que se apliquen cargos a tu Google Cloud cuenta de por los recursos que usaste en esta página:

  1. Borra los archivos de prueba del volumen de Managed Lustre:

    ssh -i ./id_rsa -o "StrictHostKeyChecking=no" -o UserKnownHostsFile=/dev/null ${SSH_USER}@${HEAD_NODE} "rm -rf /lustre/test"
    
  2. Borra las máquinas cliente de Compute Engine creadas de forma masiva:

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

    Como alternativa, si conoces los nombres exactos o deseas borrarlos de forma individual, haz lo siguiente:

    gcloud compute instances delete CLIENT_PREFIX-0001 CLIENT_PREFIX-0002 ... --zone=ZONE
    
  3. Si creaste una imagen personalizada, puedes borrarla:

    gcloud compute images delete CUSTOM_IMAGE_NAME
    
  4. Si creaste la instancia de Managed Lustre específicamente para esta prueba y ya no la necesitas, bórrala:

    gcloud lustre instances delete INSTANCE_ID --location=LOCATION
    

Soluciona problemas comunes de cuellos de botella de comparativas

Si los resultados de tu comparativa son significativamente más bajos que el nivel de rendimiento de almacenamiento esperado, consulta Soluciona problemas comunes de cuellos de botella.