Tareas de ejemplo (secuencial y paralela)¶
Ejemplo 1. Una tarea secuencial en un solo nodo.¶
- Programa de metodo de montecarlo para el calculo de pi (montecarlo.c)
/*
* C program to compute the value of pi using Monte Carlo
*
* Command-line arguments: number_of_samples, seed
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h> /* has fabs() */
#include <sys/time.h>
/* main program */
unsigned int mysecond()
{
struct timeval tp;
struct timezone tzp;
int i;
i = gettimeofday(&tp,&tzp);
return ( (unsigned int) tp.tv_sec + (unsigned int) tp.tv_usec * 1.e-6);
}
int main(int argc, char* argv[]) {
int num_samples,i;
int seed;
double start_time, end_time;
int count, local_count = 0;
double x, y;
double pi = 0.0;
int nprocs=1;
/* process command-line arguments */
if (argc != 2) {
fprintf(stderr, "usage: %s number_of_samples\n", argv[0]);
exit(1);
}
num_samples = atoi(argv[1]);
seed = mysecond();
if ((num_samples <= 0) || (seed <= 0)) {
fprintf(stderr, "usage: %s number_of_samples\n", argv[0]);
exit(1);
}
/* do calculation */
srand((unsigned int) seed);
for (i = 0; i < num_samples; i += nprocs) {
x = (double) rand() / (double) (RAND_MAX);
y = (double) rand() / (double) (RAND_MAX);
if ((x*x + y*y) <= 1.0)
++local_count;
}
count=local_count;
pi = 4.0 * (double) count / (double) num_samples;
printf("Program results with %d processes:\n", nprocs);
printf("number of samples = %d, seed = %d\n", num_samples, seed);
printf("estimated pi = %12.10f\n", pi);
printf("difference between estimated pi and math.h M_PI = %12.10f\n",fabs(pi - M_PI));
return EXIT_SUCCESS;
}
- Programa de metodo de montecarlo para el calculo de pi (montecarlo.c)
$ icc monte-carlo-pi.c -o montecarlo-pi
- Preparar el programa que se enviara al sistema PBS (montecarlo-pi.pbs)
#!/bin/bash
#PBS -N montecarlo-pi
#PBS -q intel
#PBS -o salidapi.out
#PBS -e salidapi.err
set -x
cd $PBS_O_WORKDIR
date > tiempoINTEL.txt
./montecarlo-pi 10000000000
date >> tiempoINTEL.txt
echo "Finalize"
- Ejecutarlo:
$ qsub montecarlo-pi.pbs
- Salida:
$ more salidapi.out
Program results with 1 processes:
number of samples = 1410065408, seed = 1592253525
estimated pi = 3.1415875738
difference between estimated pi and math.h M_PI = 0.0000050798
Finalice
Ejemplo 2. Una tarea paralela usando MPI de intel ejecutandose en 96 cores¶
a)Programa fuente en C llamada matrix-mpi.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include "mpi.h"
#define MatrixSIZE 1000
#define TYPE float
#define MPITYPE MPI_FLOAT
#define TAG_MATRIX1 1
#define TAG_MATRIX2 2
#define TAG_RESULT 3
TYPE Matrix1 [MatrixSIZE][MatrixSIZE];
TYPE Matrix2 [MatrixSIZE][MatrixSIZE];
TYPE Result [MatrixSIZE][MatrixSIZE];
long Rows;
long i;
long Counter = 0;
double start_time;
double end_time;
int my_rank;
int p;
MPI_Status status;
TYPE GetRand()
{
TYPE fl;
int num1, num2;
fl = (char) random();
num1 = (int) random();
num2 = (int) random();
fl += (TYPE) num2/num1;
return fl;
}
double GetTime()
{
struct timeval t;
gettimeofday(&t, (struct timezone *) 0);
return (t.tv_sec + ((double) t.tv_usec)/1000000);
}
void FillMatrix()
{
long i, i1;
for (i=0; i<MatrixSIZE; i++)
{
srandom( (int) GetTime());
for (i1=0; i1<MatrixSIZE; i1++)
{
Matrix1[i][i1] = GetRand();
Matrix2[i][i1] = GetRand();
}
}
}
void Multiply()
{
long i, i1, i2;
for (i = Rows*my_rank; i < Rows*(my_rank+1); i++)
{
for (i1 = 0; i1 < MatrixSIZE; i1++)
{
Result[i][i1] = 0;
for (i2 = 0; i2 < MatrixSIZE; i2++)
{
Result[i][i1] += (Matrix1[i][i2] * Matrix2[i2][i1]);
}
}
}
}
void PrintMatrix(TYPE Matrix[MatrixSIZE][MatrixSIZE])
{
int i, i1;
for (i = 0; i < MatrixSIZE; i++)
{
for (i1 = 0; i1 < MatrixSIZE; i1++)
{
printf("%f ", Matrix[i][i1]);
}
printf("\n");
}
}
int main(int argc, char ** argv)
{
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
MPI_Comm_size(MPI_COMM_WORLD, &p);
if (my_rank == 0)
{
printf("Running on %d processors...\n", p);
FillMatrix();
printf("Finished Filling Matrix...\n");
for (i = 1; i < p; i++)
{
MPI_Send(&Matrix1, MatrixSIZE*MatrixSIZE, MPITYPE, i, TAG_MATRIX1,
MPI_COMM_WORLD);
MPI_Send(&Matrix2, MatrixSIZE*MatrixSIZE, MPITYPE, i, TAG_MATRIX2,
MPI_COMM_WORLD);
}
start_time = MPI_Wtime();
}
else
{
MPI_Recv(&Matrix1, MatrixSIZE*MatrixSIZE, MPITYPE, 0, TAG_MATRIX1,
MPI_COMM_WORLD, &status);
MPI_Recv(&Matrix2, MatrixSIZE*MatrixSIZE, MPITYPE, 0, TAG_MATRIX2,
MPI_COMM_WORLD, &status);
}
Rows = MatrixSIZE/p;
Multiply();
MPI_Barrier(MPI_COMM_WORLD);
if (my_rank == 0)
{
end_time = MPI_Wtime();
Counter = MatrixSIZE*MatrixSIZE*MatrixSIZE;
printf("\nElapsed Time : %f, Ops : %d, MFLops : %f\n",
end_time-start_time, Counter, Counter/((end_time-start_time)*100000
0));
for (i = 1; i < p; i++)
{
MPI_Recv(&Result[Rows*i][0], Rows*MatrixSIZE, MPITYPE, i,
TAG_RESULT, MPI_COMM_WORLD, &status);
}
}
else
{
MPI_Send(&Result[Rows*my_rank][0], Rows*MatrixSIZE, MPITYPE, 0,
TAG_RESULT, MPI_COMM_WORLD);
}
MPI_Finalize();
}
- Compilacion del programa matrix-mpi.c
mpiicc matrix-mpi.c -o matrix-mpi
- Realizacion del script en PBS con las directivas enviarse al sistema de colas.
#!/bin/bash
#PBS -N matrix-mpi_8x12
#PBS -l nodes=8:ppn=12
#PBS -q intel
#PBS -o pi.log
#PBS -e pi.error
cd $PBS_O_WORKDIR
sort -u $PBS_NODEFILE > nodes.file
mpirun -ppn $PBS_NUM_PPN -n $PBS_NP ./matrix-mpi >out.mpi
- Ejecucion:
qsub matrix-mpi.pbs
- El resultado.
$ more out.mpi
Running on 96 processors...
Finished Filling Matrix...
Elapsed Time : 0.002329, Ops : 1000000000, MFLops : 429348.346811
Python¶
Programas en python pueden ser enviados como tareas por lotes al cluster.
Como ejemplo el siguiente codigo en python. interpol1D.py
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from scipy import interpolate
x = np.linspace(0, 10, num=10, endpoint=True)
y = np.cos(-x**2/9.0)
f = interpolate.interp1d(x, y)
f2 = interpolate.interp1d(x, y, kind='cubic')
xnew = np.linspace(0, 10, num=200, endpoint=True)
tck = interpolate.splrep(x, y, s=0)
f3 = interpolate.splev(xnew, tck , der=0)
plt.plot(x, y, 'o', xnew, f(xnew), '-', xnew, f2(xnew), '--', xnew, f3)
plt.title('Intepolacion 1D - metodos')
plt.legend(['data', 'linear', 'cubic','Cubic Spline'], loc='best')
plt.savefig('interpol1D.png', dpi=250, format='png')
Preparamos el script para enviar la tarea al manejador de recursos:
#!/bin/bash
#PBS -N pythonjob
#PBS -q intel
#PBS -l nodes=1
#PBS -j oe
set -x
cd $PBS_O_WORKDIR
echo Inicio: `date` > tiempo.log
start=`date +%s`
python interpol1D.py
echo Final : `date` >> tiempo.log
end=`date +%s`
echo Tiempo ejecución : $((end-start)) seg. >> tiempo.log
Para ejecutar la tarea escribimos:
$ qsub submitjob.sh
El resultado de la operación correcta de esta tarea debe producir tres archivos, una imagen png interpol1D.png
un archivo tiempo.log
y submitjob.o####
siendo #### el numero del JobID que nos asigno el manejador de tareas.