Post on 23-Jan-2016
Comunicadores Colectivos
BARRIER Esta es una de las primeras que ya vimos. Bloquea todos los procesos hasta que todos los procesos del Comm la llaman. MPI_BARRIER( MPI_COMM_WORLD)
BROADCAST un mensaje para todos los procesos (incluido el mismo) del COMM definidoMPI_BCAST( &a/buffer, count, MPI_FLOAT/datatype, root, comm) &a/buffer en donde se almacena lo enviado count numeros de envios (INT) MPI_FLOAT/datatype tipo de dato enviado (handle) root rango del que envia (INT) comm communicador (handle)
Comunicadores Colectivos
REDUCE al buffer datos de todos los procesos al root utilizando un tipo definido de operación
MPI_REDUCE(&integral/sendbuffer, &total/recvbuffer, count, datatype, op, root, comm)
sendbuffer dirección de iniciorecvbuffer dirección de recepcióncount número de datos enviadosdatatype tipo de datos enviadosop tipo de operación (handle)
MPI_MAX MPI_MIN MPI_SUM MPI_ PROD MPI_LAND MPI_LOR etc.
if(my_rank==0) { a=0; b=1; n=1000; }
(I/O en MPI)
void GeneraVectores(
if (my_rank == 0) { in = fopen("datos.txt","r+");
Truco
Generador de vectores/matrices/datos interno
if (my_rank != 0) { source = 0; MPI_Recv(&a, 1, MPI_FLOAT, source, tag, MPI_COMM_WORLD,&status); MPI_Recv(&b, 1, MPI_FLOAT, source, tag, MPI_COMM_WORLD,&status); MPI_Recv(&n, 1, MPI_INT, source, tag, MPI_COMM_WORLD,&status); } else {
for (dest = 1; dest < p; dest++) { MPI_Send(&a, 1, MPI_FLOAT, dest, tag,MPI_COMM_WORLD); MPI_Send(&b, 1, MPI_FLOAT, dest, tag,MPI_COMM_WORLD); MPI_Send(&n, 1, MPI_INT, dest, tag,MPI_COMM_WORLD); } }h = (b-a)/(n*p); local_n = n; local_a = a + my_rank * (local_n*h); local_b = local_a + (local_n*h); integral_local = Trap(local_a, local_b, local_n, h); error_local = Error_Trap(local_a, local_b, local_n, h); if (my_rank != 0) {
dest = 0; MPI_Send(&integral_local, 1, MPI_FLOAT, dest, tag,MPI_COMM_WORLD); MPI_Send(&error_local, 1, MPI_FLOAT, dest, tag,MPI_COMM_WORLD); } else { total=integral_local; errorT=error_local; for (source = 1; source < p; source++) { MPI_Recv(&integral_local, 1, MPI_FLOAT, source, tag, MPI_COMM_WORLD,&status); total = total + integral_local; MPI_Recv(&error_local, 1, MPI_FLOAT, source, tag, MPI_COMM_WORLD,&status); errorT=errorT + error_local; } }
Trapecio con Send-Recive
MPI_Bcast(&a,1,MPI_FLOAT, 0,MPI_COMM_WORLD); MPI_Bcast(&b,1,MPI_FLOAT, 0,MPI_COMM_WORLD); MPI_Bcast(&n,1,MPI_LONG, 0,MPI_COMM_WORLD); h = (b-a)/(n*p); local_n = n; local_a = a + my_rank * (local_n*h); local_b = local_a + (local_n*h); integral = Trap(local_a, local_b, local_n, h); error = Error_Trap(local_a, local_b, local_n, h); MPI_Reduce(&integral, &total, 1, MPI_FLOAT, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Reduce(&error, &totalError, 1, MPI_FLOAT, MPI_SUM, 0, MPI_COMM_WORLD);
Trapecio con Broadcast-Reduce
MPI_GATHER(sendbuffer, sendcount, sendtype, recvbuffer, recvcount, recvtype, root, comm)
sendbuffer Dirección inicial de los datos de envio. sendcount Numero de datos enviados
sendtype Tipo de datos enviado recvbuffer Dirección inicial de los datos recibidos
recvcount Número de datos recibidosrecvtype Tipo de datos recibidosroot rango del proceso que recibecomm Comunicador
Cada proceso envía el contenido almacenado en sendbuffer al rootQuien lo guarda en el orden del rango
Comunicadores Colectivos
MPI_SCATTER( sendbuffer, sendcount, sendtype, recvbuffer, recvcount, recvtype, root, comm)
sendbuffer Dirección inicial de los datos de envio.sendcount Numero de datos enviadossendtype Tipo de datos enviado
recvbuffer Dirección inicial de los datos recibidosrecvcount Número de datos recibidosrecvtype Tipo de datos recibidosroot rango del proceso que recibecomm Comunicador
Es la operación inversa del MPI GATHER.Una operación en la que cada proceso se queda con un grupo diferente de datos
Comunicadores Colectivos
MPI_Comm comm;int myrank,nprocs,root,iarray[100];int *rbuff;
MPI_Comm_rank(comm, &myrank); // define el rangoMPI_Comm_size(comm, &nprocs); // define numero de procesos
if (myrank == root) { // crea un buffer receptor del tamaño adecuadorbuff = (int *)malloc(nprocs*100*sizeof(int)); }
MPI_Gather(iarray,100,MPI_INT,rbuff,100,MPI_INT,root,comm);
Ejemplo
MPI_ALLGATHER( sendbuffer, sendcount, sendtype, recvbuffer, recvcount, recvtype, root, comm)
sendbuffer Dirección inicial de los datos de envio.sendcount Numero de datos enviadossendtype Tipo de datos enviadorecvbuffer Dirección inicial de los datos recibidosrecvcount Número de datos recibidosrecvtype Tipo de datos recibidosroot rango del proceso que recibecomm Comunicador
Con esta función, una variante de MPI GATHER, todos los procesos en el comm obtienen los mismos Resultados (GATHER + BCAST).
Comunicadores Colectivos
MPI_ALLTOALL( sendbuffer, sendcount, sendtype, recvbuffer, recvcount,recvtype, root, comm)sendbuffer Dirección inicial de los datos de envio.sendcount Numero de datos enviadossendtype Tipo de datos enviadorecvbuffer Dirección inicial de los datos recibidosrecvcount Número de datos recibidosrecvtype Tipo de datos recibidosroot rango del proceso que recibecomm Comunicador
Es una extensión de MPI ALLGATHERpara el caso en que cada proceso envié diferentes datos a cada receptorEl bloque j que viene del proceso i esrecibido por el proceso j y ubicado en la posición i
Comunicadores Colectivos
int MPI_Gatherv ( void *sendbuf, int sendcnt, MPI_Datatype sendtype, void *recvbuf, int *recvcnts, int *displs, MPI_Datatype recvtype, int root, MPI_Comm comm )
A diferencia de MPI_Gather, esta función permite que el tamaño de los subarreglos sea diferente en cada nodo. Tiene dos parámetros diferentes: recvcnts y displs: recvcnts[i]: es un arreglo de enteros de tamaño size que posee en cada celda el tamaño del subarreglo respectivo al nodo i. displs[i]: es un arreglo de enteros de tamaño size que posee en cada celda el offset del subarreglo i en el arreglo global.
Comunicadores Colectivos
En forma similar se define MPI_Scatherv
MPI ALLREDUCE Esta función reduce en el buffer de recepción elementos de todos los procesos con la operación marcada y lo almacena en todos los procesos del comm
El usuario puede imaginar sus propias operaciones de reducción y programarlas.
Un ejemplo MPI_REDUCE_SCATTER una combinación de MPI_REDUCE y MPI_SCATTERV. Que reduce un conjunto de datos y luego lo posiciona en partes en todos los procesos
OJO como se almacenan los datos en C y FORTRAN!
Comunicadores Colectivos
Comunicadores Colectivos: ejemplos
Producto Interno PI = A[100] * B[100]
1) p procesos. Es 100 divisible por p.
Posibilidades: Truco n*p (vale en trapecios)
Completar con ceros
2) Leo en p=0 y distribuyo
00003
00002
00001
252525250
25252525
000253
000252
000251
000250
25252525
SCATTER
PI_Local = Local_A[25] * LocalB[25]
Comunicadores Colectivos: ejemplos
00003
00002
00001
00010
25252525
00013
00012
00011
00010
25252525
REDUCE
4) PI_Local = Local_A[25] * LocalB[25]
5) Reducir al master, imprimir, etc
Comunicadores Colectivos: ejemplos
Multiplicar Matrices (cuadradas) A[100][100]*B[100][100]=C[100][100]
Hay diversas soluciones. Un algoritmo interesante: FOX. Está en el capitulo 7 del Pacheco.
A16A15A14A13
A12A11A10A9
A8A7A6A5
A4A3A2A1
B16B15B14B13
B12B11B10B9
B8B7B6B5
B4B3B2B1
C16C15C14C13
C12C11C10C9
C8C7C6C5
C4C3C2C1
=
C1 = A1*B1 + A2*B5 + A3*B9 + A4*B13
Comunicadores Colectivos: ejemplos
Ab4(25x100)
Ab3(25x100)
Ab2(25x100)
Ab1(25x100)
Bb4(100x25)
Bb3(100x25)
Bb2(100x25)
Bb1(100x25)
A B´
0
1
2
3
SCATTER
25x25
25x25
25x25
25x250
1
2
3
Comunicadores Colectivos: ejemplos
Ab4(25x100)
Ab3(25x100)
Ab2(25x100)
Ab1(25x100)
Bb3(100x25)
Bb2(100x25)
Bb1(100x25)
Bb4(100x25)
A B´
0
1
2
3
25x2525x25
25x2525x25
25x2525x25
25x2525x250
1
2
3
Send-Recv
Comunicadores Colectivos: ejemplos
0
1
2
3 C16C15C14C13
C12C11C10C9
C8C7C6C5
C4C3C2C1
Gather al master
Cb4(25x100)
Cb3(25x100)
Cb2(25x100)
Cb1(25x100)
=
MPI INITMPI COMM SIZEMPI COMM RANKMPI SENDMPI RECEIVEMPI FINALIZE
MPI_Barrier
MPI_Broadcast
MPI_Reduce
MPI_ALLReduce
MPI_Scatter
MPI_Gather
MPI_AllGather
MPI_AlltoALL
MPI_Gatherv
MPI_Scatterv
MPI_Wtime = 17
Varios
Todo el material esta en el sitio web
www.lsc.dc.uba.ar\courses\...
Acceso a Clusters
Herramienta BCCD: http://bccd.cs.uni.edu
lorito.exp.dc.uba.ar
hpci i=1,10 password: mpi2007
Windows
hpci i=1,16 password: a123456Z
SPEEDY SCRIPT.SHhttp://lsc.dc.uba.ar/hpc-grid/cluster-speedy
1) cuentahpci i=1,12 pass = mpi20072) Acceso ssh hpc1@master.fiscmp.lab.dc.uba.ar 3) transferencia de información al cluster sftp 4) COMPILACION Transferir el programa fuente al cluster Conectarse al cluster con ssh Compilar el fuente con el comando correspondiente según las bibliotecas utilizadas. Por ejemplo, utilizando MPI:
mpicc -o prog_fuente_linux prog_fuente_linux.c
5) EJECUCION qsub encolador de procesos. El comando qsub necesita como parámetro un script. Típicamente este script contiene: los parámetros propios del qsub (entre ellos la selección de nodos a utilizar) la invocación al programa que se quiere ejecutar en batch Ejemplos de scripts según las bibliotecas utilizadas: MPI mpich.sh PVM pvm.sh LAM MPI lam.sh 6) cola de procesos qstat Uno de los campos de la tabla de salida de este comando es el estado del proceso, el mismo puede ser:E - Exiting H - Held Q - Queued R - Running T - el job se esta cambiando de nodo W - Waiting S - Suspend 7) eliminar un proceso de la cola qstat Tomar el ID del proceso a eliminar y ejecutar: qdel Job_id
#------------------------------------------------------------------------ # Speedy UBA ## Host : master.speedy.dc.uba.ar # Archivo : /usr/local/speedy/mpich.sh# Creacion : 20030520 - Carolina Leon Carri - mcarri@dc.uba.ar# Revision :# Titulo : Ejemplo de script PBS para MPICH# Descripcion : Este script se utiliza para enviar a ejecutar programas# en batch que utilizan las bibliotecas MPICH el # comando 'qsub' # El comando 'qsub' acepta parametros por linea de comando# o bien pueden definirse dentro de este script. Las lineas # que comienzan con '#PBS' son los parametros que tomara el # comando 'qsub', NO son comentarios.# Para mas informacion puede ver los manuales:# man qsub## Lea atentamente los comentarios del script y modifique # con lo que corresponda donde encuentre la palabra COMPLETAR## Ejecucion : qsub mpich.sh# #------------------------------------------------------------------------
# La opcion -l permite definir los recursos del sistema que se quieren# utilizar. Para ver todos los tipos de recursos que se pueden definir# ver 'man pbs_resources'# El recurso mas utilizado es la especificacion de los nodos que se# quieren utilizar.## Ejemplo por cantidad de nodos:# -l nodes=<cant_nodos>## Ejemplo por nombre de maquina:# -l nodes=<nombre1>+<nombre2>+...
#PBS -l nodes=COMPLETAR
#------------------------------------------------------------------------ # El comando 'qsub' deja la salida de 'standard output' y 'standard error'# en diferentes archivos. Para que guarde todo en un unico archivo se define# la opcion -j donde:# oe : 'std output' y 'std error' como output (*.o*)# eo : 'std output' y 'std error' como error (*.e*)
#PBS -j oe
#------------------------------------------------------------------------ # El 'qsub' envia un mail segun el/los evento/s definido/s:# a abort# b begin# e end# n never
#PBS -m ba
#------------------------------------------------------------------------ # Especificar direccion de e-mail donde se enviara el mail#PBS -M COMPLETAR
#------------------------------------------------------------------------ # La variable PBS_NODEFILE es una variable de entorno del PBS, hace # referencia al archivo que contiene la lista de nodos que se utilizara# para esta corrida dependiendo de la definicion anterior '-l nodes=...'# La variable NP guardara la cantidad de nodos elegidos
NP=$(wc -l $PBS_NODEFILE | awk '{print $1}')
#------------------------------------------------------------------------ # Las siguientes lineas imprimiran en el archivo de output los nodos que# fueron utilizados en la corrida.echo "nodes ($NP cpu total):"sort $PBS_NODEFILE | uniqecho#------------------------------------------------------------------------ # La variable PBS_O_WORKDIR es una variable de entorno del PBS, indica# el PATH absoluto del directorio de trabajo corriente# y es en este directorio donde quedaran los archivos de salida.cd $PBS_O_WORKDIR#------------------------------------------------------------------------ # Linea de ejecucion del mpirunmpirun -machinefile $PBS_NODEFILE -np $NP COMPLETAR
exit 0#------------------------------------------------------------------------