Teste de performance com clientes do Compute Engine

Esta página descreve como testar a performance de uma instância do Google Cloud Managed Lustre usando clientes do Compute Engine. Ela fornece instruções para medir a performance de um único cliente usando fio e a performance agregada de vários clientes usando a ferramenta de comparação IOR.

Medir a performance de um único cliente

Para testar a performance de leitura e gravação de um único cliente do Compute Engine, use a fio (testador de E/S flexível) ferramenta de linha de comando.

  1. Instale o fio:

    Rocky 8

    sudo dnf install fio -y
    

    Ubuntu 20.04 e 22.04

    sudo apt update
    sudo install fio
    
  2. Execute este 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
    

O teste leva aproximadamente 5 minutos para ser concluído. Quando terminar, os resultados serão exibidos. Dependendo da configuração, você pode esperar uma capacidade de processamento de até a velocidade máxima da rede da VM e milhares de IOPS por TiB.

Medir a performance de vários clientes

Para testar a performance de leitura e gravação do Managed Lustre de vários clientes do Compute Engine, use a ferramenta de comparação IOR. As instruções a seguir mostram como automatizar a configuração do cliente e usar o IOR para testar a E/S agregada de várias máquinas cliente. O IOR usa MPI, um protocolo de passagem de mensagens, para permitir que as várias máquinas cliente se coordenem.

Antes de começar, verifique se o valor mtu da rede está definido como 8896.

Definir variáveis de ambiente e gerar uma chave SSH

Antes de implantar o cluster, gere uma chave SSH na máquina local. Essa chave será distribuída às máquinas cliente durante a criação para ativar a comunicação sem senha para o 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"

Crie o script de inicialização

Salve o conteúdo a seguir em um arquivo chamado install-ior.sh na máquina local. Esse script detecta o sistema operacional, aguarda o lançamento de bloqueios de inicialização, instala com segurança o cliente e as dependências do Lustre, compila uma versão estável do IOR e ativa o sistema de arquivos do Managed Lustre.

Substitua LUSTRE_IP pelo endereço IP da instância do Managed Lustre e FS_NAME pelo nome do sistema de arquivos.

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

Implantar as máquinas cliente

Execute o comando a seguir para criar em massa as máquinas cliente do 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
  • Substitua ZONE e SUBNET por seus valores de implantação específicos.

  • Escolha um MACHINE_TYPE. A performance geral da comparação depende dos tipos de máquinas cliente. Consulte Considerações de performance para informações sobre como escolher tipos de máquinas para obter a melhor capacidade de processamento.

  • Se o tipo de máquina não oferecer suporte à rede TIER_1, exclua a linha --network-performance-configs do comando.

  • Defina o DISK_TYPE como um de hyperdisk-balanced (para um tipo de máquina com um 4 no nome da geração, como c4a ou n4) ou pd-balanced.

  • Especifique o IMAGE_FAMILY e o IMAGE_PROJECT. Os valores aceitos são:

    SO Família de imagens (x86) Família de imagens (ARM) Projeto de imagem
    HPC Rocky Linux 8 hpc-rocky-linux-8 Indisponível 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 Indisponível ubuntu-2404-lts-arm64 ubuntu-os-cloud
  • Especifique o NUM_NODES. Para saturar o sistema de arquivos, a capacidade de rede agregada do cluster precisa exceder a capacidade de processamento provisionada do sistema de arquivos em aproximadamente 20%.

    Para máquinas com a rede de nível 1 ativada, uma única máquina pode enviar entre 25 Gbps e 200 Gbps (aproximadamente 3.000 a 25.000 MBps), dependendo da família de VMs e da contagem de CPUs. Para instâncias padrão, a saída é normalmente limitada a cerca de 2 Gbps por vCPU.

    Por exemplo, se a capacidade da instância do Managed Lustre gerar 100.000 MBps de capacidade de processamento teórica, você precisará de uma saída agregada do cliente de 120.000 MBps (100,000 * 1.2) para saturá-la:

    • Com instâncias padrão: se cada máquina cliente tiver uma saída publicada de 2.000 MBps, provisione pelo menos 60 clientes (120,000 / 2,000).
    • Com a rede de nível 1: se cada máquina cliente tiver uma saída publicada de 10.000 MBps (aproximadamente 80 Gbps), provisione pelo menos 12 clientes (120,000 / 10,000).

Copiar chaves e arquivos

Enquanto aguarda a conclusão dos scripts de inicialização das máquinas cliente, execute os comandos a seguir localmente para configurar automaticamente todos os nós para comunicação entre nós.

  1. Salve os endereços IP privados das máquinas cliente para o arquivo de host MPI e os endereços IP públicos para acesso SSH e SCP às 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. Copie a chave privada para todos os clientes. Isso permite que os nós de worker se comuniquem entre si com segurança durante a comparação:

    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. Designe o nó principal e copie o arquivo de host para ele. Essa será a máquina em que você executará a comparação.

    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
    

Conectar e verificar

  1. Conecte-se ao nó principal:

    ssh -i ./id_rsa -o "StrictHostKeyChecking=no" -o UserKnownHostsFile=/dev/null ${SSH_USER}@${HEAD_NODE}
    
  2. Verifique se o script de inicialização foi concluído e se o sistema de arquivos foi ativado antes de executar a comparação.

    Para verificar os registros de script de inicialização:

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

    Para verificar se o sistema de arquivos está ativado:

    df -h | grep lustre
    

    Se o sistema de arquivos não estiver listado, aguarde mais alguns minutos para que o script de instalação em segundo plano seja concluído. Depois de ativado, ele estará disponível no caminho absoluto /lustre.

Executar a comparação IOR

  1. Somente Rocky Linux e RHEL:carregue o módulo OpenMPI do nó principal.

    if [ -f /etc/profile.d/modules.sh ]; then
        source /etc/profile.d/modules.sh
        module load mpi/openmpi-$(arch)
    fi
    
  2. Crie um diretório de teste e assuma a propriedade:

    sudo mkdir -p /lustre/test
    sudo chown -R $USER:$USER /lustre/test
    
  3. Defina as variáveis de teste:

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

    Em que:

    • NUM_NODES: o número total de máquinas cliente que participam do teste.
    • PROCESSES_PER_NODE: o número de classificações MPI a serem executadas em cada máquina cliente individual. Recomendamos que você comece definindo esse valor para corresponder ao número de núcleos físicos (ou metade do número de vCPUs) nas máquinas cliente. Para tipos de máquinas de alta performance, definir esse valor entre 8 e 16 normalmente gera a melhor capacidade de processamento de rede. Definir esse valor muito alto pode causar sobrecarga de troca de contexto e degradar a performance da comparação.
  4. Execute o comando para iniciar a comparação:

    Rocky Linux e RHEL

    Capacidade de processamento de gravação

    Esse comando grava continuamente por 60 segundos para testar a capacidade de processamento máxima de estado estável. O tamanho do arquivo por tarefa é definido como um limite máximo arbitrariamente grande de 50 TiB para manter as tarefas de gravação até que o timer de 60 segundos expire.

    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

    Capacidade de leitura

    Essa fase lê exatamente a quantidade de dados que foi gravada com sucesso durante o teste de capacidade de gravação de 60 segundos. Embora o tamanho do arquivo por tarefa (-b) seja definido como 50 TiB para corresponder à geometria da fase de gravação, a flag -O stoneWallingWearOut=1 instrui o IOR a parar de ler assim que atingir o limite de dados exato registrado no arquivo de status do 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 gravação

    Esse teste usa tamanhos de transferência pequenos de 4 KiB e tamanhos de arquivo de 8 GiB por tarefa para medir o número máximo de operações de entrada/saída por segundo (IOPS) que o sistema de arquivos pode processar.

    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 leitura

    Para evitar a leitura de um arquivo esparso, esse teste usa dois comandos: uma gravação para criar um arquivo sólido usando tamanhos de transferência de 4 MiB e tamanhos de arquivo de 8 GiB por tarefa, seguida do teste real de IOPS de leitura aleatória de 4 KiB.

    1. Crie o arquivo a ser lido:

      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. Execute o teste de leitura 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

    Capacidade de processamento de gravação

    Esse comando grava continuamente por 60 segundos para testar a capacidade de processamento máxima de estado estável. O tamanho do arquivo por tarefa é definido como um limite máximo arbitrariamente grande de 50 TiB para manter as tarefas de gravação até que o timer de 60 segundos expire.

    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

    Capacidade de leitura

    Essa fase lê exatamente a quantidade de dados que foi gravada com sucesso durante o teste de capacidade de gravação de 60 segundos. Embora o tamanho do arquivo por tarefa (-b) seja definido como 50 TiB para corresponder à geometria da fase de gravação, a flag -O stoneWallingWearOut=1 instrui o IOR a parar de ler assim que atingir o limite de dados exato registrado no arquivo de status do 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 gravação

    Esse teste usa tamanhos de transferência pequenos de 4 KiB e tamanhos de arquivo de 8 GiB por tarefa para medir o número máximo de operações de entrada/saída por segundo (IOPS) que o sistema de arquivos pode processar.

    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 leitura

    Para evitar a leitura de um arquivo esparso, esse teste usa dois comandos: uma gravação para criar um arquivo sólido usando tamanhos de transferência de 4 MiB e tamanhos de arquivo de 8 GiB por tarefa, seguida do teste real de IOPS de leitura aleatória de 4 KiB.

    1. Crie o arquivo a ser lido:

      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. Execute o teste de leitura 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

    As flags mpirun são:

    • --mca plm_rsh_no_tree_spawn 1: desativa a geração de daemons baseada em árvore para melhorar a confiabilidade de inicialização em nós.
    • --mca opal_set_max_sys_limits 1: tenta definir automaticamente os limites do sistema (como o número máximo de arquivos abertos) para os valores permitidos mais altos.
    • --mca plm_rsh_num_concurrent: define o número máximo de conexões SSH simultâneas que mpirun usará ao iniciar daemons de worker.
    • --mca plm_rsh_args ...: ignora a verificação estrita da chave do host para evitar que os prompts SSH interativos bloqueiem a inicialização do processo MPI.
    • --prefix ...: define explicitamente o caminho de instalação do OpenMPI para Rocky Linux e RHEL para que os nós de worker possam encontrar o daemon necessário (orted).
    • --allow-run-as-root: permite que mpirun seja executado como o usuário raiz.
    • --oversubscribe: permite que o MPI programe mais processos em um nó do que há núcleos físicos disponíveis.
    • --map-by node: distribui os processos MPI de maneira uniforme entre os nós disponíveis.
    • --bind-to socket: vincula os processos MPI a soquetes de CPU físicos para otimizar o acesso à memória e a performance do cache.
    • --npernode: o número de processos por nó.
    • --np: o número total de processos MPI a serem iniciados.
    • --hostfile: especifica o arquivo que contém a lista de hosts a serem executados.

    As flags ior são:

    • -a AIO --posix.odirect: usa o mecanismo de E/S assíncrona (AIO) combinado com a E/S direta POSIX. Isso ignora o cache de página da RAM do lado do cliente e força gravações simultâneas não bloqueadoras diretamente nos servidores de armazenamento, garantindo que a comparação meça a performance real do armazenamento de rede em vez de buffers de memória.
    • --aio.max-pending=256: determina o número máximo de operações de E/S assíncronas simultâneas em trânsito por processo.
    • -C: reordena as tarefas para uma performance de leitura ideal.
    • -F: modo de arquivo por processo.
    • -g: usa barreiras para separar as fases de gravação e leitura do teste.
    • -v: gera registros detalhados.
    • -w / -r: instrui o IOR a executar o teste de performance de gravação (-w) ou leitura (-r) .
    • -k: impede que o IOR exclua o arquivo de teste após a gravação, disponibilizando-o para o teste de leitura.
    • -e: executa um fsync após a fase de gravação para garantir que os dados sejam confirmados nas unidades de armazenamento.
    • -z: instrui o IOR a executar E/S de acesso aleatório em vez de acesso sequencial.
    • -s 1: define o número de segmentos como 1.
    • -Q 1: define o deslocamento de tarefa por nó, alinhando as tarefas para que a comparação seja coordenada corretamente em todos os nós.
    • -G 1745405099: codifica o carimbo de data/hora da semente aleatória para que a fase de leitura gere exatamente os mesmos deslocamentos de arquivo aleatórios usados pela fase de gravação.
    • -t: define o tamanho da transferência para cada operação de E/S (por exemplo, 4m para capacidade de processamento, 4k para IOPS).
    • -b: define o tamanho do bloco de destino por processo (por exemplo, 50t para capacidade de processamento, 8g para IOPS) para garantir que o teste não fique sem dados de payload durante a execução cronometrada.
    • -D: restringe a duração do tempo de execução do teste a um número específico de segundos (por exemplo, 60 ou 45). Esse "stonewalling" encerra a comparação de maneira uniforme para capturar uma medição de estado estável real.
    • -O stoneWallingWearOut=1: força todas as linhas de execução simultâneas a continuar gerando carga de gravação contínua durante toda a duração, impedindo que as linhas de execução mais rápidas sejam concluídas mais cedo e diminuam a pressão geral da rede.
    • -O stoneWallingStatusFile=<path>: grava um arquivo de verificação de estado no final da fase de gravação. A fase de leitura subsequente usa esse arquivo para ler apenas os blocos que foram confirmados com sucesso, evitando erros de ponteiro nulo durante as leituras.
    • -o: o caminho para o arquivo de teste no sistema de arquivos do Managed Lustre

Ver os resultados

Quando a comparação for concluída, ela vai mostrar as métricas de performance agregadas de todas as VMs ou pods do cliente diretamente no terminal. Procure a tabela Resultados na parte de baixo da saída para encontrar a capacidade de processamento ou IOPS máximas.

Principais métricas

  • aggregate filesize: a quantidade total de dados gravados ou lidos durante o teste em todos os clientes participantes.

  • bw(MiB/s) / Max Write / Max Read: a métrica mais importante para testes sequenciais. Mostra a largura de banda agregada alcançada pelo sistema de arquivos do Managed Lustre.

  • IOPS: a métrica mais importante para testes de E/S aleatórios. Mostra o número máximo de operações de entrada/saída por segundo.

Exportar resultados para um arquivo

Se você quiser analisar os resultados de maneira programática, inseri-los em um banco de dados ou salvá-los para análise posterior, instrua o IOR a exportar os dados de resumo nos formatos JSON e CSV em vez de apenas imprimi-los na tela.

Para fazer isso, anexe as flags -O ao final da string de comando ior:

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

O diretório de saída precisa existir no sistema de arquivos antes de executar a comparação.

Performance esperada x real

É possível calcular a capacidade de processamento máxima matemática do sistema de arquivos com base na capacidade provisionada e no nível de performance. Como a capacidade de armazenamento é provisionada em gibibytes (GiB) e os níveis são classificados em tebibytes (TiB), primeiro converta a capacidade:

(Capacity GiB / 1024) * Tier MBps = MBps máximos teóricos

Por exemplo, uma instância de 216.000 GiB no nível de 500 MBps por TiB fornece matematicamente 105.469 MBps de capacidade de processamento ((216000 / 1024) * 500).

A capacidade de processamento máxima observada sempre será limitada pela capacidade de processamento provisionada do sistema de arquivos ou pelos limites de saída de rede combinados das máquinas cliente, o que for menor.

Alguns motivos comuns para que os números de comparação não atinjam as velocidades teóricas incluem:

  • Sobrecarga de TCP/IP:a encapsulamento de rede padrão e os cabeçalhos de pacote consomem aproximadamente 5 a 10% da largura de banda bruta. O máximo matemático inclui essa sobrecarga, mas a comparação IOR mede apenas o payload bruto gravado no disco.

  • Limites de rede do cliente:as máquinas cliente têm limites máximos de largura de banda de saída. Se você usar um pequeno número de clientes ou nós ou tipos de máquinas sem a rede de nível 1 ativada, os clientes vão limitar a comparação antes que o sistema de arquivos do Managed Lustre atinja o limite.

  • Troca de contexto MPI:se PROCESSES_PER_NODE estiver definido como um valor maior que o número de núcleos físicos nas máquinas cliente, a contenção de CPU e a sobrecarga de troca de contexto vão degradar artificialmente a performance de E/S da comparação.

  • E/S direta ausente:se a flag --posix.odirect for omitida, os dados vão passar pelo cache de página da RAM do cliente. Isso introduz gargalos de memória e sobrecarga de CPU que mascaram a performance real do armazenamento de rede.

Limpar

Para evitar cobranças na sua Google Cloud conta pelos recursos usados nesta página, siga estas etapas:

  1. Exclua os arquivos de teste do volume do Managed Lustre:

    ssh -i ./id_rsa -o "StrictHostKeyChecking=no" -o UserKnownHostsFile=/dev/null ${SSH_USER}@${HEAD_NODE} "rm -rf /lustre/test"
    
  2. Exclua as máquinas cliente do Compute Engine criadas em massa:

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

    Como alternativa, se você souber os nomes exatos ou quiser excluí-los individualmente:

    gcloud compute instances delete CLIENT_PREFIX-0001 CLIENT_PREFIX-0002 ... --zone=ZONE
    
  3. Se você criou uma imagem personalizada, poderá excluí-la:

    gcloud compute images delete CUSTOM_IMAGE_NAME
    
  4. Se você criou a instância do Managed Lustre especificamente para esse teste e não precisa mais dela, exclua-a:

    gcloud lustre instances delete INSTANCE_ID --location=LOCATION
    

Resolver problemas comuns de gargalos de comparação

Se os resultados da comparação forem significativamente menores do que o nível de performance de armazenamento esperado, consulte Resolver problemas comuns de gargalos.