Computación de altas prestaciones - Departamento de Informática y

Anuncio
Computación de altas prestaciones
Computación híbrida y heterogénea
Domingo Giménez
Dpto. de Informática y Sistemas
Universidad de Murcia
http://dis.um.es/~domingo
1
Nociones básicas de
2
Programación Híbrida
OpenMP
MPI
Paralelismo de grano fino
Eficiencia en SMP
Códigos secuencial y paralelo similares
Herramientas de desarrollo y paralelización
Permite asignación en tiempo de ejecución
La asignación de memoria puede reducir las prestaciones
Paralelismo de grado grueso
Más portable
Código paralelo muy diferente
del secuencial
Desarrollo y depuración más
difícil
Asignación estática de
procesos
Memorias locales, que
facilitan eficiencia
Nociones básicas de
3
Programación Híbrida
Ventajas de la Programación Híbrida
●
●
●
●
●
●
Para mejorar la escalabilidad
Cuando muchas tareas producen desbalanceo
Aplicaciones que combinan paralelismo de grano grueso y fino
Reducción del tiempo de desarrollo de código
Cuando el número de procesos MPI es fijo
En caso de mezcla de paralelismo funcional y de datos
Nociones básicas de
4
Programación Híbrida
La gran mayoría
son sistemas
híbridos
Nociones básicas de
Programación Híbrida
Modelos
MPI+OpenMP
OpenMP usado para paralelización de bucles
OpenMP+MPI
Threads no seguros
Procesos MPI y OpenMP en modelo SPMD
Reduce el coste de las comunicaciones
5
6
Ejemplos básicos
int main(int argc, char *argv[]) { int nthreads,nprocs,idpro,idthr; int namelen;
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&nprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&idpro);
MPI_Get_processor_name(processor_name,&namelen);
#pragma omp parallel private(idthr) firstprivate(idpro,processor_name) {
idthr = omp_get_thread_num();
printf("... thread %d, proceso %d procesador %s\n",idthr,idpro,processor_name);
if (idthr == 0) {
nthreads = omp_get_num_threads();
printf(" proceso %d, threads %d, procesos %d\n",idpro,nthreads,nprocs);
} }
MPI_Finalize(); }
7
Ejemplos básicos
int main (int argc,char **argv) {
//Variables
int i,load,begin,end,*a,n,l,u,x,keepon=1,position=­1,thread=­1;
int nthreads,nprocs,idpro,idthr;
int namelen;
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Status estado;
//Iniciación MPI
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&nprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&idpro);
MPI_Get_processor_name(processor_name,&namelen);
8
Ejemplos básicos
if(idpro==0) { //Entrada y envío de datos
printf("De el numero de datos del array: "); scanf("%d",&n);
MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
a=(int *) malloc(sizeof(double)*n);
printf("De los valores minimo y maximo: "); scanf("%d %d",&l,&u);
generar_enteros(a,n,l,u); escribir_enteros(a,n);
printf("De el numero a buscar: "); scanf("%d",&x);
MPI_Bcast(&x, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
for(i=1;i<nprocs;i++) MPI_Send(&a[i*n/nprocs],n/nprocs,MPI_INT,i,ENVIO_INICIAL,
MPI_COMM_WORLD);
} else { //Recepción de datos
MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Bcast(&x, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
a=(int *) malloc(sizeof(int)*n/nprocs);
MPI_Recv(a,n/nprocs,MPI_INT,0,ENVIO_INICIAL,MPI_COMM_WORLD,
&estado);
}
9
Ejemplos básicos
//Puesta en marcha de los threads #pragma omp parallel private(idthr,i,load,begin,end)
{
#pragma omp master
nthreads = omp_get_num_threads();
idthr = omp_get_thread_num(); load = n/nprocs/nthreads; begin = idthr*load; end = begin+load;
for (i = begin; ((i<end) && keepon); i++) {
if (a[i] == x) {
keepon = 0; position = i; thread=idthr;
}
#pragma omp flush(keepon,position)
} }
10
Ejemplos básicos
if(idpro==0) { //Recibir datos
if(position!=­1)
printf("Encontrado en la posicion %di, por el thread %d de %d, del proceso %d\n",position,thread,nthreads,idpro);
for(i=1;i<nprocs;i++){
MPI_Recv(&position,1,MPI_INT,i,ENVIO_FINAL,MPI_COMM_WORLD,&estado);
MPI_Recv(&thread,1,MPI_INT,i,ENVIO_FINAL_THR,MPI_COMM_WORLD,&estado);
MPI_Recv(&nthreads,1,MPI_INT,i,ENVIO_FINAL_NTHR,MPI_COMM_WORLD,
&estado);
if(position!=­1)
printf("Encontrado en la posicion %d,por el tread %d de %d, del proceso %d\n",position+i*n/nprocs,thread,nthreads,i);
} } else { //Enviar datos
MPI_Send(&position,1,MPI_INT,0,ENVIO_FINAL,MPI_COMM_WORLD);
MPI_Send(&thread,1,MPI_INT,0,ENVIO_FINAL_THR,MPI_COMM_WORLD);
MPI_Send(&nthreads,1,MPI_INT,0,ENVIO_FINAL_NTHR,MPI_COMM_WORLD);
} MPI_Finalize(); }
11
Programación heterogénea

Algoritmos HoHe:
Un único proceso por procesador

Con un volumen heterogéneo de datos en cada proceso


Inconveniente: reprogramar los algoritmos
existentes para sistemas homogéneos
b0
b1
b2
b0
b1
b2
b0
b
b2
b0
1
12
Programación heterogénea

Algoritmos HeHo:




Un número distinto de procesos por procesador en
función de las velocidades relativas de los procesadores.
Se decide al lanzar la ejecución (en MPI usando el
fichero de máquinas)
Con un volumen homogéneo de datos en cada proceso
Ventaja: no es necesario reprogramar los
algoritmos existentes para sistemas homogéneos
Inconveniente: necesario obtener un método
automático y eficiente para mapear los procesos a
los procesadores.
Descargar