Tres Algoritmos Paralelos para Multiplicacin Matriz Vector Capitulo

  • Slides: 42
Download presentation
Tres Algoritmos Paralelos para Multiplicación Matriz Vector Capitulo 8

Tres Algoritmos Paralelos para Multiplicación Matriz Vector Capitulo 8

Los Tres Algoritmos para computar el producto matrizvector Ab=c – Rowwise block striped –

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 m. Xn a[0. . m-1][0. . n-1]

Algoritmo Secuencial (cont) • Entrada: una matríz m. Xn 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 Complexidad: O(mn)

Algoritmo I (Rowwise block striped matrix) • Descomposición de dominio • Una tarea primitive

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

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

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

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

MPI_Allgatherv int MPI_Allgatherv ( void *send_buffer, int send_cnt, MPI_Datatype send_type, void *receive_buffer, int *receive_cnt,

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

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 Phases of Parallel Algorithm b ~c b c

Multiplications b Column i of A Phases of Parallel Algorithm b ~c b c Reduction Column i of A All-to-all exchange b ~c

Leer una matriz en forma de bloques de columnas Archivo

Leer una matriz en forma de bloques de columnas Archivo

Aglomeración y Asignación de Procesos • Aglomerar grupos de columnas • Cada proceso tiene

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

MPI_Scatterv int MPI_Scatterv ( void *send_buffer, int *send_cnt, int *send_disp, MPI_Datatype send_type, void *receive_buffer,

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

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) P 0 P 1 P 2 P 3 P 4

All-to-all Exchange (Before) P 0 P 1 P 2 P 3 P 4

All-to-all Exchange (After) P 0 P 1 P 2 P 3 P 4

All-to-all Exchange (After) P 0 P 1 P 2 P 3 P 4

MPI_Alltoallv int MPI_Alltoallv ( void *send_buffer, int *send_cnt, int *send_disp, MPI_Datatype send_type, void *receive_buffer,

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

Algoritmo III Descomposición Checkerboard

Diseño del Algoritmo • Asociar una tarea primitiva con cada elemento de la matríz

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

La Tareas después de la Aglomeración

Los Pasos del Algoritmo

Los Pasos del Algoritmo

Redistribuir el Vector b • Paso 1: Mover b de la primera columna a

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

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 •

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 •

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

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

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,

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

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 periodico[2]; int tamano[2]; … tamano[0]=0; MPI_Dim_create(p, 2, tamano)

Ejemplo de MPI_Cart_create(2) MPI_Comm cart_comm; int periodico[2]; int tamano[2]; … 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

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_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

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) {

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

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

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

Leer un vector b de un archivo y distribuirlo en com_col • Hacer uso de read_block_vector en My. MPI. 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

Analisis de Complexidad (presumiendo que m=n) • Cada proceso hace su parte de la computación: (n 2/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: (n 2/p + n log p / p)

Analisis de Isoeficiencia • Complexidad Secuencial: (n 2) • Complexidad de comunicación: (n log

Analisis de Isoeficiencia • Complexidad Secuencial: (n 2) • Complexidad de comunicación: (n log p / p) • La función de Isoeficiencia: n 2 Cn p log p n C p log p • M(n)=n 2 M(C p log p)/p = C 2 log 2 p

Comparación de los tres Métodos Algoritmo Complexidad Rowwise Block- (n 2/p + n+log p)

Comparación de los tres Métodos Algoritmo Complexidad Rowwise Block- (n 2/p + n+log p) Striped Isoeficiencia C 2 p Columnwise Block-Striped (n 2/p + nlog p) Checkerboard (n 2/p + n log p/ p) C 2 log 2 p Cp