Test delle prestazioni con i client Compute Engine

Questa pagina descrive come testare il rendimento di un'istanza Google Cloud Managed Lustre utilizzando i client Compute Engine. Fornisce istruzioni per misurare il rendimento di un singolo client utilizzando fio e il rendimento aggregato di più client utilizzando lo strumento di benchmarking IOR.

Misurare il rendimento di un singolo client

Per testare il rendimento di lettura e scrittura da un singolo client Compute Engine, utilizza lo strumento da riga di comando fio (Flexible I/O tester).

  1. Installa fio:

    Rocky 8

    sudo dnf install fio -y
    

    Ubuntu 20.04 e 22.04

    sudo apt update
    sudo install fio
    
  2. Esegui questo 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
    

Il completamento del test richiede circa 5 minuti. Al termine, vengono visualizzati i risultati. A seconda della configurazione, puoi prevedere un throughput fino a alla velocità di rete massima della VM e migliaia di IOPS per TiB.

Misurare il rendimento di più client

Per testare il rendimento di lettura e scrittura di Managed Lustre da più client Compute Engine, utilizza lo strumento di benchmarking IOR. Le seguenti istruzioni mostrano come automatizzare la configurazione del client e utilizzare IOR per testare l'I/O aggregato da più macchine client. IOR utilizza MPI, un protocollo di passaggio dei messaggi, per consentire alle più macchine client di coordinarsi tra loro.

Prima di iniziare, assicurati che il valore mtu della rete sia impostato su 8896.

Impostare le variabili di ambiente e generare una chiave SSH

Prima di eseguire il deployment del cluster, genera una chiave SSH sulla macchina locale. Questa chiave verrà distribuita alle macchine client durante la creazione per abilitare la comunicazione senza password per 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"

Creare lo script di avvio

Salva i seguenti contenuti in un file denominato install-ior.sh sulla macchina locale. Questo script rileva il sistema operativo, attende il rilascio dei blocchi di avvio, installa in modo sicuro il client Lustre e le dipendenze, compila una release stabile di IOR e monta il file system Managed Lustre.

Sostituisci LUSTRE_IP con l'indirizzo IP dell'istanza Managed Lustre e FS_NAME con il nome del file system.

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

Eseguire il deployment delle macchine client

Esegui il comando seguente per creare in blocco le macchine client 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
  • Sostituisci ZONE e SUBNET con i valori di deployment specifici.

  • Scegli un MACHINE_TYPE. Il rendimento complessivo del benchmark dipende dai tipi di macchine client. Per informazioni sulla scelta dei tipi di macchine per ottenere il miglior throughput, consulta Considerazioni sul rendimento.

  • Se il tipo di macchina non supporta la rete TIER_1, elimina la riga --network-performance-configs dal comando.

  • Imposta DISK_TYPE su uno di hyperdisk-balanced (per un tipo di macchina con un 4 nel nome della generazione, ad esempio c4a o n4) o pd-balanced.

  • Specifica IMAGE_FAMILY e IMAGE_PROJECT. I valori supportati sono:

    Sistema operativo Famiglia di immagini (x86) Famiglia di immagini (ARM) Progetto di immagini
    HPC Rocky Linux 8 hpc-rocky-linux-8 Non supportata 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 Non supportata ubuntu-2404-lts-arm64 ubuntu-os-cloud
  • Specifica NUM_NODES. Per saturare il file system, la capacità di rete aggregata del cluster deve superare il throughput di cui è stato eseguito il provisioning del file system di circa il 20%.

    Per le macchine con la rete Tier 1 abilitata, una singola macchina può inviare tra 25 Gbps e 200 Gbps (circa 3000-25.000 MBps), a seconda della famiglia di VM e del numero di CPU. Per le istanze standard, la trasmissione dei dati in uscita è in genere limitata a circa 2 Gbps per vCPU.

    Ad esempio, se la capacità dell'istanza Managed Lustre produce 100.000 MBps di throughput teorico, è necessaria una trasmissione dei dati in uscita aggregata del client di 120.000 MBps (100,000 * 1.2) per saturarla:

    • Con le istanze standard: se ogni macchina client ha una trasmissione dei dati in uscita pubblicata di 2000 MBps, devi eseguire il provisioning di almeno 60 client (120,000 / 2,000).
    • Con la rete Tier 1: se ogni macchina client ha una trasmissione dei dati in uscita pubblicata di 10.000 MBps (circa 80 Gbps), devi eseguire il provisioning di almeno 12 client (120,000 / 10,000).

Copiare chiavi e file

Mentre aspetti che le macchine client completino gli script di avvio, esegui i seguenti comandi in locale per configurare automaticamente tutti i nodi per la comunicazione tra nodi.

  1. Salva gli indirizzi IP privati delle macchine client per il file host MPI e gli indirizzi IP pubblici per l'accesso SSH e SCP alle macchine client:

    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 chiave privata su tutti i client. In questo modo, i nodi worker possono comunicare tra loro in modo sicuro durante il benchmark:

    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 il nodo principale e copia il file host. Questa sarà la macchina da cui esegui il benchmark.

    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
    

Connettersi e verificare

  1. Connettiti al nodo principale:

    ssh -i ./id_rsa -o "StrictHostKeyChecking=no" -o UserKnownHostsFile=/dev/null ${SSH_USER}@${HEAD_NODE}
    
  2. Prima di eseguire il benchmark, verifica che lo script di avvio sia stato completato e che il file system sia stato montato correttamente.

    Per controllare i log dello script di avvio:

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

    Per verificare che il file system sia montato:

    df -h | grep lustre
    

    Se il file system non è elencato, attendi qualche minuto in più per il completamento dello script di installazione in background. Una volta montato, sarà disponibile nel percorso assoluto /lustre.

Eseguire il benchmark IOR

  1. Solo Rocky Linux e RHEL: carica il modulo OpenMPI dal nodo principale.

    if [ -f /etc/profile.d/modules.sh ]; then
        source /etc/profile.d/modules.sh
        module load mpi/openmpi-$(arch)
    fi
    
  2. Crea una directory di test e prendine la proprietà:

    sudo mkdir -p /lustre/test
    sudo chown -R $USER:$USER /lustre/test
    
  3. Definisci le variabili di test:

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

    Dove:

    • NUM_NODES: il numero totale di macchine client che partecipano al test.
    • PROCESSES_PER_NODE: il numero di ranghi MPI da eseguire su ogni singola macchina client. Ti consigliamo di iniziare impostando questo valore in modo che corrisponda al numero di core fisici (o alla metà del numero di vCPU) sulle macchine client. Per i tipi di macchine ad alte prestazioni, l'impostazione di questo valore tra 8 e 16 in genere produce il miglior throughput di rete. Se imposti un valore troppo alto, puoi causare un overhead di cambio di contesto e ridurre il rendimento del benchmark.
  4. Esegui il comando per avviare il benchmark:

    Rocky Linux e RHEL

    Throughput di scrittura

    Questo comando scrive continuamente per 60 secondi per testare il throughput di stato stabile di picco. La dimensione del file per attività è impostata su un limite massimo di 50 TiB arbitrariamente grande per mantenere le attività di scrittura fino alla scadenza del timer di 60 secondi.

    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

    Throughput di lettura

    Questa fase legge esattamente la quantità di dati scritti correttamente durante il test del throughput di scrittura di 60 secondi. Sebbene la dimensione del file per attività (-b) sia impostata su 50 TiB per corrispondere alla geometria della fase di scrittura, il flag -O stoneWallingWearOut=1 indica a IOR di interrompere la lettura non appena raggiunge il limite esatto dei dati registrato nel file di stato di 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 di scrittura

    Questo test utilizza dimensioni di trasferimento ridotte di 4 KiB e dimensioni di file per attività di 8 GiB per misurare il numero massimo di operazioni di input/output al secondo (IOPS) che il file system può gestire.

    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 di lettura

    Per evitare di leggere da un file sparse, questo test utilizza due comandi: una scrittura per creare un file solido utilizzando dimensioni di trasferimento di 4 MiB e dimensioni di file per attività di 8 GiB, seguita dal test IOPS di lettura casuale di 4 KiB effettivo.

    1. Crea il file da leggere:

      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. Esegui il test di lettura 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

    Throughput di scrittura

    Questo comando scrive continuamente per 60 secondi per testare il throughput di stato stabile di picco. La dimensione del file per attività è impostata su un limite massimo di 50 TiB arbitrariamente grande per mantenere le attività di scrittura fino alla scadenza del timer di 60 secondi.

    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

    Throughput di lettura

    Questa fase legge esattamente la quantità di dati scritti correttamente durante il test del throughput di scrittura di 60 secondi. Sebbene la dimensione del file per attività (-b) sia impostata su 50 TiB per corrispondere alla geometria della fase di scrittura, il flag -O stoneWallingWearOut=1 indica a IOR di interrompere la lettura non appena raggiunge il limite esatto dei dati registrato nel file di stato di 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 di scrittura

    Questo test utilizza dimensioni di trasferimento ridotte di 4 KiB e dimensioni di file per attività di 8 GiB per misurare il numero massimo di operazioni di input/output al secondo (IOPS) che il file system può gestire.

    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 di lettura

    Per evitare di leggere da un file sparse, questo test utilizza due comandi: una scrittura per creare un file solido utilizzando dimensioni di trasferimento di 4 MiB e dimensioni di file per attività di 8 GiB, seguita dal test IOPS di lettura casuale di 4 KiB effettivo.

    1. Crea il file da leggere:

      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. Esegui il test di lettura 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

    I flag mpirun sono:

    • --mca plm_rsh_no_tree_spawn 1: disabilita la generazione di daemon basata su albero per migliorare l'affidabilità di avvio tra i nodi.
    • --mca opal_set_max_sys_limits 1: tenta automaticamente di impostare i limiti di sistema sui valori massimi consentiti (ad esempio il numero massimo di file aperti).
    • --mca plm_rsh_num_concurrent: imposta il numero massimo di connessioni SSH simultanee che mpirun utilizzerà durante l'avvio dei daemon worker.
    • --mca plm_rsh_args ...: ignora il controllo rigoroso della chiave host per impedire che le richieste SSH interattive blocchino l'avvio del processo MPI.
    • --prefix ...: definisce in modo esplicito il percorso di installazione di OpenMPI per Rocky Linux e RHEL in modo che i nodi worker possano trovare il daemon richiesto (orted).
    • --allow-run-as-root: consente a mpirun di essere eseguito come utente root.
    • --oversubscribe: consente a MPI di pianificare più processi su un nodo rispetto ai core fisici disponibili.
    • --map-by node: distribuisce i processi MPI in modo round robin uniformemente tra i nodi disponibili.
    • --bind-to socket: associa i processi MPI ai socket CPU fisici per ottimizzare l'accesso alla memoria e il rendimento della cache.
    • --npernode: il numero di processi per nodo.
    • --np: il numero totale di processi MPI da avviare.
    • --hostfile: specifica il file contenente l'elenco degli host su cui eseguire.

    I flag ior sono:

    • -a AIO --posix.odirect: utilizza il motore I/O asincrono (AIO) combinato con I/O diretto POSIX. In questo modo viene ignorata la cache delle pagine RAM lato client e le scritture simultanee non bloccanti vengono forzate direttamente sui server di archiviazione, garantendo che il benchmark misuri il rendimento effettivo dell'archiviazione di rete anziché i buffer di memoria.
    • --aio.max-pending=256: determina il numero massimo di operazioni di I/O asincrono simultanee in corso per processo.
    • -C: riordina le attività per un rendimento di lettura ottimale.
    • -F: modalità file per processo.
    • -g: utilizza le barriere per separare le fasi di scrittura e lettura del test.
    • -v: output di log dettagliati.
    • -w / -r: indica a IOR di eseguire il test di rendimento di scrittura (-w) o lettura (-r) .
    • -k: impedisce a IOR di eliminare il file di test dopo la scrittura, rendendolo disponibile per il test di lettura.
    • -e: esegue un fsync dopo la fase di scrittura per garantire che i dati vengano salvati sulle unità di archiviazione.
    • -z: indica a IOR di eseguire I/O ad accesso casuale anziché accesso sequenziale.
    • -s 1: imposta il numero di segmenti su 1.
    • -Q 1: imposta l'offset attività per nodo, allineando le attività in modo che il benchmark si coordini correttamente su tutti i nodi.
    • -G 1745405099: codifica in modo rigido il timestamp del seme casuale in modo che la fase di lettura generi gli stessi offset di file casuali utilizzati dalla fase di scrittura.
    • -t: imposta la dimensione del trasferimento per ogni operazione di I/O (ad es. 4m per throughput, 4k per IOPS).
    • -b: imposta la dimensione del blocco target per processo (ad es. 50t per il throughput, 8g per IOPS) per garantire che il test non esaurisca i dati del payload durante l'esecuzione a tempo.
    • -D: limita la durata di esecuzione del test a un numero specifico di secondi (ad es. 60 o 45). Questo "stonewalling" termina il benchmark in modo uniforme per acquisire una misurazione di stato stabile effettiva.
    • -O stoneWallingWearOut=1: forza tutti i thread simultanei a continuare a generare un carico di scrittura continuo per l'intera durata, impedendo ai thread più veloci di completarsi in anticipo e di ridurre la pressione di rete complessiva.
    • -O stoneWallingStatusFile=<path>: scrive un file di verifica dello stato alla fine della fase di scrittura. La fase di lettura successiva utilizza questo file per leggere solo i blocchi di cui è stato eseguito il commit correttamente, evitando errori di puntatore null durante le letture.
    • -o: il percorso del file di test nel file system Managed Lustre file system.

Visualizzare i risultati

Al termine del benchmark, vengono visualizzate le metriche sul rendimento aggregate di tutte le VM o i pod client direttamente nel terminale. Cerca la tabella Risultati nella parte inferiore dell'output per trovare il throughput o le IOPS massime.

Metriche chiave

  • aggregate filesize: la quantità totale di dati scritti o letti durante il test su tutti i client partecipanti.

  • bw(MiB/s) / Max Write / Max Read: la metrica più importante per i test sequenziali. Mostra la larghezza di banda aggregata raggiunta dal file system Managed Lustre.

  • IOPS: la metrica più importante per i test di I/O casuale. Mostra il numero massimo di operazioni di input/output al secondo.

Esportare i risultati in un file

Se vuoi analizzare i risultati a livello di programmazione, inserirli in un database o salvarli per un'analisi successiva, puoi indicare a IOR di esportare i dati di riepilogo in formato JSON e CSV anziché stamparli sullo schermo.

Per farlo, aggiungi i flag -O alla fine della stringa del comando ior:

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

La directory di output deve esistere nel file system prima di eseguire il benchmark.

Rendimento previsto rispetto a quello reale

Puoi calcolare il throughput massimo matematico del file system in base alla capacità di cui è stato eseguito il provisioning e al livello di rendimento. Poiché la capacità di archiviazione viene sottoposta a provisioning in gibibyte (GiB) e i livelli sono valutati in tebibyte (TiB), devi prima convertire la capacità:

(Capacity GiB / 1024) * Tier MBps = MBps massimi teorici

Ad esempio, un'istanza 216.000 GiB nel livello 500 MBps per TiB fornisce matematicamente 105.469 MBps di throughput ((216000 / 1024) * 500).

Il throughput massimo osservato sarà sempre limitato dalla capacità di throughput di cui è stato eseguito il provisioning del file system o dai limiti di trasmissione dei dati in uscita di rete combinati delle macchine client, a seconda di quale sia inferiore.

Ecco alcuni motivi comuni per cui i numeri di benchmark potrebbero non raggiungere le velocità teoriche:

  • Overhead TCP/IP: l'incapsulamento di rete standard e le intestazioni dei pacchetti consumano circa il 5-10% della larghezza di banda non elaborata. Il massimo matematico include questo overhead, ma il benchmark IOR misura solo il payload non elaborato scritto sul disco.

  • Limiti di rete client: le macchine client hanno limiti rigidi di larghezza di banda di trasmissione dei dati in uscita. Se utilizzi un numero ridotto di client o nodi o tipi di macchine senza la rete Tier 1 abilitata, i client limiteranno il benchmark prima che il file system Managed Lustre raggiunga il suo limite.

  • Cambio di contesto MPI: se PROCESSES_PER_NODE è impostato su un valore superiore al numero di core fisici sulle macchine client, la contesa della CPU e l'overhead di cambio di contesto ridurranno artificialmente il rendimento I/O del benchmark.

  • I/O diretto mancante: se il flag --posix.odirect viene omesso, i dati passano attraverso la cache delle pagine RAM del client. Ciò introduce colli di bottiglia della memoria e overhead della CPU che mascherano il rendimento effettivo dell'archiviazione di rete.

Liberare spazio

Per evitare che al tuo Google Cloud account vengano addebitati costi relativi alle risorse utilizzate in questa pagina, segui questi passaggi:

  1. Elimina i file di test dal volume Managed Lustre:

    ssh -i ./id_rsa -o "StrictHostKeyChecking=no" -o UserKnownHostsFile=/dev/null ${SSH_USER}@${HEAD_NODE} "rm -rf /lustre/test"
    
  2. Elimina le macchine client Compute Engine create in blocco:

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

    In alternativa, se conosci i nomi esatti o vuoi eliminarli singolarmente:

    gcloud compute instances delete CLIENT_PREFIX-0001 CLIENT_PREFIX-0002 ... --zone=ZONE
    
  3. Se hai creato un'immagine personalizzata, puoi eliminarla:

    gcloud compute images delete CUSTOM_IMAGE_NAME
    
  4. Se hai creato l'istanza Managed Lustre appositamente per questo test e non ne hai più bisogno, eliminala:

    gcloud lustre instances delete INSTANCE_ID --location=LOCATION
    

Risolvere i problemi relativi ai colli di bottiglia comuni del benchmarking

Se i risultati del benchmark sono significativamente inferiori al livello di rendimento dell'archiviazione previsto, consulta Risolvere i problemi relativi ai colli di bottiglia comuni.