User Tools

Site Tools


cluster

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
cluster [2018/09/20 10:33]
osotolongo [The real life (--multi-prog)]
cluster [2020/05/04 10:23]
osotolongo [Paralelizando un archivo de ordenes]
Line 3: Line 3:
 [[https://youtu.be/q5SG7U76tls | Get it started ]] [[https://youtu.be/q5SG7U76tls | Get it started ]]
  
-El cluster (//brick//) consta de cuatro nodos (//brick00, brick01, brick02 y brick03//). Lo que sigue describe la operativa básica para ejecutar tareas en estas maquinas de una manera ordenada+El cluster (//brick//) consta de tres nodos (//brick01, brick02 y brick03//). Lo que sigue describe la operativa básica para ejecutar tareas en estas maquinas de una manera ordenada
  
 {{ ::topologia.png?direct&300 |}} {{ ::topologia.png?direct&300 |}}
Line 219: Line 219:
  
 Este script lo unico que hace es configurar minimamente **sbatch** y lanzar el comando **srun**.  Este script lo unico que hace es configurar minimamente **sbatch** y lanzar el comando **srun**. 
 +  * La directiva //time// especifica cuantos minutos dejaremos correr el trabajo. Con //--time=0// no se aplica límite de tiempo. 
   * Las directivas importantes aqui son //--ntasks-per-node=20// y //-n 50//. La primera dice a **sbatch** que lance 20 tareas en cada nodo, la segunda que hay un total de 50 tareas. para que todo vaya bien n/ntask-per-node < 3. Por ejemplo si ponemos //--ntasks-per-node=10//, entonces dara error porque 50/10=5. //Esto se puede quitar pero si lanzamos 50 tareas las metera todas en brick01 y el ejemplo no servira de nada//.   * Las directivas importantes aqui son //--ntasks-per-node=20// y //-n 50//. La primera dice a **sbatch** que lance 20 tareas en cada nodo, la segunda que hay un total de 50 tareas. para que todo vaya bien n/ntask-per-node < 3. Por ejemplo si ponemos //--ntasks-per-node=10//, entonces dara error porque 50/10=5. //Esto se puede quitar pero si lanzamos 50 tareas las metera todas en brick01 y el ejemplo no servira de nada//.
   * Las directivas //--mail-type=ALL// y //--mail-user=osotolongo// dicen que envie por email todo lo que ocurra al usuario //osotolongo//. Si el usuario de cada uno esta bien configurado, esto deberia funcionar para cada uno con solo cambiar el nombre.   * Las directivas //--mail-type=ALL// y //--mail-user=osotolongo// dicen que envie por email todo lo que ocurra al usuario //osotolongo//. Si el usuario de cada uno esta bien configurado, esto deberia funcionar para cada uno con solo cambiar el nombre.
Line 327: Line 328:
  
 {{ ::screenshot_from_2018-09-20_11-45-17.png?nolink |}} {{ ::screenshot_from_2018-09-20_11-45-17.png?nolink |}}
 +
 +==== Hard batching ====
 +
 +[[https://www.youtube.com/watch?v=86URGgqONvA|Run to the hills]]
 +
 +El procedimiento anterior funciona OK cuando se lanzan pocas tareas que consuman tiempo. Si hemos de lanzar muchas tareas rapidas lo mejor no es usar un solo //srun// con el switch //--multi-prog// sino lanzar un //sbatch// para cada proceso.
 +
 +Ahora el //test_generator// es distinto, cada proceso se ejecutara con un sbatch, que hay que construir en un bucle. Luego basta con hacer un ejecutable que lance los //sbatch// consecutivamente,
 +<code bash test_generator2.sh>
 +#!/bin/sh
 +#Creo los batch a ejecutar
 +count=0
 +while [ $count -lt 50 ]
 +do
 +        cn=$((count+1))
 +        echo "#!/bin/bash" > test_run_${cn}.sh
 +        echo "#SBATCH -J test" >> test_run_${cn}.sh
 +        echo "#SBATCH --mail-type=FAIL,TIME_LIMIT,STAGE_OUT" >> test_run_${cn}.sh
 +        echo "#SBATCH --mail-user=`whoami`" >> test_run_${cn}.sh
 +        echo "srun test_runner.sh test/blah${cn}.txt" >> test_run_${cn}.sh
 +        ((count++))
 +done
 +#Creo un archivo que ejecute los batch
 +count=0
 +echo "#!/bin/bash" > test.sh
 +while [ $count -lt 50 ]
 +do
 +        cn=$((count+1))
 +        echo "sbatch test_run_${cn}.sh" >> test.sh
 +        ((count++))
 +done
 +# Creo un script de aviso
 +echo "#!/bin/bash" > mailme.sh
 +echo "#SBATCH -J test" >> mailme.sh
 +echo "#SBATCH --mail-type=END" >> mailme.sh
 +echo "#SBATCH --mail-user=`whoami`" >> mailme.sh
 +echo "srun :" >> mailme.sh
 +echo "sbatch --dependency=singleton mailme.sh" >> test.sh
 +chmod +x test.sh
 +</code>
 +**Nota:** Cada proceso se ejecuta independientemente y solo envia emails en caso de fallo, para recibir un aviso cuando se termina la ejecucion es necesario crear y ejecutar un porceso que lo haga y que dependa especificamente de que todos los procesos previos terminen. La forma natural es ejecutarlo con el comando //sbatch --dependency=singleton//, pero ojo que esto se ejecutara cuando todos los procesos con elmismo nombre y bajo el mismo usuario hayan terminado, asi que ha de asignarse a cada proceso el mismo nombre (//swarm//). Si hay que lanzar dos //swarm// diferentes hay que hacerlo con un nombre distinto y correr porque seras condenado a la guillotina por el administrador del cluster. Ojo, que este proceso (que aparece como Dependency bajo //squeue//) en realidad no hace nada, solo manda un email cuando se ejecuta.
 +Vamos a probarlo,
 +<code bash>
 +[osotolongo@detritus cluster]$ ./test_generator2.sh 
 +[osotolongo@detritus cluster]$ ls
 +mailme.sh     test_run_10.sh  test_run_15.sh  test_run_1.sh   test_run_24.sh  test_run_29.sh  test_run_33.sh  test_run_38.sh  test_run_42.sh  test_run_47.sh  test_run_5.sh  test_runner.sh
 +test     test_run_11.sh  test_run_16.sh  test_run_20.sh  test_run_25.sh  test_run_2.sh   test_run_34.sh  test_run_39.sh  test_run_43.sh  test_run_48.sh  test_run_6.sh  test.sh
 +test.conf     test_run_12.sh  test_run_17.sh  test_run_21.sh  test_run_26.sh  test_run_30.sh  test_run_35.sh  test_run_3.sh   test_run_44.sh  test_run_49.sh  test_run_7.sh
 +test_generator2.sh  test_run_13.sh  test_run_18.sh  test_run_22.sh  test_run_27.sh  test_run_31.sh  test_run_36.sh  test_run_40.sh  test_run_45.sh  test_run_4.sh   test_run_8.sh
 +test_generator.sh   test_run_14.sh  test_run_19.sh  test_run_23.sh  test_run_28.sh  test_run_32.sh  test_run_37.sh  test_run_41.sh  test_run_46.sh  test_run_50.sh  test_run_9.sh
 +[osotolongo@detritus cluster]$ cat test_run_1.sh
 +#!/bin/bash
 +#SBATCH -J test
 +#SBATCH --mail-type=FAIL,TIME_LIMIT,STAGE_OUT
 +#SBATCH --mail-user=osotolongo
 +srun test_runner.sh test/blah1.txt
 +[osotolongo@detritus cluster]$ cat test.sh
 +#!/bin/bash
 +sbatch test_run_1.sh
 +sbatch test_run_2.sh
 +sbatch test_run_3.sh
 +sbatch test_run_4.sh
 +sbatch test_run_5.sh
 +...................
 +sbatch test_run_50.sh
 +sbatch --dependency=singleton mailme.sh
 +
 +[osotolongo@detritus cluster]$ ./test.sh 
 +Submitted batch job 15262
 +Submitted batch job 15263
 +Submitted batch job 15264
 +Submitted batch job 15265
 +Submitted batch job 15266
 +Submitted batch job 15267
 +Submitted batch job 15268
 +...............
 +
 +[osotolongo@detritus cluster]$ squeue
 +             JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
 +             15312     devel     test osotolon PD       0:00      1 (Dependency)
 +             15262     devel     test osotolon  R       0:03      1 brick01
 +             15263     devel     test osotolon  R       0:03      1 brick01
 +             15264     devel     test osotolon  R       0:03      1 brick01
 +             15265     devel     test osotolon  R       0:00      1 brick01
 +             15266     devel     test osotolon  R       0:00      1 brick01
 +....................
 +</code>
 +
 +{{::email_done.png|}}
 +
 +
 +===== Paralelizando un archivo de ordenes =====
 +
 +Podemos abstraer todo esto en un script simple para paralelizar las ordenes escritas en un solo archivo.
 +
 +Ejemplo, este script,
 +
 +<code perl slurmize.pl>
 +#!/usr/bin/perl
 +use strict;
 +use warnings;
 +
 +#Cambiar aqui el tiempo maximo de ejecucion
 +my $time = '3:0:0';
 +
 +my $ifile = $ARGV[0];
 +my $wdir = 'slurm';
 +mkdir $wdir;
 +my $count = 0;
 +open IPDF, "<$ifile" or die "Could not open input file\n$!\n";
 +while (<IPDF>) {
 +        $count++;
 +        my $ofile = sprintf ("%s_%04d", 'sorder', $count);
 +        $ofile = $wdir.'/'.$ofile;
 +        open ORD, ">$ofile";
 +        print ORD '#!/bin/bash'."\n";
 +        print ORD '#SBATCH -J '.$ifile."\n";
 +        print ORD '#SBATCH -c 8'."\n";
 +        print ORD '#SBATCH --mem-per-cpu=4G'."\n";
 +        print ORD '#SBATCH --time='.$time."\n"; #si no ha terminado en X horas matalo
 +        print ORD '#SBATCH --mail-type=FAIL,TIME_LIMIT,STAGE_OUT'."\n"; #que mande email solo cuando falle
 +        print ORD '#SBATCH --mail-user='."$ENV{'USER'}\n";
 +        print ORD '#SBATCH -p fast'."\n";
 +        print ORD '#SBATCH -o '.$wdir.'/'.$ifile.'-%j'."\n";
 +        print ORD "srun $_\n";
 +        close ORD;
 +        system("sbatch $ofile");
 +}
 +close IPDF;
 +my $orderfile = $wdir.'/'.$ifile.'_end.sh';
 +open ORD, ">$orderfile";
 +print ORD '#!/bin/bash'."\n";
 +print ORD '#SBATCH -J '.$ifile."\n";
 +print ORD '#SBATCH --mail-type=END'."\n"; #email cuando termine
 +print ORD '#SBATCH --mail-user='."$ENV{'USER'}\n";
 +print ORD '#SBATCH -o '.$wdir.'/'.$ifile.'_end-%j'."\n";
 +print ORD ":\n";
 +close ORD;
 +my $xorder = 'sbatch --dependency=singleton'.' '.$orderfile;
 +exec($xorder);
 +</code>
 +
 +lee un archivo de entrada y ejecuta cada linea como una tarea de SLURM. Para esto basta hacer,
 +
 +<code bash>
 +$ ./slurmize.pl ordenes.txt
 +</code>
 +
 +donde //ordenes.txt// es cualquier listado de tareas.
 +
 +==== ejemplo ====
 +  * Las ordenes deben ejecutarse dentro del directorio /nas/ para que el sistema de archivos sea accesible a todos los nodos.
 +  * Escribo las ordenes dentro de un archivo (en este caso //test//)
 +  * Ejecuto el script dando como argumento el nombre del archivo de ordenes
 +  * Las tareas seenvian a los nodos del cluster
 +  * El output (STDOUT & STDERR) queda dentro del directorio //slurm// en un archivo distinto para cada proceso
 +  * Tambien pueden mirarse los scripts individuales que quedan en el mismo directorio
 +
 +
 +<code bash>
 +[osotolongo@detritus slurmit]$ pwd
 +/nas/osotolongo/slurmit
 +[osotolongo@detritus slurmit]$ cat test
 +sleep 2000;hostname
 +sleep 2000;hostname
 +sleep 2000;hostname
 +[osotolongo@detritus slurmit]$ ./slurmize.pl test
 +Submitted batch job 129583
 +Submitted batch job 129584
 +Submitted batch job 129585
 +Submitted batch job 129586
 +[osotolongo@detritus slurmit]$ squeue | grep test
 +            129586      fast     test osotolon PD       0:00      1 (Dependency)
 +            129583      fast     test osotolon  R       0:06      1 brick02
 +            129584      fast     test osotolon  R       0:06      1 brick02
 +            129585      fast     test osotolon  R       0:06      1 brick02
 +[osotolongo@detritus slurmit]$ tree
 +.
 +├── slurm
 +│   ├── sorder_0001.sh
 +│   ├── sorder_0002.sh
 +│   ├── sorder_0003.sh
 +│   ├── test-129583
 +│   ├── test-129584
 +│   ├── test-129585
 +│   └── test_end.sh
 +├── slurmize.pl
 +└── test
 +
 +1 directory, 9 files
 +
 +</code>
 +
cluster.txt · Last modified: 2020/08/04 10:58 (external edit)