Multiplicacion de una matriz por un vector

Download Report

Transcript Multiplicacion de una matriz por un vector

Tres Algoritmos Paralelos para
Multiplicación Matriz Vector
Capitulo 8
Los Tres Algoritmos
para computar el producto matrizvector Ab=c
– Rowwise block striped
– Columnwise block striped
– Checkerboard block
Algoritmo Secuencial (cont)
• Entrada: una matríz
mXn a[0..m-1][0..n-1] y
un vector b[0..n-1]
• Salida: El producto a b
= c[0..m-1]
• for i←0 to m-1 do
c[i] ←0
for j←0 to n-1 do
c[i] ← c[i] + a[i,j] * b[j]
endfor
endfor
Complexidad:
O(mn)
Algoritmo I (Rowwise block striped
matrix)
• Descomposición de dominio
• Una tarea primitive está asociada con
- una fila de la matríz y
- el vector b entero
Un Paso del Algoritmo Paralelo
Producto interior
b
Fila i de A
b
Fila i of A
b
Fila i de A
ci
c
Comunicación All-gather
Aglomeración y Asignación de
Procesos
• Aglomerar grupos de filas
• Cada proceso tiene un bloque de filas y
todo de los vectores b y c
• La función read_row_striped_matrix
particiona la matriz A en p bloques de filas
y distribuye los bloques a los procesos
La idea del algoritmo
• Cada proceso computa un bloque de c
• La función replicate_block_vector hace
uso de MPI_Allgatherv para concatenar
los bloques de c y dejar el resultado en
cada uno de los procesadores.
MPI_Allgatherv
MPI_Allgatherv
int MPI_Allgatherv (
void
*send_buffer,
int
send_cnt,
MPI_Datatype send_type,
void
*receive_buffer,
int
*receive_cnt,
int
*receive_disp,
MPI_Datatype receive_type,
MPI_Comm
communicator)
Algoritmo II (Columnwise block
striped matrix)
• Descomposición de dominio
• Una tarea primitive está asociada con
- una columna de la matríz y
- un bloque apropiado del vector b
Multiplications
b
Column i of A
Column i of A
Phases of Parallel Algorithm
b
~c
b
c
Reduction
Column i of A
Column i of A
All-to-all exchange
b
~c
Leer una matriz en forma de
bloques de columnas
Archivo
Aglomeración y Asignación de
Procesos
• Aglomerar grupos de columnas
• Cada proceso tiene un bloque de columnas, un
bloque de b y un producto interior y todo de los
vectores b y una suma parcial de c
• La función read_col_striped_matrix particiona la
matriz A en p bloques de columnas y distribuye
los bloques a los procesos. Para esto hace uso
de la función MPI_Scatterv
MPI_Scatterv
MPI_Scatterv
int MPI_Scatterv (
void
*send_buffer,
int
*send_cnt,
int
*send_disp,
MPI_Datatype send_type,
void
*receive_buffer,
int
receive_cnt,
MPI_Datatype receive_type,
int
root,
MPI_Comm
communicator)
La fase computacional
• Cada proceso multiplica su bloque de
columnas por su bloque de b y asi
computa una suma parcial de c.
• El resultado final será la suma de estas
sumas parciales.
• Para efectuar la suma de las sumas
parciales, se puede aplicar
comunicaciones alltoall
All-to-all Exchange (Before)
P0
P1
P2
P3 P4
All-to-all Exchange (After)
P0
P1
P2
P3 P4
MPI_Alltoallv
int MPI_Alltoallv (
void
*send_buffer,
int
*send_cnt,
int
*send_disp,
MPI_Datatype send_type,
void
*receive_buffer,
int
*receive_cnt,
int
*receive_displacement
MPI_Datatype receive_type,
MPI_Comm
communicator)
Algoritmo III
Descomposición Checkerboard
Diseño del Algoritmo
• Asociar una tarea primitiva con cada elemento
de la matríz A
• Cada tarea primitive hace una multiplicación
• Aglomerar tareas primitivas en bloques
rectangulares
• Procesos constituyen una parrilla bidimensional
• Distribuir el vector b en los procesos de la
primera columna de la parrilla
La Tareas después de la
Aglomeración
Los Pasos del Algoritmo
Redistribuir el Vector b
• Paso 1: Mover b de la primera columna a la primera fila
– Si p es un cuadrado
• Procesos en la primera columna envian sus
pedazos de b a procesos de la primera fila
– Si p no es un cuadrado
• Acumula (“gather”) b en el proceso (0, 0)
• El process (0,0) distribuye (“scatters” ) los pedazos
de b en los procesos en la primera fila
• Paso 2: Los procesos de la primera fila emiten los
pedazos de b dentro de las columnas
Comunicadores
• Comunicaciones colectivas envuelve
todos los procesos en un comunicador.
• Necesitamos hacer broadcasts y
reduciones dentro de subconjuntos de
procesos
• Necesitamos crear comunicadores para
hacer esto
• Crearemos comunicadores para procesos
en la misma fila o en la misma columna.
Comunicadores
Un comunicador consiste de
• un grupo de procesos
• un contexto
• atributos, que incluyen una topología
Para Crear una Parrilla Vitual de
Procesos
• MPI_Dims_create
– parametros de entrada
• número de procesos en la parrilla deseada
• número de dimensiones
• Devuelve el número de procesos en cada dim
• MPI_Cart_create
– Crea un comunicador con una topología
cartesiana
MPI_Dims_create
• int MPI_Dims_create(
int nodes, /*el número de procesos en
la parrilla*/
int dims, /* el número de dimensiones */
int *tamano/* el tamano de cada
dimension*/)
Ejemplo de MPI_DIMS_create
Supongamos que nos gustaria determinar las dimensiones
de una malla bidimensional balanceado que contiene p
proocesos. Esto se logra como sigue:
int p;
int tamano[2];
…
tamano[0]=0;tamano[1]=0;
MPI_Dims_create [p,2,tamano]
Despues de ejecutar este segmento de código,
MPI_Dim_create, tamano[0] contendra la cantidad de
filas y tamano[1] contendra la cantidad de columnas.
MPI_Cart_create
• Crea un comunicador con una topología cartesiana
MPI_Cart_create(
MPI_Comm com_viejo,
int dims,
int *size,/*un arreglo de tamaño dims*/
int *periodico, /*un arreglo de tamano
dims, periodico[j]=1 si se desea
“wraparound” en la dimension j*/
int reordenar, /*0 si rango en el nuevo
comunicador es lo mismo como en el viejo*/
MPI_Comm *com_cart)
Ejemplo de MPI_Cart_create
• Supongamos que
• el comunicador viejo es MPI_COMM_WORLD
• la malla tiene 2 dimensiones, que la función
MPI_Dims_create ya ha inicializado el arrelgo
tamano que contiene los tomaños de cada
dimensión
• no queremos “wraparounds”
• el rango de cada proceso es igual a su rango en
el comunicador viejo
Ejemplo de MPI_Cart_create(2)
MPI_Comm cart_comm;
int p;
int periodico[2];
int tamano[2];
…
tamano[0]=tamano[0]=0;
MPI_Dim_create(p,2,tamano)
periodico[0]=periodico[1]=0;
MPI_Cart_create(MPI_COMM_WORLD,2,tamano,
periodico,0);
Dos Funciones Relacionadas con
Parrillas
• MPI_Cart_rank
– Devuelve el rango del proceso, dada las
coordenadas del proceso en un comunicador
cartesiano
• MPI_Cart_coords
– Devuelve las coordenadas cartesianas de un
proceso, dado su rango.
MPI_Cart_rank
int MPI_Cart_rank (
MPI_Comm com,
int *coords,
int *rango)
MPI_Cart-coords
int MPI_Cart_coords (
MPI_Comm com,
/* In - Communicator */
int rango,
int dims,
int *coords)
Ejemplo
#include <stdio.h>
#include <mpi.h>
int main (int argc, char **argv)
{ MPI_Comm com_cart;
int id;
int p;
int tamano[2];
int periodo[2];
int coords[2];
MPI_Init (&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &p);
tamano[0]=tamano[1]=0;
MPI_Dims_create(p,2,tamano);
MPI_Cart_create(MPI_COMM_WORLD,2,size,periodo,1,&com_cart);
MPI_Comm_rank(com_cart,&id);
MPI_Cart_coords(com_cart,id,2,coords);
printf("id=%d, (%d,%d)\n",id,coords[0],coords[1]);
MPI_Finalize();
return 0}
MPI_Comm_split
• MPI_Comm_split(MPI_Comm com_viejo,
int particion,int orden_rango,
MPI_Comm *com_nuevo)
Particiona un comunicador existente
com_viejo en una o mas particiones.
Se agrupan todos los procesos que tienen
el mismo número particion
El rango en el nuevo comunicador se da
por orden_nuevo
Ejemplo
• En el ejemplo anterior, se puede hacer un
comunicador de la primera columna de
com_cart:
• MPI_Comm_split(com_cart,coords[1]==0,
coords[0],&com_col)
Leer un vector b de un archivo y
distribuirlo en com_col
• Hacer uso de read_block_vector en
MyMPI.c:
read_block_vector(argv[1],(void **) &b,
mpitype, &m, com_col);
Analisis de Complexidad
(presumiendo que m=n)
• Cada proceso hace su parte de la
computación: (n2/p)
• Redistribuir b: (n / p + log p(n / p )) =
(n log p / p)
• Reducción de los vectores de resultados
parciales: (n log p / p)
• La complexidad paralela total:
(n2/p + n log p / p)
Analisis de Isoeficiencia
• Complexidad Secuencial: (n2)
• Complexidad de comunicación:
(n log p / p)
• La función de Isoeficiencia:
n2  Cn p log p  n  C p log p
• M(n)=n2  M(C p log p)/p = C2 log2 p
Comparación de los tres Métodos
Algoritmo
Complexidad
Rowwise Block- (n2/p + n+log p)
Striped
Isoeficiencia
C2 p
Columnwise
Block-Striped
(n2/p + nlog p)
Checkerboard
(n2/p + n log p/ p) C2 log2 p
Cp