StarPU sur Jean Zay

Présentation

StarPU est une bibliothèque de programmation par tâches pour les architectures hybrides, multicœurs et hétérogènes.

L'utilisateur doit fournir les algorithmes ainsi que les contraintes et Starpu s'occupe pour lui des dépendances des tâches, de la planification hétérogène optimisée, ainsi que du tranfert et réplication optimisés des données entre les différents emplacements mémoires.

StarPU peut être utilisé via son API en C/C++/Fortran/Python ou par des pragmas OpenMP.

Liens utiles

Versions disponibles

module avail starpu

Version 1.3.9

Variantes
cuda, cuda-simgrid, cuda-debug, cuda-debug-simgrid
Modules nécessaires Modules supplémentaires pour simgrid
hwloc, libpciaccess, libxml2boost
# Exemple
module load starpu/1.3.9-cuda-debug hwloc/2.7.1-cuda libpciaccess/0.16 libxml2/2.9.9 

Version 1.4.2

Variantes
mpi-debug, mpi-cuda-debug

Chargement automatique des modules pré-requis à l'utilisation de starpu 1.4.2 :

# Exemple
module load starpu/1.4.2-mpi-debug

StarPU sur A100

Modules supplémentaires pour A100
archcpu/amd

Attention, charger d'abord le module 'archcpu/amd'

Guide de démarrage sur Jean Zay de StarPU pour du code en C

Pré-requis : Accéder à un noeud de calcul en interactif

$ srun --ntasks=1 --cpus-per-task=10 --partition=cpu_p1 --hint=nomultithread --time=08:00:00 --pty bash
# chargement du module starpu et de ses dépendances
module load starpu/1.3.9-cuda-debug hwloc/2.7.1-cuda libpciaccess/0.16 libxml2/2.9.9

On définit un code simple qui soumet une tâche à StarPU.

#include <starpu.h>
#include <stdio.h>
 
/* Bien respecter la signature de la fonction qui doit être soumis à StarPU */
void cpu_func(void *buffers[], void *cl_arg)
{
    printf("Hello world\n");
}
 
/* On enveloppe la fonction avec des paramètres spécifiques à une tâche StarPU, appelé "Codelet" */
struct starpu_codelet cl =
{
    .cpu_funcs = { cpu_func },
    .nbuffers = 0
};
 
 
int main(int argc, char *argv[])
{
    int ret;
 
    /* Initialisation de StarPU */
    ret = starpu_init(NULL);
    STARPU_CHECK_RETURN_VALUE(ret, "starpu_init"); /* Vérifie l'état de l'initialisation */
 
    /* Définition d'une tâche StarPU */
    struct starpu_task *task = starpu_task_create();
    task->cl = &cl; /* On pointe vers le codelet défini plus haut */
 
    /* Soumission de la tâche à StarPU */
    ret = starpu_task_submit(task);
    STARPU_CHECK_RETURN_VALUE(ret, "starpu_task_submit");
    ret = starpu_task_wait_for_all();
 
    /* Termine StarPU */
    starpu_shutdown();
 
    return 0; 
}

Compilation du code ci-dessus avec un Makefile :

CFLAGS += $$(pkg-config --cflags starpu-1.3)
LDLIBS += $$(pkg-config --libs starpu-1.3)
 
all: hello_world
 
hello_world:
	gcc $(CFLAGS) hello_world.cpp -o hello_world $(LDLIBS)
 
clean:
	rm -f hello_world starpu.log

Soumission en mode batch

#!/bin/bash
 
## JOB INFO
#SBATCH --job-name=starpu_code
#SBATCH --output=%x_%j.out
#SBATCH --error=%x_%j.err 
 
## NODE CONFIGURATION
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=10
#SBATCH --partition=cpu_p1
#SBATCH --hint=nomultithread
 
## JOB ACCOUNTABILITY
#SBATCH --account=xxx@cpu
#SBATCH --partition=cpu_p1
#SBATCH --time=01:00:00
 
## ENV ACTIVATION
module purge
module load starpu/1.3.9-cuda-debug hwloc/2.7.1-cuda libpciaccess/0.16 libxml2/2.9.9
 
## CODE EXECUTION
make
./my_app

Soumission en batch pour du code multi-noeuds

Starpu versions
1.4.2-mpi-debug, 1.4.2-mpi-cuda-debug
#!/bin/bash
 
## JOB INFO
#SBATCH --job-name=starpu_multi-nodes_code
#SBATCH --output=%x_%j.out
#SBATCH --error=%x_%j.err 
 
## NODE CONFIGURATION
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=10
#SBATCH --partition=cpu_p1
#SBATCH --hint=nomultithread
 
## JOB ACCOUNTABILITY
#SBATCH --account=xxx@cpu
#SBATCH --partition=cpu_p1
#SBATCH --time=01:00:00
 
## ENV ACTIVATION
module purge
module load starpu/1.4.2-mpi-debug hwloc/2.7.1-cuda libpciaccess/0.16 libxml2/2.9.9
 
## CODE EXECUTION
make
srun ./my_mpi_app

On utilise dans notre exemple :

  • 2 noeuds
  • srun indique à chaque noeud de lancer 1 seule tâche qui exécute ./my_mpi_app et qui communique entre eux
  • chaque exécution utilise 10 coeurs cpus
  • on utilise le module starpu/1.4.2-mpi-debug qui contient l'option mpi.

Exécution d'un code python

Starpu versions Module nécessaire
1.4.2-mpi-debug, 1.4.2-mpi-cuda-debugpython/3.8.8
# Chargé en premier le module python en premier
module load python/3.8.8
module load starpu
import time
import starpu
from starpu.joblib import Parallel, delayed
 
# Initialise StarPU
starpu.init()
 
# define a function which last several seconds
def huge_task(task_number):
    print("Beginning of task : ", task_number, "\n")
    c = 0
    for i in range(200000000):
        c += 1
    print("End of task : ", task_number, "\n")
    return task_number
 
 
start = time.time()
X = [1,2,3,4]
Parallel()(delayed(huge_task)(x) for x in X) # lance plusieurs tâches à StarPU
stop = time.time()
print(stop-start)
 
 
# Termine StarPU
starpu.shutdown()

Astuces

# Ignorer le binding-CPU fait par slurm et s'assurer de profiter de l'ensemble des coeurs allouées
export STARPU_WORKERS_GETBIND=0

Configurations particulières

Si vous avez besoin d'une compilation avec une configuration très précise (et non disponible depuis nos modules), il est tout à fait possible de compiler StarPU en local. Pour toutes demandes d'aides, vous pouvez contacter l'assistance