3. Exemplos de Aplicações

3.1. Introdução

Os exemplos a seguir demonstram a execução de algumas aplicações com CPUs ou GPUs. Essas opções serão indicadas entre parênteses. Alguns exemplos também utilizam containers otimizados da NVIDIA.

Importante

Todos os scripts dos jobs mostrados aqui estão disponíveis no diretório /sw/share/jobs/ no cluster sismom. Isso facilita a reutilização dos mesmos.

3.2. MPI (CPUs)

Usando o código abaixo de Hello World como exemplo.

// Author: Wes Kendall
// Copyright 2011 www.mpitutorial.com
// This code is provided freely with the tutorials on mpitutorial.com. Feel
// free to modify it for your own use. Any distribution of the code must
// either provide a link to www.mpitutorial.com or keep this header intact.
//
// An intro MPI hello world program that uses MPI_Init, MPI_Comm_size,
// MPI_Comm_rank, MPI_Finalize, and MPI_Get_processor_name.
//
#include <mpi.h>
#include <stdio.h>

int main(int argc, char** argv) {
  // Initialize the MPI environment. The two arguments to MPI Init are not
  // currently used by MPI implementations, but are there in case future
  // implementations might need the arguments.
  MPI_Init(NULL, NULL);

  // Get the number of processes
  int world_size;
  MPI_Comm_size(MPI_COMM_WORLD, &world_size);

  // Get the rank of the process
  int world_rank;
  MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);

  // Get the name of the processor
  char processor_name[MPI_MAX_PROCESSOR_NAME];
  int name_len;
  MPI_Get_processor_name(processor_name, &name_len);

  // Print off a hello world message
  printf("Hello world from processor %s, rank %d out of %d processors\n",
        processor_name, world_rank, world_size);

  // Finalize the MPI environment. No more MPI calls can be made after this
  MPI_Finalize();
}

O cluster possui duas bibliotecas de MPI, que seriam o MVAPICH e o OpenMPI. A seguir são mostrados os jobs para executar o programa acima em cada uma das bibliotecas.

3.2.1. MVAPICH

O script de submissão define a quantidade de nós de processamento (2) e a quantidade de processos (192 no total e 96 por nó). Além disso, carrega o módulo do MPI e a execução do mesmo. Esses itens estão em destaque no script abaixo.

#!/bin/bash
#SBATCH -J mvapich
#SBATCH -p cpuq
#SBATCH --nodes 2
#SBATCH --ntasks-per-node=96
#SBATCH --ntasks 192
#SBATCH -o %x-%j.out

# modules
module load mvapich
cd $SLURM_SUBMIT_DIR

mpirun ./mpi_hello_world_mvapich

Importante

É essencial garantir que o mesmo module utilizado na compilação seja incluído no job de execução. No caso do MPI, o cluster possui múltiplas bibliotecas, e a compilação com uma biblioteca e a execução com outra resultará em falha durante o processamento.

Seguem os comandos da compilação, submissão do job e para ver a saída do programa. O do arquivo de saída é mvapich2-10.out, onde mpi-test e 10 correspondem respectivamente o nome do job e o JobId informado após o comando sbatch.

3.2.2. OpenMPI

Segue abaixo o script usando o OpenMPI para executar o mesmo programa.

#!/bin/bash
#SBATCH -J openmpi
#SBATCH -p cpuq
#SBATCH --nodes 2
#SBATCH --ntasks-per-node=96
#SBATCH --ntasks 192
#SBATCH -o %x-%j.out
#SBATCH --cpus-per-task=1

# modules
module load openmpi
cd $SLURM_SUBMIT_DIR

#run
srun --mpi=pmix ./mpi_hello_openmpi

Nota

Como alternativa, o MPI pode ser utilizado por meio do comando srun do SLURM. A linha 8 especifica a quantidade de tasks por CPU, enquanto a linha 11 realiza o carregamento do módulo openmpi. Por fim, a linha 15 apresenta o comando de execução propriamente dito.

[user1@sismom-1 mpi]$ module load purge
[user1@sismom-1 mpi]$ module load openmpi
[user1@sismom-1 mpi]$ mpicc -o mpi_hello_world_mvapich2 mpi_hello_world.c
[user1@sismom-1 mpi]$ sbatch mpi.job
Submitted batch job 10
[user1@sismom-1 mpi]$ cat mvapich2-10.out
Hello world from processor sismom-1, rank 1 out of 192 processors
Hello world from processor sismom-1, rank 2 out of 192 processors
Hello world from processor sismom-2, rank 135 out of 192 processors
Hello world from processor sismom-1, rank 18 out of 192 processors
Hello world from processor sismom-2, rank 150 out of 192 processors
Hello world from processor sismom-1, rank 0 out of 192 processors
Hello world from processor sismom-2, rank 128 out of 192 processors
...

Atenção

Este job demonstra o uso de múltiplos nós de processamento. É importante notar que, na prática, raramente é necessário utilizar mais de um nó, pois cada um oferece 96 cores e 192 threads. O uso de múltiplos nós só se justifica quando o programa é capaz de aproveitar eficientemente o aumento no número de processos.

3.3. Pytorch (GPUs)

Executando o script test-pt.py em python para usar o Pytorch.

import torch
print('PyTorch version:', torch.__version__)
print('CUDA available:', torch.cuda.is_available())
assert torch.cuda.is_available()
print('Number of devices:', torch.cuda.device_count())
assert torch.cuda.device_count() > 0
print('Devices:')
for device in range(torch.cuda.device_count()):
   print(f'{device}:', torch.cuda.get_device_name(device))

Abaixo segue o conteúdo do job usado pytorch.job.

#!/bin/bash
#SBATCH --nodes=1
#SBATCH --ntasks=56
#SBATCH -J pytorch
#SBATCH -o %x-%j.out
#SBATCH -p gpuq
#SBATCH --gpus=2
#SBATCH --time=3:00:00

# list nodes
echo $SLURM_JOB_NODELIST
# change dir
cd $SLURM_SUBMIT_DIR

# apptainer/singularity
PYTORCH="/sw/containers/pytorch_latest.sif"
apptainer run --nv ${PYTORCH} python test-pt.py

Nota

Recomenda-se que seja feito um link simbólico da última versão do container para o nome pytorch_latest.sif. Dessa forma, não é necessário mudar o script quando houver alguma atualização do container. Entretanto, se for necessário executar com alguma versão especifica, basta incluir a versão.

Saída do job, omitindo alguns comentários.

gpu01

=============
== PyTorch ==
=============

NVIDIA Release 25.11 (build 231036167)
PyTorch Version 2.10.0a0+b558c98
Container image Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
...

PyTorch version: 2.10.0a0+b558c986e8.nv25.11
CUDA available: True
Number of devices: 2
Devices:
0: NVIDIA H200
1: NVIDIA H200

3.4. Tensorflow (GPUs)

Executando o script test-tf.job em python para usar o TensorFlow.

import tensorflow as tf

physical_devices = tf.config.list_physical_devices('GPU')
print("Num GPUs:", len(physical_devices))

Abaixo segue o conteúdo do job usado tf.job.

#!/bin/bash
#SBATCH --nodes=1
#SBATCH --ntasks=96
#SBATCH -J tensorflow
#SBATCH -o %x-%j.out
#SBATCH -p gpuq
#SBATCH --gpus=2
#SBATCH --time=3:00:00

# list nodes
echo $SLURM_JOB_NODELIST
# change dir
cd $SLURM_SUBMIT_DIR

# apptainer/singularity
TF="/sw/containers/tensorflow_25.02-tf2-py3.sif"
apptainer run --nv ${TF} python test-tf.py

Saída do job, omitindo alguns comentários.

gpu01

================
== TensorFlow ==
================

NVIDIA Release 25.02-tf2 (build 143088766)
TensorFlow Version 2.17.0
Container image Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
Copyright 2017-2024 The TensorFlow Authors.  All rights reserved.
...
Num GPUs: 2

3.5. CUDA

Existem duas formas de compilar códigos CUDA: via módulo nvhpc ou por meio de containers. Para a primeira opção, basta carregar o módulo conforme demonstrado abaixo.

user1@sismom-1:~$ module load nvhpc/25.11
user1@sismom-1:~$ nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2025 NVIDIA Corporation
Built on Wed_Aug_20_01:58:59_PM_PDT_2025
Cuda compilation tools, release 13.0, V13.0.88
Build cuda_13.0.r13.0/compiler.36424714_0

Alternativamente, a compilação pode ser realizada em ambiente de container com suporte a GPU. Neste cenário, adota-se a imagem devel para a compilação e a versão runtime para a execução, otimizando o ambiente final.

user1@sismom-1:~$ salloc -p gpuq --gpus=1
salloc: Granted job allocation 25
salloc: Nodes gpu01 are ready for job

user1@gpu01:~$ nvidia-smi
Fri Dec 19 20:29:29 2025
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 580.95.05              Driver Version: 580.95.05      CUDA Version: 13.0     |
+-----------------------------------------+------------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA H200                    Off |   00000000:0A:00.0 Off |                    0 |
| N/A   31C    P0             77W /  700W |       0MiB / 143771MiB |      0%      Default |
|                                         |                        |             Disabled |
+-----------------------------------------+------------------------+----------------------+
+-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI              PID   Type   Process name                        GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|  No running processes found                                                             |
+-----------------------------------------------------------------------------------------+

user1@gpu01:~$ apptainer exec /sw/containers/cuda_13.0.2-cudnn-devel-ubuntu24.04.sif nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2025 NVIDIA Corporation
Built on Wed_Aug_20_01:58:59_PM_PDT_2025
Cuda compilation tools, release 13.0, V13.0.88
Build cuda_13.0.r13.0/compiler.36424714_0
user1@sismom-1:~$

Nota

Recomenda-se o uso da imagem de runtime para a execução, pois, por serem mais leves, essas imagens reduzem a sobrecarga no sistema de arquivos e no cache do host. Neste caso, a imagem seria cuda_13.0.2-cudnn-runtime-ubuntu24.04.sif. Observe a diferença de tamanho das duas imagens.

user1@gpu01:~$ ls -lh /sw/containers/cuda_13.0.2-cudnn-*
-rwxr-xr-x 1 root root 4.0G Dec 10 19:31 /sw/containers/cuda_13.0.2-cudnn-devel-ubuntu24.04.sif
-rwxr-xr-x 1 root root 1.9G Dec 10 19:31 /sw/containers/cuda_13.0.2-cudnn-runtime-ubuntu24.04.sif