|
|
Línea 1: |
Línea 1: |
| == Concepto de Escalamiento == | | == Beneficios == |
| Cuando nos referimos al '''Escalamiento de un programa''', debemos apuntar al comportamiento del programa a medida que se ejecuta de manera paralela al tener mayor cantidad de procesadores para utilizar. De ser así, podemos considerar que el programa a utilizar permite ser escalable y podremos calcular su eficiencia.
| | Al usar este Toolbox permite ejecutar una tarea en múltiples CPU en un mismo nodo, con un '''máximo de 20 o 44 (dependiendo del nodo)''', la ventaja es que se mejora el rendimiento de una aplicación cuando se lanza en modo paralelo. |
|
| |
|
| Entonces, el escalamiento de un programa será calculado a razón de un determinado rango de procesadores a utilizar, pero pasado ciertos niveles -según el programa-, no importará la cantidad de procesadores que podamos asignar, ya que su eficiencia no será la óptima, e incluso puede verse afectada de manera negativa.
| | == Comparación de parfor v/s for == |
| | Usaremos el siguiente código de ejemplo que utiliza la función [https://mathworks.com/help/matlab/ref/for.html for] v/s [https://mathworks.com/help/distcomp/parfor.html parfor], lanzaremos distintas tareas con diferentes parámetros para luego hacer una tabla comparativa de los resultados de los tiempos. |
|
| |
|
| == Importancia del Escalamiento de Programas ==
| | '''for''' |
| La importancia respecto a cómo escalan los programas se debe al uso óptimo de recursos disponibles, permitiendo que cada usuario obtenga los resultados esperados en un mejor tiempo en comparación a trabajos secuenciales, como también sabiendo que una incorrecta asignación de recursos puede hacer que los resultados deseados se obtengan un mayor período de tiempo como también que la tarea falle.
| |
|
| |
|
| Además, una incorrecta asignación de recursos no solo afectará al usuario que intenta ejecutar una tarea, ya que también afectará a los otros usuarios del Cluster que requieren poder de cómputo.
| | Código MATLAB para for: |
| | |
| Un escalamiento adecuado permitirá un uso eficiente de los recursos para la ejecución de nuestras tareas y las de todos.
| |
| | |
| == Calculando el Speedup y Eficiencia de mi programa ==
| |
| Para realizar el escalamiento de un programa, utilizaremos dos métricas: Speedup y Eficiencia.
| |
| | |
| El Speedup se obtiene calculando el cociente entre el tiempo de ejecución secuencial (1 proceso) y el tiempo de ejecución aumentando la cantidad de procesos asignados a la misma tarea.
| |
| <pre>speedup = tiempo 1 proceso / tiempo N procesos</pre>
| |
| | |
| | |
| La Eficiencia se obtiene calculando el cociente entre el Speedup y el Número de Procesos asignados a la tarea.
| |
| <pre>eficiencia = speedup / Número de Procesos</pre>
| |
| La realización de este ejercicio consta en modificar la cantidad de procesadores a utilizar y comparar sus tiempos de ejecución. Cada tarea ejecutada debe ser planeada según los recursos disponibles en las particiones que necesitamos utilizar, como también considerar la agrupación de tareas.
| |
| | |
| En nuestro siguiente ejemplo hemos ejecutado una tarea en la partición '''Slims''' y utilizado el software '''LAMMPS'''. Al ejecutarlo por primera vez, asignando un solo proceso( #SBATCH -n 1 ), el tiempo de ejecución alcanzó a 1 hora con 27 segundos.
| |
| | |
| El script utilizado fue:
| |
| <pre> | | <pre> |
| #!/bin/bash
| | N = str2num(getenv('MATLAB_N')); |
| #SBATCH -J escalamiento
| | M = 1000; |
| #SBATCH -p slims
| |
| #SBATCH -n 1
| |
| #SBATCH --ntasks-per-node=1
| |
| #SBATCH --mail-user=$USER@nlhpc.cl
| |
| #SBATCH --mail-type=FAIL
| |
| #SBATCH -o escalamiento_%j.out
| |
| #SBATCH -e escalamiento_%j.err
| |
|
| |
|
| ml purge
| | a = zeros(N,1); |
| ml intel
| | tic; |
| ml impi
| | for i = 1:N |
| ml icc
| | a(i) = max(abs(eig(rand(M)))); |
| ml LAMMPS/20Nov19
| | end |
|
| |
|
| srun lmp_intel_cpu_intelmpi -in input-file/in.poly-bench
| | fprintf('\n\n for (N=%d): %f secs\n\n', N, toc); |
| </pre> | | </pre> |
| En las siguientes iteraciones, en donde aumentamos el número de procesos, los tiempos de ejecución fueron bajando. Los parámetros que fueron siendo modificados fueron:
| |
|
| |
| * Número de procesos (tareas en paralelo): -n X
| |
| * Número de tareas por nodo (aumentando según los límetes de la partición Slims): --ntasks-per-node=X
| |
| Por ejemplo, el script usado para la prueba con 128 procesos fue:
| |
|
| |
|
| | Script para lanzar la tarea: |
| <pre> | | <pre> |
| #!/bin/bash | | #!/bin/bash |
| #SBATCH -J escalamiento | | #SBATCH --job-name=for_test |
| #SBATCH -p slims
| | #SBATCH --mail-user=usuario@correo.cl |
| #SBATCH -n 128
| | #SBATCH --mail-type=ALL |
| #SBATCH --ntasks-per-node=16
| | #SBATCH --output=%j_%x.out |
| #SBATCH --mail-user=$USER@nlhpc.cl | | #SBATCH --error=%j_%x.err |
| #SBATCH --mail-type=FAIL | | #SBATCH --partition=slims |
| #SBATCH -o escalamiento_%j.out | | #SBATCH -n 20 |
| #SBATCH -e escalamiento_%j.err | | #SBATCH -L matlab # indico licencias a usar |
| | #SBATCH --mem-per-cpu=2300 |
|
| |
|
| ml purge
| | module load MATLAB/2017a |
| ml intel
| |
| ml impi
| |
| ml icc
| |
| ml LAMMPS/20Nov19
| |
|
| |
|
| srun lmp_intel_cpu_intelmpi -in input-file/in.poly-bench
| | export MATLAB_N=$1 |
| | |
| | matlab -nodisplay -nosplash -nodesktop < for.m |
| </pre> | | </pre> |
|
| |
|
| La siguiente es la tabla de comparación en relación a número de procesos, tiempo de ejecución, Speedup y Eficiencia:
| | '''parfor''' |
|
| |
|
| <table class="wikitable"> | | Código MATLAB para parfor: |
| | <pre> |
| | pc = parcluster(); |
| | pc.JobStorageLocation = strcat('/tmp/', getenv('SLURM_JOB_ID'), '/lcj/'); |
| | parpool(pc, str2num(getenv('SLURM_CPUS_ON_NODE'))); |
|
| |
|
| <tbody><tr>
| | N = str2num(getenv('MATLAB_N')); |
| <th>Procesos <br> <code>-n</code></th>
| | M = 1000; |
| <th>Tareas por Nodo<br><code>--ntasks-per-node</code></th>
| |
| <th>Tiempo</th>
| |
| <th>Speedup</th>
| |
| <th>Eficiencia
| |
| </th></tr>
| |
| <tr>
| |
| <td>1</td>
| |
| <td>1</td>
| |
| <td>01:00:27</td>
| |
| <td>1</td>
| |
| <td>1
| |
| </td></tr>
| |
| <tr>
| |
| <td>2</td>
| |
| <td>2</td>
| |
| <td>00:33:47</td>
| |
| <td>1,8</td>
| |
| <td>0,9
| |
| </td></tr>
| |
| <tr>
| |
| <td>4</td>
| |
| <td>4</td>
| |
| <td>00:18:02</td>
| |
| <td>3,4</td>
| |
| <td>0,8
| |
| </td></tr>
| |
| <tr>
| |
| <td>8</td>
| |
| <td>8</td>
| |
| <td>00:09:13</td>
| |
| <td>6,6</td>
| |
| <td>0,8
| |
| </td></tr>
| |
| <tr>
| |
| <td>16</td>
| |
| <td>16</td>
| |
| <td>00:05:06</td>
| |
| <td>11,9</td>
| |
| <td>0,7
| |
| </td></tr>
| |
| <tr>
| |
| <td>32</td>
| |
| <td>16</td>
| |
| <td>00:02:31</td>
| |
| <td>24,0</td>
| |
| <td>0,8
| |
| </td></tr>
| |
| <tr>
| |
| <td>64</td>
| |
| <td>16</td>
| |
| <td>00:01:18</td>
| |
| <td>46,5</td>
| |
| <td>0,7
| |
| </td></tr>
| |
| <tr>
| |
| <td>128</td>
| |
| <td>16</td>
| |
| <td>00:00:48</td>
| |
| <td>75,6</td>
| |
| <td>0,6
| |
| </td></tr>
| |
| <tr>
| |
| <td>256</td>
| |
| <td>16</td>
| |
| <td>00:00:34</td>
| |
| <td>106,7</td>
| |
| <td>0,4
| |
| </td></tr>
| |
| <tr>
| |
| <td>500</td>
| |
| <td>20</td>
| |
| <td>00:00:31</td>
| |
| <td>117,0</td>
| |
| <td>0,2
| |
| </td></tr>
| |
| <tr>
| |
| <td>600</td>
| |
| <td>20</td>
| |
| <td>00:00:35</td>
| |
| <td>103,6</td>
| |
| <td>0,2
| |
| </td></tr>
| |
| <tr>
| |
| <td>700</td>
| |
| <td>20</td>
| |
| <td>00:00:35</td>
| |
| <td>103,6</td>
| |
| <td>0,1
| |
| </td></tr></tbody></table>
| |
|
| |
|
| Una vez que hemos obtenido resultados suficientes, podemos graficar el comportamiento de nuestra tarea, obteniendo una comparativa entre Speedup v/s Eficiencia:
| | a = zeros(N,1); |
| | tic; |
| | parfor i = 1:N |
| | a(i) = max(abs(eig(rand(M)))); |
| | end |
|
| |
|
| IMAGEN
| | fprintf('\n\n parfor (N=%d): %f secs\n\n', N, toc); |
| | </pre> |
|
| |
|
| Escalamiento-2022.png
| | Script para lanzar la tarea: |
| Es recomendable que la eficiencia que se busque siempre sea superior a 0,5 (con un décimal), por lo que el uso de más de 128 procesos o más, según nuestro ejemplo, serán descartados. Incluso podemos agregar que el uso de más de 256 procesos y más no representa una verdadera mejora, e incluso afectará la cola de trabajo evitando que otras tareas entren en ejecución.
| | <pre> |
| | #!/bin/bash |
| | #SBATCH --job-name=parfor_test |
| | #SBATCH --mail-user=usuario@correo.cl |
| | #SBATCH --mail-type=ALL |
| | #SBATCH --output=%j_%x.out |
| | #SBATCH --error=%j_%x.err |
| | #SBATCH --partition=slims |
| | #SBATCH -n 20 |
| | #SBATCH -L matlab,matlab-distrib_computing # indico licencias a usar |
| | #SBATCH --mem-per-cpu=2300 |
|
| |
|
| Ante esto, es recomendable seleccionar 128 o 64 procesadores para optar a un tiempo menor de ejecución y a una mejor eficacia.
| | module load MATLAB/2017a |
|
| |
|
| == Cuentas de Pruebas == | | mkdir -p /tmp/${SLURM_JOB_ID}/{lcj,mcr} |
| El NLHPC pone a disposición cuentas para la realización de Pruebas de Escalamiento.
| | export MCR_CACHE_ROOT=/tmp/${SLURM_JOB_ID}/mcr |
|
| |
|
| Estas cuentas tienen las siguientes características:
| | export MATLAB_N=$1 |
|
| |
|
| 500 cores
| | matlab -nodisplay -nosplash -nodesktop < parfor.m |
| 6 horas de tiempo de ejecución
| | </pre> |
| 100Gb de Almacenamiento
| |
| 1 semana de duración
| |
| Pueden ser solicitadas desde nuestra página de SOLICITUD DE CUENTAS indicar que realizará la prueba de escalamiento.
| |
|
| |
|
| === Estudio de Escalamiento ===
| | para encolar las diferentes tareas |
| Es importante que si va a solicitar una cuenta en el Cluster del NLHPC, realice una prueba de escalamiento como la indicada anteriormente en donde se pueda medir el Speedup y la Eficiencia.
| | <pre> |
| | | for i in 400 600 800 1000 1200 |
| Puede descargar la siguiente plantilla para ver un ejemplo y editarla con los datos de su aplicación.
| | do sbatch script.sh $i |
| | | done |
| === Ejecución de varias instancias de mi programa ===
| | </pre> |
| Una vez concluido tu estudio de escalamiento, podrás considerar una mayor cantidad de procesadores/cores a solicitar.
| |
| | |
| Siguiendo nuestro ejemplo anterior, si el valor máximo para una tarea es de 128 procesos en paralelo y teniendo la necesidad de ejecutar LAMMPS con 3 archivos distintos de entrada, podré solicitar 384 cores al momento de requerir mi cuenta.
| |
|
| |
|
| === Ejecución de distintos programas que escalen === | | == Tabla Comparativa == |
| En el caso de que sea necesario ejecutar distintos programas que puedan ser paralelizables, lo ideal es que el cálculo de escalamiento sea realizado en el programa que más recursos requiera.
| |
|
| |
|
| Siempre considera realizar pruebas que sean un reflejo a las tareas reales que ejecutarás de esta manera existirá una correlación con lo que reportes y el comportamiento en producción de tus tareas.
| | <p> </p> |
|
| |
|
| == Programas secuenciales == | | <table align="center" border="1" cellpadding="1" cellspacing="1" style="height:419px; width:400px"> |
| Si utilizará programas secuenciales que no soporten paralelización, no es necesario realizar el estudio de escalamiento.
| | <tr> |
| | <th scope="col">N</th> |
| | <th scope="col">parfor</th> |
| | <th scope="col">for</th> |
| | </tr> |
| | <tr> |
| | <td style="text-align:center">400</td> |
| | <td style="text-align:center">37</td> |
| | <td style="text-align:center">374</td> |
| | </tr> |
| | <tr> |
| | <td style="text-align:center">600</td> |
| | <td style="text-align:center">42</td> |
| | <td style="text-align:center">557</td> |
| | </tr> |
| | <tr> |
| | <td style="text-align:center">800</td> |
| | <td style="text-align:center">54</td> |
| | <td style="text-align:center">711</td> |
| | </tr> |
| | <tr> |
| | <td style="text-align:center">1000</td> |
| | <td style="text-align:center"> 66</td> |
| | <td style="text-align:center">900</td> |
| | </tr> |
| | <tr> |
| | <td style="text-align:center">1200</td> |
| | <td style="text-align:center">88</td> |
| | <td style="text-align:center"> 1479</td> |
| | </tr> |
| | </table> |
|
| |
|
| En el caso de que reserve recursos a modo de intentar paralelizar una tarea secuencial, solo generará una reserva de recursos incorrecta, generando estados ociosos, los que son considerados subutilización y su tarea será cancelada.
| | <p> <br /> |
| | <br /> |
| | </p> |
|
| |
|
| Y por último si necesita ejecutar varias tareas secuenciales, estas se podrán lanzar de manera simultanea aprovechando los recursos disponibles.
| | <p> </p> |
|
| |
|
| == Pasos a seguir ==
| |
| Ya hemos visto el proceso de calcular el escalamiento de un programa, requerido para cuando soliciten cuentas en el Cluster del NLHPC.
| |
|
| |
|
| Recuerda que las tareas de los usuarios son monitoreadas para dar un uso adecueado a los recursos. Si quieres saber más visita nuestra sección sobre Monitoreo De Tareas.
| | Los valores del tiempo de ejecución están expresados en segundos, para medir se ocupo la función [https://mathworks.com/help/matlab/ref/tic.html tic]/[https://mathworks.com/help/matlab/ref/toc.html toc]. En el caso de un vector de 400 elementos, con el uso de parfor presenta una mejora del 90% en tiempo respecto al uso de for. |
|
| |
|
| == Enlaces de Interés == | | == Referencias == |
| Introducción al paralelismo y al rendimiento
| | * [https://mathworks.com/products/parallel-computing.html Parallel Computing Toolbox] |
| Performance Metrics, Prediction, and Measurement
| | * [https://mathworks.com/help/distcomp/decide-when-to-use-parfor.html Decide When to Use parfor] |
| A Begginer's Guide to High-Performance Computing
| |
Beneficios
Al usar este Toolbox permite ejecutar una tarea en múltiples CPU en un mismo nodo, con un máximo de 20 o 44 (dependiendo del nodo), la ventaja es que se mejora el rendimiento de una aplicación cuando se lanza en modo paralelo.
Comparación de parfor v/s for
Usaremos el siguiente código de ejemplo que utiliza la función for v/s parfor, lanzaremos distintas tareas con diferentes parámetros para luego hacer una tabla comparativa de los resultados de los tiempos.
for
Código MATLAB para for:
N = str2num(getenv('MATLAB_N'));
M = 1000;
a = zeros(N,1);
tic;
for i = 1:N
a(i) = max(abs(eig(rand(M))));
end
fprintf('\n\n for (N=%d): %f secs\n\n', N, toc);
Script para lanzar la tarea:
#!/bin/bash
#SBATCH --job-name=for_test
#SBATCH --mail-user=usuario@correo.cl
#SBATCH --mail-type=ALL
#SBATCH --output=%j_%x.out
#SBATCH --error=%j_%x.err
#SBATCH --partition=slims
#SBATCH -n 20
#SBATCH -L matlab # indico licencias a usar
#SBATCH --mem-per-cpu=2300
module load MATLAB/2017a
export MATLAB_N=$1
matlab -nodisplay -nosplash -nodesktop < for.m
parfor
Código MATLAB para parfor:
pc = parcluster();
pc.JobStorageLocation = strcat('/tmp/', getenv('SLURM_JOB_ID'), '/lcj/');
parpool(pc, str2num(getenv('SLURM_CPUS_ON_NODE')));
N = str2num(getenv('MATLAB_N'));
M = 1000;
a = zeros(N,1);
tic;
parfor i = 1:N
a(i) = max(abs(eig(rand(M))));
end
fprintf('\n\n parfor (N=%d): %f secs\n\n', N, toc);
Script para lanzar la tarea:
#!/bin/bash
#SBATCH --job-name=parfor_test
#SBATCH --mail-user=usuario@correo.cl
#SBATCH --mail-type=ALL
#SBATCH --output=%j_%x.out
#SBATCH --error=%j_%x.err
#SBATCH --partition=slims
#SBATCH -n 20
#SBATCH -L matlab,matlab-distrib_computing # indico licencias a usar
#SBATCH --mem-per-cpu=2300
module load MATLAB/2017a
mkdir -p /tmp/${SLURM_JOB_ID}/{lcj,mcr}
export MCR_CACHE_ROOT=/tmp/${SLURM_JOB_ID}/mcr
export MATLAB_N=$1
matlab -nodisplay -nosplash -nodesktop < parfor.m
para encolar las diferentes tareas
for i in 400 600 800 1000 1200
do sbatch script.sh $i
done
Tabla Comparativa
N |
parfor |
for |
400 |
37 |
374 |
600 |
42 |
557 |
800 |
54 |
711 |
1000 |
66 |
900 |
1200 |
88 |
1479 |
Los valores del tiempo de ejecución están expresados en segundos, para medir se ocupo la función tic/toc. En el caso de un vector de 400 elementos, con el uso de parfor presenta una mejora del 90% en tiempo respecto al uso de for.
Referencias