Executando seu primeiro benchmark usando STREAM

O STREAM mede a largura de banda de memória sustentável, que é essencial para cargas de trabalho associadas à memória, como CFD (dinâmica de fluido computacional), análise de elemento finito e análise de dados. STREAM é um parâmetro de comparação sintético simples que mede a largura de banda de memória para quatro operações de vetor:

Operação DESCRIÇÃO Formula
Copiar Mede as taxas de transferência a(i) = b(i)
Scale Adiciona operações aritméticas simples a(i) = q × b(i)
Adicionar Várias operações de carregamento/repositório a(i) = b(i) + c(i)
Tríade Mais representativo a(i) = b(i) + q × c(i)

O resultado da Tríade é a métrica padrão para comparar a largura de banda de memória entre sistemas.

Tempo de conclusão: 15 a 20 minutos

Pré-requisitos

  • Uma VM HPC do Azure (HBv3, HBv4, HBv5 ou série HX recomendada)
  • Acesso SSH à VM
  • Privilégios raiz ou sudo

Dica

Para obter melhores resultados, use as imagens do Azure HPC Marketplace (AlmaLinux-HPC ou Ubuntu-HPC) que incluem compiladores e bibliotecas otimizados.

Resultados esperados pela família de VMs

Use estes valores para validar seus resultados:

Série VM Tríade STREAM (GB/s) Anotações
HBv5 (com HBM) ~7.000 Usa memória HBM
HBv4 ~650-780 Memória DDR5
HBv3 ~330-350 Memória DDR4
HBv2 ~260 Memória DDR4

Se os resultados forem significativamente menores (mais de 10% abaixo), verifique sua configuração.

Etapa 1: Conectar-se à VM

Conecte-se via SSH à HPC VM:

ssh azureuser@<vm-public-ip>

Ou conecte-se através do seu nó de login do Slurm, caso esteja usando um cluster.

Etapa 2: Instalar dependências

As imagens de HPC do Azure incluem os compiladores necessários. Verifique se o GCC está disponível:

gcc --version

Opção B: instalação manual

Se estiver usando uma imagem padrão, instale as ferramentas de build:

# AlmaLinux/RHEL
sudo dnf groupinstall "Development Tools" -y

# Ubuntu
sudo apt update && sudo apt install build-essential -y

Etapa 3: Baixar e compilar STREAM

Clone o repositório de benchmarking do Azure, que inclui configurações de STREAM otimizadas:

# Create working directory
mkdir -p ~/benchmarks && cd ~/benchmarks

# Clone Azure benchmarking repository
git clone https://github.com/Azure/woc-benchmarking.git
cd woc-benchmarking/apps/hpc/stream

Como alternativa, baixe o STREAM diretamente:

mkdir -p ~/benchmarks/stream && cd ~/benchmarks/stream
wget https://www.cs.virginia.edu/stream/FTP/Code/stream.c

Compile com otimizações para processadores AMD EPYC (usados na série HB):

gcc -O3 -march=znver3 -fopenmp -DSTREAM_ARRAY_SIZE=800000000 \
    -DNTIMES=20 stream.c -o stream

Sinalizadores do compilador explicados:

Flag Propósito
-O3 Nível máximo de otimização
-march=znver3 Otimizar para a arquitetura AMD Zen 3/4
-fopenmp Habilite o OpenMP para multithreading.
-DSTREAM_ARRAY_SIZE=800000000 Tamanho da matriz (aproximadamente 6 GB por matriz, total de 18 GB)
-DNTIMES=20 Número de iterações

Importante

O tamanho da matriz deve ser grande o suficiente para que os dados não caibam no cache. Para HBv4/HBv5 com cache L3 de 1,5 GB, use pelo menos 800M de elementos.

Etapa 4: Configurar afinidade de thread

A fixação correta do thread é fundamental para obter resultados precisos. Definir variáveis de ambiente OpenMP:

# Get number of physical cores
NCORES=$(lscpu | grep "^Core(s) per socket:" | awk '{print $4}')
NSOCKETS=$(lscpu | grep "^Socket(s):" | awk '{print $2}')
TOTAL_CORES=$((NCORES * NSOCKETS))

echo "Total physical cores: $TOTAL_CORES"

# Set OpenMP configuration
export OMP_NUM_THREADS=$TOTAL_CORES
export OMP_PROC_BIND=spread
export OMP_PLACES=cores

Para HBv4 (176 núcleos):

export OMP_NUM_THREADS=176
export OMP_PROC_BIND=spread
export OMP_PLACES=cores

Para HBv5 (configuração padrão):

export OMP_NUM_THREADS=176
export OMP_PROC_BIND=spread
export OMP_PLACES=cores

Etapa 5: Executar o parâmetro de comparação

Executar STREAM:

./stream

Saída de exemplo (HBv4):

-------------------------------------------------------------
STREAM version $Revision: 5.10 $
-------------------------------------------------------------
This system uses 8 bytes per array element.
-------------------------------------------------------------
Array size = 800000000 (elements), Offset = 0 (elements)
Memory per array = 6103.5 MiB (= 5.96 GiB).
Total memory required = 18310.5 MiB (= 17.88 GiB).
Each kernel will be executed 20 times.
-------------------------------------------------------------
Number of Threads requested = 176
Number of Threads counted = 176
-------------------------------------------------------------
Function    Best Rate MB/s  Avg time     Min time     Max time
Copy:          753284.2     0.017157     0.016966     0.018884
Scale:         707935.3     0.018260     0.018045     0.019629
Add:           756972.9     0.025508     0.025318     0.027311
Triad:         757820.9     0.025464     0.025290     0.027212
-------------------------------------------------------------

A Melhor Taxa de Tríade (757.820,9 MB/s = ~740 GB/s) é o resultado chave.

Etapa 6: Validar resultados

Compare o resultado da Tríade com os valores esperados:

# Quick validation script
TRIAD_RESULT=757820  # Replace with your result in MB/s
VM_TYPE="HBv4"       # HBv2, HBv3, HBv4, or HBv5

case $VM_TYPE in
    "HBv5") EXPECTED=7000000 ;;
    "HBv4") EXPECTED=700000 ;;
    "HBv3") EXPECTED=330000 ;;
    "HBv2") EXPECTED=260000 ;;
esac

PERCENT=$(echo "scale=1; $TRIAD_RESULT * 100 / $EXPECTED" | bc)
echo "Achieved $PERCENT% of expected bandwidth"

Interpretação de resultados:

Conquista Interpretação
95-105% Excelente – VM com desempenho conforme o esperado
85-95% Otimização boa – pequenas melhorias possíveis
70-85% Investigar – Verificar afinidade de thread, NUMA
<70% Problema – Verificar a configuração

Etapa 7: Executar em vários domínios NUMA (avançado)

Para análise detalhada do NUMA, execute STREAM por domínio NUMA:

# Check NUMA topology
numactl --hardware

# Run on NUMA node 0 only
numactl --cpunodebind=0 --membind=0 \
    OMP_NUM_THREADS=22 OMP_PROC_BIND=spread OMP_PLACES=cores ./stream

# Run on all NUMA domains (default full-node run)
numactl --interleave=all \
    OMP_NUM_THREADS=176 OMP_PROC_BIND=spread OMP_PLACES=cores ./stream

Resolução de problemas

Resultados de baixa largura de banda

Sintoma: Resultados significativamente abaixo dos valores esperados

Soluções:

  1. Verifique a contagem de threads:

    echo $OMP_NUM_THREADS
    # Should match physical core count
    
  2. Verifique a associação de thread:

    export OMP_DISPLAY_ENV=TRUE
    ./stream 2>&1 | head -20
    
  3. Verifique se há escala de frequência de CPU:

    cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
    # Should be "performance" for benchmarking
    
  4. Verifique a política de memória NUMA:

    numactl --show
    

Tamanho da matriz insuficiente

Sintoma: Resultados acima do esperado (medindo cache, não memória)

Solução: Aumentar STREAM_ARRAY_SIZE no tempo de compilação. A memória total usada deve ser de pelo menos 4× o tamanho do cache L3.

# Recompile with larger array
gcc -O3 -march=znver3 -fopenmp -DSTREAM_ARRAY_SIZE=1000000000 \
    -DNTIMES=20 stream.c -o stream

Resultados inconsistentes

Sintoma: grande variação entre execuções

Soluções:

  1. Verifique se nenhum outro processo está em execução:

    top -b -n 1 | head -20
    
  2. Execute mais iterações:

    # Recompile with more iterations
    gcc -O3 -march=znver3 -fopenmp -DSTREAM_ARRAY_SIZE=800000000 \
        -DNTIMES=50 stream.c -o stream
    

Executando STREAM em um trabalho do Slurm

Se estiver usando um cluster Slurm, crie um script de trabalho:

cat << 'EOF' > stream-job.sh
#!/bin/bash
#SBATCH --job-name=stream
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=176
#SBATCH --time=00:10:00
#SBATCH --partition=hpc
#SBATCH --exclusive

# Set thread configuration
export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK
export OMP_PROC_BIND=spread
export OMP_PLACES=cores

# Run STREAM
cd ~/benchmarks/woc-benchmarking/apps/hpc/stream
./stream
EOF

sbatch stream-job.sh

Automatizar com os scripts de benchmarking do Azure

O repositório woc-benchmarking do Azure inclui scripts de automação:

cd ~/benchmarks/woc-benchmarking/apps/hpc/stream

# View available scripts
ls -la

# Run automated benchmark (if available)
./run_stream.sh