Mpi Spanish
Mpi Spanish
Alumno: Vicente F. Reyes Puerta Director: Jose Antonio Jimnez Milln Julio 2003
Resumen
El presente documento realiza un estudio de investigacin que aborda el procesamiento paralelo en redes de ordenadores. De esta manera se analiza la utilizacin de los clusters (grupos de ordenadores conectados en red) a modo de computador virtual paralelo como plataforma para la ejecucin de aplicaciones paralelas. El entorno utilizado para realizar dicho estudio es el sistema operativo Linux, el cual ofrece todas las facilidades de acceso a dispositivos y comunicacin necesarias para la ejecucin de los algoritmos paralelos. Para la implementacin de los algoritmos paralelos desarrollados hemos utilizado la interfaz MPI (Message Passing Interface, Interfaz de Paso de Mensajes). Dicha interfaz es un estndar que dene la sintaxis y la semntica de las funciones contenidas en una librera de paso de mensajes diseada para ser usada en programas que exploten la existencia de mltiples procesadores. De este modo no slo conseguimos que el desarrollo de los algoritmos sea ms claro y sencillo, si no que adems logramos que sean portables. El estudio realizado queda dividido en tres partes diferenciadas que coinciden con la estructura del documento. En un principio hacemos un estudio general sobre el procesamiento paralelo, y establecemos una clasicacin detallada sobre los distintos tipos de paralelismo existentes en la actualidad. En la segunda parte realizamos un anlisis detallado de la interfaz de paso de mensajes MPI, ejemplicando la informacin ofrecida con diversos algoritmos escritos en C que realizan cmputos paralelos utilizando dicha interfaz. Por ltimo generamos un estudio de los resultados obtenidos en las ejecuciones explicando paso a paso la manera en la que han sido cosechados.
ndice general
Objetivos Desarrollo
I III
1
3 3 4 4 5 6 6 7 9 9 13 15 19 19 26 37 38 43 43 43 46 49 49 50 51 52 53
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
NDICE GENERAL
II
Gua MPI
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
55
57 57 58 59 62 62 62 63 64 64 67 67 68 69 69 70 70 71 73 73 74 76 77 78 79 80 80 80 86 93 93 94 96 97 98 105 105 106 107 110
3. El Estndar MPI 3.1. Origen . . . . . . 3.2. Historia . . . . . 3.3. Objetivos . . . . 3.4. Usuarios . . . . 3.5. Plataformas . . . 3.6. Versiones . . . . 3.6.1. MPI-1 . . 3.6.2. MPI-2 . . 3.7. Implementaciones
4. Conceptos Bsicos 4.1. Algoritmo Hola Mundo! . . . . . . . . . 4.2. Programas MPI en General . . . . . . . . 4.3. Informndonos del Resto del Mundo . . . 4.4. El Problema de la Entrada/Salida . . . . . 4.5. Ubicacin de los Procesos . . . . . . . . 4.6. Informacin Temporal . . . . . . . . . . 4.7. Implementacin Algoritmo Hola Mundo!
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
5. Paso de Mensajes 5.1. Algoritmo Clculo de reas mediante Montecarlo . . . 5.2. El Entorno del Mensaje . . . . . . . . . . . . . . . . . 5.3. Funciones de Paso de Mensajes Bloqueantes . . . . . . 5.4. Funciones de Paso de Mensajes No Bloqueantes . . . . 5.5. Agrupaciones de Datos . . . . . . . . . . . . . . . . . 5.5.1. Tipos Derivados . . . . . . . . . . . . . . . . 5.5.2. Vectores . . . . . . . . . . . . . . . . . . . . . 5.6. Implementacin Clculo de reas mediante Montecarlo 5.6.1. Implementacin con Mensajes Bloqueantes . . 5.6.2. Implementacin con Mensajes No Bloqueantes 6. Comunicacin Colectiva 6.1. Algoritmo Regla del Trapecio . . . . . 6.2. Distribucin y Recoleccin de los Datos 6.3. Operaciones de Comunicacin Colectiva 6.4. Operaciones de Reduccin . . . . . . . 6.5. Implementacin Regla del Trapecio . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
7. Comunicadores y Topologas 7.1. Algoritmo Multiplicacin de Matrices de Fox . . . . 7.2. Comunicadores . . . . . . . . . . . . . . . . . . . . 7.3. Trabajando con Grupos, Contextos y Comunicadores 7.4. Particionamiento de los Comunicadores . . . . . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
NDICE GENERAL
7.5. Topologas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 7.6. Divisin de Rejillas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 7.7. Implementacin Multiplicacin de Matrices de Fox . . . . . . . . . . . . . . 114
125
127 127 128 128 129 129 130 130 131 132 133 135 136 140 143 143 144 146 147 148 148 149 149 149 149 151 154 159 163 164 165 165 166 166 167 168 170
9. Evaluacin de los Algoritmos 9.1. Herramientas de Monitorizacin . . . . . . . . . . . . . . . . . . . . . . 9.1.1. Ficheros de Recorrido . . . . . . . . . . . . . . . . . . . . . . . 9.1.2. Trazado de la Ejecucin . . . . . . . . . . . . . . . . . . . . . . 9.1.3. Animacin en Tiempo Real . . . . . . . . . . . . . . . . . . . . 9.2. Criterios de Evaluacin . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2.1. Tiempo de Ejecucin . . . . . . . . . . . . . . . . . . . . . . . . 9.2.2. Nmero de Procesadores . . . . . . . . . . . . . . . . . . . . . . 9.2.3. Coste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3. Resultados Obtenidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3.1. Algoritmo Clculo de reas mediante Montecarlo Bloqueante . . 9.3.2. Algoritmo Clculo de reas mediante Montecarlo No Bloqueante 9.3.3. Algoritmo Regla del Trapecio . . . . . . . . . . . . . . . . . . . 9.3.4. Algoritmo Multiplicacin de Matrices de Fox . . . . . . . . . . . A. Instalacin, Conguracin y Manejo de MPICH A.1. Dispositivos . . . . . . . . . . . . . . . . . . A.2. Obtencin . . . . . . . . . . . . . . . . . . . A.3. Compilacin e Instalacin . . . . . . . . . . A.4. Conguracin . . . . . . . . . . . . . . . . . A.4.1. El Fichero de Mquinas . . . . . . . A.4.2. RSH . . . . . . . . . . . . . . . . . . A.4.3. SSH . . . . . . . . . . . . . . . . . A.4.4. Secure Server . . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
NDICE GENERAL
A.5. Compilacin y Enlace de Programas . . . . . . . . . . . . . . . . . . . . . . 171 A.6. Ejecucin de Programas con mpirun . . . . . . . . . . . . . . . . . . . . . . 172 A.7. Extensin MPE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
B. Manual de Referencia B.1. MPI_Bcast . . . . . . . . B.2. MPI_Cart_coords . . . . . B.3. MPI_Cart_create . . . . . B.4. MPI_Cart_rank . . . . . . B.5. MPI_Cart_sub . . . . . . . B.6. MPI_Comm_create . . . . B.7. MPI_Comm_group . . . . B.8. MPI_Comm_rank . . . . . B.9. MPI_Comm_size . . . . . B.10. MPI_Comm_split . . . . . B.11. MPI_Finalize . . . . . . . B.12. MPI_Get_processor_name B.13. MPI_Group_incl . . . . . B.14. MPI_Init . . . . . . . . . . B.15. MPI_Irecv . . . . . . . . . B.16. MPI_Isend . . . . . . . . . B.17. MPI_Recv . . . . . . . . . B.18. MPI_Reduce . . . . . . . B.19. MPI_Send . . . . . . . . . B.20. MPI_Sendrecv_replace . . B.21. MPI_Type_commit . . . . B.22. MPI_Type_struct . . . . . B.23. MPI_Type_vector . . . . . B.24. MPI_Wait . . . . . . . . . B.25. MPI_Waitall . . . . . . . . B.26. MPI_Waitany . . . . . . . B.27. MPI_Wtime . . . . . . . . Conclusiones Bibliografa Direcciones URL
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 208 209
ndice de guras
1.1. 1.2. 1.3. 1.4. 1.5. 1.6. 1.7. 1.8. 1.9. 1.10. 1.11. 1.12. 1.13. 1.14. 1.15. 1.16. 1.17. 1.18. 1.19. Clasicacin Paralelismo Implcito . . . . . . . . . . Clasicacin Paralelismo Explcito . . . . . . . . . . Ciclo de Instruccin de 2 etapas (A) . . . . . . . . . Ciclo de Instruccin de 10 etapas . . . . . . . . . . . Ciclo de Instruccin de 2 etapas (B) . . . . . . . . . Cauce de 6 etapas . . . . . . . . . . . . . . . . . . . Procesamiento Digital de Seales . . . . . . . . . . . Esquema Multiprocesador . . . . . . . . . . . . . . Organizacin Bsica Bus de Tiempo Compartido . . Organizacin Bus de Tiempo Compartido con Cach Organizacin Memorias Multipuerto . . . . . . . . . Topologa Anillo . . . . . . . . . . . . . . . . . . . Topologa Malla . . . . . . . . . . . . . . . . . . . . Topologa rbol . . . . . . . . . . . . . . . . . . . . Topologa Hipercubo . . . . . . . . . . . . . . . . . Objetivo Procesamiento Paralelo en Clusters . . . . . Esquema Procesador Matricial . . . . . . . . . . . . Esquema Procesador Vectorial . . . . . . . . . . . . Cray SX-6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 7 9 10 11 12 16 19 20 21 22 27 27 27 28 30 37 40 41 44 47 51 57 74 75 95 132 134 135 137 139
2.1. Modelo Bsico para Paso de Mensajes . . . . . . . . . . . . . . . . . . . . . 2.2. Modelo Bsico para Memoria Compartida . . . . . . . . . . . . . . . . . . . 2.3. Esquema Bsico Utilizacin MPI . . . . . . . . . . . . . . . . . . . . . . . . 3.1. Logo MPI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1. Generacin Puntos Aleatorios . . . . . . . . . . . . . . . . . . . . . . . . . 5.2. Clculo Hipotenusa Punto Aleatorio . . . . . . . . . . . . . . . . . . . . . . 6.1. Procesos estructurados en rbol . . . . . . . . . . . . . . . . . . . . . . . . . 8.1. 8.2. 8.3. 8.4. 8.5. Grco Comunicacin Bloqueante . . . . . . . . . Comparacin Com.Bloqueante - No Bloqueante . . Comparacin Com. Participativa - No Participativa Comparacin Com. Solapada - No Solapada . . . . Grco Comunicacin Colectiva . . . . . . . . . . 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10 9.1. 9.2. 9.3. 9.4. 9.5. 9.6. 9.7. 9.8. 9.9. 9.10. 9.11. 9.12. 9.13.
NDICE DE FIGURAS
Animacin en Tiempo Real . . . . . . . . . . . . . . . . . . . Modelo Ejecucin Clculo de reas Bloqueante 8 Procesos . . Grco Tiempo Ejecucin Clculo de reas Bloqueante . . . Grco Coste Clculo de reas Bloqueante . . . . . . . . . . Modelo Ejecucin Clculo de reas No Bloqueante 8 Procesos Grco Tiempo Ejecucin Clculo de reas No Bloqueante . Grco Coste Clculo de reas No Bloqueante . . . . . . . . Modelo Ejecucin Regla del Trapecio 8 Procesos . . . . . . . Grco Tiempo Ejecucin Regla del Trapecio . . . . . . . . . Grco Coste Regla del Trapecio . . . . . . . . . . . . . . . . Comparacin Tiempos de distintas Cantidades de Procesos . . Comparacin Costes de distintas Cantidades de Procesos . . . Modelo Ejecucin Algoritmo de Fox 9 Procesos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 150 152 152 153 155 155 156 158 158 160 160 161
ndice de cuadros
1.1. Dimetros Topologas Hipercubo y Malla . . . . . . . . . . . . . . . . . . . 1.2. Ejemplos Computadores Vectoriales . . . . . . . . . . . . . . . . . . . . . . 5.1. Tipos de Datos MPI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1. Operaciones de Reduccin . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 42 76 98
7.1. Particin Matriz 6*6 en 9 Procesos . . . . . . . . . . . . . . . . . . . . . . . 106 7.2. Topologa Fsica 3*3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 9.1. 9.2. 9.3. 9.4. Evaluacin Clculo de reas Bloqueante . . . Evaluacin Clculo de reas No Bloqueante . Evaluacin Regla del Trapecio . . . . . . . . Evaluacin Multiplicacin de Matrices de Fox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 154 157 159
11
12
NDICE DE CUADROS
ndice de algoritmos
4.1. 5.1. 5.2. 6.1. 7.1. Hola Mundo! . . . . . . . . . . . . . . . . . . . . . . . Clculo de reas mediante Montecarlo (Bloqueante) . . Clculo de reas mediante Montecarlo (No Bloqueante) Regla del Trapecio . . . . . . . . . . . . . . . . . . . . Multiplicacin de Matrices de Fox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 . 81 . 86 . 98 . 114
13
14
NDICE DE ALGORITMOS
Objetivos
El objetivo principal del presente proyecto de investigacin consiste en demostrar la utilidad y potencialidad del procesamiento paralelo, concretamente en lo relativo a su aplicacin en clusters (redes de computadores). Debemos probar con resultados reales y anlisis grcos la mejora en el rendimiento que produce la ejecucin paralela de determinados algoritmos.
Con el objeto de delimitar el campo de estudio lo primero que debemos hacer es situar el paralelismo basado en redes dentro de la amplia variedad de sistemas dedicados al procesamiento paralelo. Propondremos una clasicacin para los distintos tipos de paralelismo existentes en la actualidad, y explicaremos las caractersticas principales de cada uno de ellos. Un aspecto bsico para el desarrollo de la investigacin consiste en disear e implemetar un conjunto de algoritmos paralelos que pongan en prctica los tipos de comunicacin ms importantes que se dan en el procesamiento paralelo basado en redes. Para lograr este objetivo estudiaremos las caracterticas ms importantes de MPI (Message Passing Interface, Interfaz de Paso de Mensajes) y emplearemos dicha interfaz en el desarrollo de diversos algoritmos paralelos. Por ltimo haremos un estudio detallado de los resultados obtenidos en las ejecuciones de los algoritmos desarrollados, explicando paso a paso la manera en la que han sido realizados.
I
II
OBJETIVOS
Dichos resultados sern utilizados para la generacin de grcos que nos ayuden a entender las importantes ventajas que nos aporta el procesamiento paralelo.
Desarrollo
A continuacin explicaremos detenidamente el desarrollo de la investigacin llevada a cabo para la realizacin del presente proyecto. Dicho desarrollo coincide en la prctica con la estructura del documento realizado.
La tcnicas de paralelismo implcito estn dirigidas al reforzamiento del nivel de concurrencia dentro de la CPU, de manera que queda oculta a la arquitectura del ordenador. Por lo tanto pueden ser vistos como sistemas de un slo procesador.
El paralelismo explcito o de alto nivel hace referencia a aquellos sistemas en los cuales se interconectan varios procesadores para cooperar en la ejecucin de los programas de aplicacin. Se trata de sistemas que ofrecen una infraestructura explcita para el desarrollo del software del sistema y aplicaciones que exploten el paralelismo. A este tipo de paralelismo dedicaremos el resto de la investigacin, centrndonos concretamente en las arquitecturas MIMD con memoria distribuida.
III
Paralelismo Implcito
Segmentacin
Mltiples ALUs
Procesadores Auxiliares
IV
DESARROLLO
Paralelismo Explcito
MISD
(Procesadores Vectoriales)
SIMD
(Procesadores Matriciales)
MIMD
Una vez resuelto el sistema de intercomunicacin fsica de los equipos, deben abordarse los mecanismos para lograr la coordinacin entre los procesadores. En el captulo 2 analizamos las caractersticas bsicas de los dos modelos de interaccin entre procesadores (paso de mensajes y memoria compartida), para luego centrarnos en las utilidades de desarrollo de software paralelo ms populares que existen en la actualidad: PVM, MPI, p4, Express y Lynda.
Gua MPI
La segunda parte de nuestro estudio se centra en la utilizacin de la interfaz MPI (Message Passing Interface, Interfaz de Paso de Mensajes) para el desarrollo de aplicaciones paralelas. El estudio de la interfaz MPI comienza en el captulo 3 con una explicacin sobre el origen y la motivacin que promovieron la creacin del estndar. Por otro lado analizamos los contenidos del estndar, sus objetivos, su funcionamiento bsico y sus distintas versiones. Como vemos en la gura 3, MPI es implementado normalmente como interfaz de comunicaciones, utilizando las facilidades ofrecidas por el sistema que vayamos a usar (comunicacin va sockets, operaciones de memoria compartida, etc).
MPI_Send() MPI_Recv()
MPI SO
MPI SO
A continuacin en el captulo 4 vemos los conceptos bsicos sobre la utilizacin de MPI para el desarrollo de programas escritos en C. Todos los programas MPI comparten una serie de caractersticas. La inicializacin y nalizacin del entorno de ejecucin se llevan a cabo mediante funciones que explicaremos en este captulo. Tambin analizamos los mtodos para
identicar los procesos en ejecucin. Para ejemplicarlo escribiremos un sencillo programa en C que hace uso de funciones MPI para ejecutar una versin paralela del conocido algoritmo Hola Mundo!. El captulo 5 aborda la funcin ms importante y caracterstica del estndar MPI: el paso de mensajes. Se utiliza bsicamente para el intercambio de datos entre los procesos en ejecucin. En este captulo estudiamos las caractersticas ms importantes de los mensajes bloqueantes y no bloqueantes, aplicando dicha teora a la implementacin de un algoritmo diseado para el clculo de reas circulares. El algoritmo Clculo de reas mediante Montecarlo realiza una aproximacin del rea de una circunferencia con un radio determinado mediante la simulacin de variables aleatorias, empleando un mtodo estadstico (gura 4).
Las operaciones de comunicacin colectiva son aquellas que se aplican al mismo tiempo a todos los procesos pertenecientes a un comunicador. Tienen una gran importancia en el estndar MPI, debido a la claridad de su sintaxis y a su eciencia. En el captulo 6 analizamos su utilidad y conveniencia implementando el algoritmo Regla del Trapecio de manera que haga un uso inteligente de dichas operaciones. El captulo 7 aborda el uso de comunicadores y topologas. Esta caracterstica hace a MPI diferente de la mayora de los dems sistemas de paso de mensajes. En pocas palabras, un comunicador es una coleccin de procesos que pueden mandarse mensajes entre ellos. Una topologa es una estructura impuesta en los procesos de un comunicador que permite a los procesos ser direccionados de diferentes maneras. Para ilustrar estas ideas desarrollaremos el cdigo que implementa el algoritmo de Fox para multiplicar dos matrices cuadradas mediante su subdivisin en una serie de procesos (cuadro 1).
VI
DESARROLLO
determinado sistema paralelo, lo primero que debemos hacer es medir el rendimiento de dicho sistema. Dicha medicin se realiza a travs de herramientas especializadas en el anlisis, de modo que podemos saber fcilmente y con seguridad cunto de apropiado es el sistema para la ejecucin de determinados algoritmos paralelos. En las guras 6 y 7 mostramos el rendimiento del sistema en la ejecucin de paso de mensajes bloqueantes y operaciones de comunicacin colectiva, respectivamente.
Comunicacion Bloqueante 1200 Com.Bloqueante
1000
600
400
200
# # ! "# # '! ! !
# # (! '!
Proceso 6
Proceso 7
&
%
Proceso 3
Proceso 4
# ! $ # " !
Proceso 5
Proceso 0
Proceso 1
Proceso 2
VII
140000
120000
Tiempo (micro-seg)
100000
80000
60000
40000
20000
0 0 2 4 6 8 Num.Procesos 10 12 14 16
El captulo 9 aborda el estudio de los resultados obtenidos en las ejecuciones explicando paso a paso la manera en la que han sido cosechados. Dichos resultados los analizaremos ms detenidamente en el apartado de conclusiones, ya que nos ayudan a demostrar el xito del presente proyecto de investigacin.
VIII
DESARROLLO
Parte I
Captulo 1
Introduccin
Denimos como procesamiento paralelo al concepto de agilizar la ejecucin de un programa mediante su divisin en fragmentos que pueden ser ejecutados simultneamente, cada uno en un procesador. De este modo un programa que se ejecute en procesadores podra ejecutarse veces ms rpido que usando un solo procesador, al menos en teora...
Aplicaciones con suciente paralelismo como para hacer bueno el uso de mltiples procesadores. El problema radica en identicar las porciones de programa que puedan ser ejecutadas independiente y simultneamente en procesadores separados; sto en realidad es complejo, ya que encontraremos aplicaciones que podran ser ejecutadas en paralelo y sin embargo se ralentizan al ser paralelizadas en un sistema particular. Por ejemplo, un programa que tarda 4 segundos en ser ejecutado en una sola mquina podra tardar 1 segundo de procesamiento en cada uno de los cuatro procesadores disponibles en una red, pero no lograramos nada si la coordinacin entre dichos procesadores tardase ms de 3 segundos.
Implementaciones de algoritmos que o bien ya son paralelos (escritos para obtener las ventajas del procesamiento paralelo) o bien esperamos paralelizar nosotros mismos, codicando de nuevo al menos alguna de sus partes.
Si nos encontramos en alguno de estos casos veremos que el procesamiento paralelo puede proporcionarnos el rendimiento de un supercomputador, aplicado a algunos programas que realizan complejas operaciones u operan en grandes bloques de datos. Y lo que es ms, ello se puede lograr con hardware relativamente barato. Adems es posible utilizar dichos sistemas paralelos para la realizacin de otros trabajos cuando no estn ocupados con una tarea en paralelo. 3
CAPTULO 1. INTRODUCCIN
Si no es el procesamiento paralelo lo que se busca, pero queremos mejorar el rendimiento de nuestra aplicacin, se pueden hacer multitud de cosas. En aplicaciones secuenciales podemos usar un procesador ms rpido, aadir memoria al sistema, etc.
) 4210 3
lo mnimo que debe tardar la ejecucin de un segmento de cdigo para que su ejecucin en paralelo sea rentable, hablando en trminos de rendimiento computacional. Bsicamente si un segmento de cdigo se ejecuta en menos tiempo del que se emplea en transmitir su resultado (latencia), entonces ser ms rpido ejecutar dicho segmento de cdigo de manera secuencial en el procesador que necesita dicho resultado; de este modo la ejecucin secuencial evitara la sobrecarga en la comunicacin.
Todos los microprocesadores Intel x86 (a partir del 80386) siguen el modelo IA32, incluidos los ms recientes: Pentium, P6, Pentium 4, Pentium M y Xeon. AMD y Cyrix tambin desarrollan multitud de procesadores compatibles con la arquitectura IA32. Dado que Linux se desarroll en principio en procesadores IA32, y dado que sta fue la manera en que se centr en el mercado, es conveniente usar dicha denominacin IA32 para distinguir este tipo de procesadores de los PowerPC, Alpha, PA-RISC, MIPS, SPARC, etc. RAID Como en otras reas de rendimiento en los computadores, los diseadores de memorias de disco reconocen que si uno de los componentes slo puede alcanzar un determinado lmite, se puede conseguir una ganancia en prestaciones adicional usando varios de esos componentes en paralelo. En el caso de las memorias de disco, esto conduce al desarrollo de conjuntos de discos que operen independientemente y en paralelo. Siguiendo este principio, el esquema RAID (Redundant Array of Independent Disks, Conjunto Redundante de Discos Independientes) es una tecnologa sencilla para mejorar tanto el ancho de banda como la abilidad de la E/S a disco. Consta de 6 niveles independientes, desde 0 hasta 5. Estos niveles no implican una relacin jerrquica, pero designan diseos de arquitecturas diferentes que poseen tres caractersticas comunes:
Los modos de operacin La organizacin de la memoria La estructura de los registros El direccionamiento de los operandos Los tipos de datos El conjunto de instrucciones Interrupciones y excepciones
CAPTULO 1. INTRODUCCIN
Paralelismo Implcito
Segmentacin
Mltiples ALUs
Procesadores Auxiliares
Figura 1.1: Clasicacin Paralelismo Implcito 1. 2. 3. RAID es un conjunto de unidades fsicas de disco vistas por el sistema operativo como una nica unidad lgica. Los datos se distribuyen a travs de las unidades fsicas de un conjunto. La capacidad de los discos redundantes se usa para almacenar informacin de paridad, que garantice la recuperacin de los datos en caso de fallo de disco.
Los detalles de la caracterstica segunda y tercera cambian segn los distintos niveles de RAID. RAID 0 no soporta la tercera caracterstica. Linux soporta los estndares RAID 0, 1, 4 y 5 adems de hardware RAID especializado.
Segmentacin o pipeline: La ejecucin de cada instruccin se divide en una secuencia de etapas, de forma que varias instrucciones pueden ejecutarse en paralelo, cada una en una etapa distinta de su ejecucin. Mltiples Unidades Funcionales en el Procesador: La repeticin de ALUs permite una aproximacin superescalar, con la ejecucin paralela de varias instrucciones, todas en la misma etapa de su ejecucin. Un procesador superescalar es aquel en el que las instrucciones comunes (aritmtica entera y en punto otante, cargas, almacenamientos y bifurcaciones condicionales) pueden iniciar su ejecucin simultneamente y ejecutarse de manera independiente. Estas implementaciones plantean problemas complejos de
Paralelismo Explcito
MISD
(Procesadores Vectoriales)
SIMD
(Procesadores Matriciales)
MIMD
Figura 1.2: Clasicacin Paralelismo Explcito diseo relacionados con el cauce de instrucciones. En esta lnea, la tecnologa SWAR consiste en agilizar las operaciones en registros de enteros mediante la divisin de dichos registros en una serie de campos de igual longitud, asignando una ALU a cada uno de los campos y realizando la ejecucin paralelamente. En este caso se ejecuta la misma instruccin sobre distintos datos en paralelo.
Procesadores Auxiliares (Attached Processors): Los procesadores auxiliares son esencialmente computadores de propsito especco que se conectan a un sistema host o servidor para acelerar determinados tipos de cmputo. El ejemplo ms comn es el uso de procesadores de E/S, que liberan a la CPU de la responsabilidad del control detallado de las operaciones de E/S.
SISD (Single Instruction Single Data, Flujo de instrucciones nico y ujo de datos nico): Un procesador interpreta una secuencia de instrucciones para operar con los datos almacenados en una memoria. De este modo en cualquier momento slo se est ejecutando una nica instruccin. Esta categora responde a la arquitectura de Von Neumann, tambin llamados computadores serie escalares. SIMD (Single Instruction Multiple Data, Flujo de instrucciones nico y ujo de datos mltiple): Una nica instruccin es aplicada sobre diferentes datos al mismo tiempo. En las mquinas de este tipo un cierto nmero de elementos procesadores son controlados y sincronizados mediante una unidad de control. Cada elemento procesador tiene una memoria asociada, de manera que cada instruccin es ejecutada simultneamente por
CAPTULO 1. INTRODUCCIN
todos los elementos procesadores pero sobre un conjunto de datos diferentes. Debido a su utilidad en el procesamiento de matrices, a este tipo de mquinas se les llama procesadores matriciales.
En la organizacin MIMD, los procesadores son de uso general, puesto que deben ser capaces de procesar todas las instrucciones necesarias para realizar las transformaciones apropiadas de los datos. Las arquitecturas MIMD se pueden subdividir adems segn la forma que tienen los procesadores para comunicarse (gura 1.2). Si los procesadores comparten una memoria comn, entonces cada procesador accede a los programas y datos almacenados en la memoria compartida, y los procesadores se comunican unos con otros a travs de esa memoria. Este tipo de sistemas se conocen como multiprocesadores fuertemente acoplados o simplemente multiprocesadores. Si cada procesador tiene una memoria dedicada, entonces cada elemento de proceso es en s mismo un computador. La comunicacin entre los computadores se realiza a travs de caminos jos o mediante algn mecanismo de conmutacin de mensajes. Este tipo de sistemas se conocen como multiprocesadores dbilmente acoplados o multicomputadores.
MISD (Multiple Instruction Single Data, Flujo de instrucciones mltiple y ujo de datos nico): Varias instrucciones actan simultneamente sobre un nico trozo de datos. Este tipo de mquinas se pueden interpretar de dos maneras. En principio, podemos considerarlas como mquinas formadas por varias unidades de procesamiento, las cuales reciben instrucciones distintas que operan sobre los mismos datos. Esta clase de arquitectura ha sido clasicada por numerosos arquitectos de computadores como impracticable o imposible, y en estos momentos no existen ejemplos que funcionen siguiendo este modelo. Otra forma de interpretar el modelo MISD es considerarlo como una clase de mquinas donde un mismo ujo de datos uye a travs de numerosas unidades de procesamiento. Arquitecturas altamente segmentadas, como la que poseen los arrays sistlicos o los procesadores vectoriales, son clasicadas a menudo bajo esta categora. Estas arquitecturas realizan el procesamiento vectorial a travs de una serie de etapas, cada una ejecutando una funcin particular produciendo un resultado intermedio. La razn por la cual dichas arquitecturas son clasicadas como MISD es que los elementos de un vector pueden ser considerados como pertenecientes al mismo dato, y todas las etapas del cauce representan mltiples instrucciones que son aplicadas sobre ese vector.
MIMD (Multiple Instruction Multiple Data, Flujo de instrucciones mltiple y ujo de datos mltiple): Un conjunto de unidades de procesamiento ejecuta simultneamente diferentes secuencias de instrucciones sobre conjuntos de datos diferentes. Es la organizacin que poseen los sistemas multiprocesadores y multicomputadores en general. SPMD es una versin restringida de MIMD en la cual todos los procesadores ejecutan el mismo programa. Al contrario que SIMD, cada procesador ejecuta una secuencia de instrucciones diferente.
Captacin
Ejecucin
10
Indireccin
Indireccin
Captacin de instruccin
Solicitud de instruccin
Solicitud de operando
Ms de un operando
Ms de un resultado
Chequeo de interrupciones
Interrupcin
CAPTULO 1. INTRODUCCIN
Siguiente instruccin
Cadena o vector
No interrupcin
11
Esperar
Istruccin
Captacin
Ejecucin
Resultado
Descartar
Figura 1.5: Ciclo de Instruccin de 2 etapas (B) Si las etapas de captacin y ejecucin fueran de igual duracin, el tiempo de ciclo de instruccin se reducira a la mitad. Sin embargo si miramos ms atentamente el cauce de la gura 1.5 veremos que la duplicacin de la velocidad de ejecucin es poco probable por dos razones: 1. El tiempo de ejecucin ser generalmente ms largo que el tiempo de captacin. La ejecucin implicar la lectura y almacenamiento de los operandos y la realizacin de alguna operacin. De este modo la etapa de captacin puede tener que esperar algn tiempo antes de que pueda vaciar su buffer. Una instruccin de bifurcacin condicional hace que la direccin de la siguiente instruccin a captar sea desconocida. De este modo, la etapa de captacin debe esperar hasta que reciba la direccin de la siguiente instruccin desde la etapa de ejecucin. La etapa de ejecucin puede entonces tener que esperar mientras se capta la siguiente instruccin.
2.
La prdida de tiempo debida a la segunda razn puede reducirse haciendo una estimacin. Una regla simple es la siguiente: cuando una instruccin de bifurcacin condicional pasa de la etapa de captacin a la de ejecucin, la etapa de captacin capta la instruccin de memoria que sigue a la instruccin de salto. Entonces si el salto no se produce no se pierde tiempo. Si el salto se produce debe desecharse la instruccin captada y captar una nueva instruccin. Aunque estos factores reduzcan la efectividad potencial del cauce de dos etapas, se produce alguna aceleracin. Para conseguir una mayor aceleracin, el cauce debe tener ms etapas. Consideremos la siguiente descomposicin del procesamiento de una instruccin:
Captar Instruccin (Fetch Instruction, FI): Leer la supuesta siguiente instruccin en un buffer. Decodicar Instruccin (Decode Instruction, DI): Determinar el cdigo de operacin y los campos del operando. Calcular Operandos (Calculate Operands, CO): Calcular la direccin efectiva de cada operando fuente. Esto puede involucrar varios modos de direccionamiento: mediante desplazamiento, indirecto a travs de registro, indirecto u otros. Captar Operandos (Fetch Operands, FO): Captar cada operando de memoria. Los operandos en registros no tienen que ser captados.
12
1 Instruccin 1 Instruccin 2 Instruccin 3 Instruccin 4 Instruccin 5 Instruccin 6 Instruccin 7 Instruccin 8 Instruccin 9
FI
CAPTULO 1. INTRODUCCIN
2
DI FI
3
CO DI FI
4
FO CO DI FI
10
11
12
13
14
EO WO FO CO DI FI EO WO FO CO DI FI EO WO FO CO DI FI EO WO FO CO DI FI EO WO FO CO DI FI EO WO FO CO DI EO WO FO CO EO WO FO EO WO
Con esta descomposicin las diversas etapas tienen casi igual duracin. Por motivos de claridad asumamos que tienen igual duracin. La gura 1.6 muestra cmo un cauce de 6 etapas puede reducir el tiempo de ejecucin de 9 instrucciones de 54 a 14 unidades de tiempo. En realidad dicha simulacin es demasiado idealista. Para empezar no todas las instrucciones recorren las 6 etapas del cauce; por ejemplo, una instruccin de carga no necesita la etapa WO. Ello complica el hardware del cauce. Adems la mayora de los sistemas no permiten varios accesos a memoria simultneos, por lo que las etapas FI, FO y WO no podran ejecutarse al mismo tiempo. Otros factores como la dicultad en la ejecucin de la bifurcacin condicional ya comentada, o la espera que se produce en ciertas etapas cuando no todas las etapas son de igual duracin (lo cual es lo ms comn), complican el diseo y limitan la mejora de las prestaciones. Segn toda esta discusin precedente, puede parecer que cuanto mayor sea el nmero de etapas en el cauce, ms rpida ser la velocidad de ejecucin. Algunos diseadores del IBM S/360 observaron dos factores que frustran este aparente sencillo patrn de diseo de altas prestaciones, y que siguen siendo ciertos hoy da: 1. En cada etapa, hay algn gasto extra debido a la transferencia de datos de buffer a buffer y a la realizacin de varias funciones de preparacin y distribucin.
Ejecutar Instruccin (Execute Instruction, EI): Realizar la operacin indicada y almacenar el resultado, si lo hay, en la posicin de operando destino especicada. Escribir Operando (Write Operand, WO): Almacenar el resultado en memoria.
13
La cantidad de control lgico necesario para manejar dependencias de memoria y registros y para optimizar el uso del cauce aumenta enormemente con el nmero de etapas.
En denitiva, la segmentacin de instrucciones es una poderosa tcnica para aumentar las prestaciones pero requiere un diseo cuidadoso si se quieren obtener resultados ptimos con una complejidad razonable. La emergencia de la segmentacin y su temprana evolucin se produjo en la primera lnea de supercomputadores IBM. El modelo IBM 7030 (llamado computador a toda mecha) super en 100 veces la velocidad del computador ms rpido en produccin de aquella poca, el IBM 704. Dicho logro slo se pudo alcanzar mediante la segmentacin de instrucciones. Luego vinieron otros xitos como el IBM 360/91, el procesador 6502, y un largo etc. Hoy da todas las compaas implementan es sus procesadores este tipo de arquitectura.
Microunity Mediaprocessor SIGD (Single Instruction on Groups of Data, Instrucciones nicas en Grupos de Datos)
MDMX, pronunciado Mad Max (MIPS Digital Media eXtension, Extensiones Media Digital MIPS)
)6 875
14
CAPTULO 1. INTRODUCCIN
A diferencia de lo que sucede con las tres rmas que aceptaron las primitivas MMX (Intel/AMD/Cyrix), todos los los dems conjuntos de instrucciones son difcilmente comparables, y mutuamente incompatibles. Con el paso del tiempo las MMX tambin evolucionaron, generandose nuevas extensiones como las EMMX de Cyrix, las 3DNow! de AMD o las SSE y SSE2 de Intel, entre otras. 1.4.2.1. Utilidades de SWAR
Aunque todos los procesadores actuales son capaces de ejecutar al menos algn tipo de paralelismo basado en la tecnologa SWAR, la realidad es que ni siquiera los juegos de instrucciones SWAR ms desarrollados soportan paralelismo de carcter general. De hecho, muchos piensan que la diferencia de rendimiento entre un procesador Pentium y un Pentium MMX se debe ms a factores como el mayor tamao de la cach que a la aparicin de las MMX. As pues... para qu es realmente buena la tecnologa SWAR?
Es cierto que todas stas son restricciones muy duras, pero tambin es cierto que dicho tipo de paralelismo se da en muchos algoritmos paralelos (no slo en aplicaciones multimedia). Enfocada al tipo de paralelismo adecuado, la tecnologa SWAR puede ser ms eciente que utilizar SMPs o Clusters... y no cuesta nada utilizarla. 1.4.2.2. Soporte MMX Bajo Linux
Bajo Linux los procesadores IA32 son nuestro principal inters. Lo bueno es que tanto los AMD, como los Cyrix y los Intel tienen una base comn, las instrucciones MMX. Sin embargo el rendimiento de dichas instrucciones vara, y adems, actualmente cada rma tiene sus propias extensiones; por lo tanto programar un soporte para dichas instrucciones puede resultar algo engorroso. Existen tres mtodos para utilizar MMX en SWAR:
Operaciones sobre datos de tipo entero, cuanto ms pequeos mejor. Dos valores de 32 bits caben en un registro MMX de 64 bits, pero tambin lo hacen ocho caracteres de un byte o incluso un tablero de ajedrez con valores de un bit. Cuando un dato ocupa varios campos de un registro, determinadas operaciones (llamadas operaciones particionadas) se ven afectadas por interacciones entre los campos debido al acarreo/resto, etc. Por ello, cuanto menor sea el tamao de dichos enteros, ms limpias sern las operaciones y por lo tanto mejor aprovecharemos el parelismo generado por la repeticin de ALUs. Nota: En los juegos de instrucciones ms actuales, como lal EMMX, las 3DNow! o las SSE2, tambin se admiten operaciones sobre datos de tipo otante. Paralelismo SIMD o de vectores, en el cual la misma operacin es aplicada a todos los campos simultneamente. Hay maneras de anular la operacin en algunos campos seleccionados (enmascaramiento), pero ello complica el cdigo y disminuye el rendimiento. Referencias a memoria localizadas y regulares. SWAR en general y MMX en particular no obtienen buenos resultados utilizando accesos aleatorios. Reunir con dichos accesos un vector x[y] (donde y es un ndice de dicho vector) resulta demasiado costoso.
15
Utilizar una librera de funciones MMX ya desarrollada. En la Universidad de Purdue existe un grupo de trabajo (URL [15]) que ha desarrollado libreras adaptadas a varios juegos de instrucciones determinados. As, tenemos la librera libmmx diseada para las instrucciones MMX en general, la librera libxmmx para las Cyrix EMMX y la librera libsse para las Intel SSE. Tambin existe una librera un tanto curiosa, MMX Emulator (URL [7]), diseada para ejecutar programas que usen instrucciones MMX en procesadores que no tengan soporte para ellas. As, arman tener un 386 MMX... como sus realizadores apuntan, es lento pero funciona. Usar las instrucciones MMX directamente. Esto es algo complicado por dos razones. El primer problema es la portabilidad: no podremos ejecutar un programa as implementado en procesadores que no tengan soporte para MMX. El segundo problema es que el ensamblador para IA32 que utilicemos en Linux podra no soportar dichas instrucciones MMX. Utilizar un lenguage de alto nivel o un compilador que genere directamente las instrucciones MMX apropiadas. En este sentido, en la Universidad de Purdue (URL [15]) se ha desarrollado un lenguaje llamado SWARC y su compilador, el Scc, el cual est en permanente fase experimental, aunque disponible. Como sus autores sealan, Scc no pretende ser un producto de alta calidad en trminos de eciencia; en cambio proporciona una implementacin bsica del modelo SWAR. Por otro lado tenemos los compiladores de Intel (URL [4]) de C++ y Fortran para Linux, los cuales generan las instrucciones MMX deseadas de manera optimizada.
2.
3.
Antes de que nos desanime el hecho de trabajar por nuestra cuenta, es til entender que, aunque pueda ser dicultoso hacer que un PC bajo Linux acte como servidor de un determinado sistema, es una de las pocas plataformas adecuadas para este tipo de uso. Los PCs son buenos servidores por dos razones principalmente. La primera es su capacidad de ampliacin, de manera fcil y barata. Recursos como la memoria, discos, redes, etc. son aadidos a un PC de manera trivial. La segunda es su facilidad de interconexin a otros dispositivos a travs de sus interfaces estndar. No slo estn ampliamente disponibles los prototipos de los buses ISA y PCI si no que adems disponemos del puerto paralelo, el cual
16
CAPTULO 1. INTRODUCCIN
Figura 1.7: Procesamiento Digital de Seales ofrece un rendimiento razonable en un iterfaz independiente. Adems la separacin del espacio de E/S en los microprocesadores IA32 facilita la interconexin, proporcionando una proteccin hardware de las direcciones de E/S. Por otra parte Linux es un buen sistema operativo para crear un servidor. La disponibilidad de todo el cdigo fuente y la extensa documentacin existente son una ayuda tremenda, obviamente. Adems Linux proporciona una planicacin cercana al tiempo real, e incluso existe una versin de Linux en tiempo real desarrollada por FSMLabs (URL [3]). Pero lo que quizs es ms importante es el hecho de que a la vez que proporciona un entorno UNIX completo, Linux soporta herramientas de desarrollo que estn diseadas para ser ejecutadas bajo Microsoft DOS o Windows. Los programas MSDOS pueden ser ejecutados en Linux usando dosemu, el cual proporciona una mquina virtual protegida que ejecuta MSDOS. El soporte de Linux para los programas diseados para Windows 3.xx es an ms directo: software libre como wine. Este software (URL [21]) simula Windows 3.xx y Win32 lo sucientemente bien como para que la mayora de los programas se ejecuten correcta y ecientemente en un entorno UNIX/X. Las siguientes dos secciones arrojan ejemplos de sistemas paralelos que utilizan esta arquitectura que podran ser soportados bajo Linux. 1.4.3.2. Procesadores DSP
Un DSP (Digital Signal Processor, Procesador de Seales Digitales) es un tipo de microprocesador muy rpido y potente. Un DSP procesa los datos en tiempo real. Esta capacidad de tiempo real hace de los DSPs perfectos para aplicaciones que no pueden tolerar demoras. As, suelen emplearse en el Procesamiento Digital de Seales, un mtodo de procesamiento de seales del mundo real que utiliza tcnicas matemticas para realizar transformaciones o extraer informacin, como se muestra en la gura 1.7. Aqu tenemos algunas de las ventajas de dichos procesadores:
Operaciones de multiplicacin y suma en un slo ciclo Funcionamiento en tiempo real, simulacin y emulacin Flexibilidad Fiabilidad Aumenta rendimiento del sistema
17
Existe un prspero mercado para estos procesadores. Aunque estos chips fueron generalmente diseados para ser utilizados en sistemas de aplicacin especca, tambin pueden ser utilizados como magncos computadores paralelos auxiliares. Estos son los benecios de utilizar dichos procesadores como computadores paralelos auxiliares:
Muchas tarjetas de sonido y modems incluyen procesadores DSP que pueden ser accedidos mediante controladores de Linux sin ninguna dicultad. Lo difcil llega cuando utilizamos un sistema paralelo auxiliar que contenga cuatro o ms procesadores DSP... y eso es exactamente lo que nos interesa. Existen dos familias de procesadores DSP utilizados ampliamente para procesamiento paralelo: Texas Instruments TMS320 Muy populares durante mucho tiempo, resulta muy sencillo construir un procesador paralelo basado en el TMS320. Existen versiones del TMS320 slo para enteros y tambin para punto otante; los diseos ms antiguos usaban algn tipo inusual del formato punto otante de precisin simple, pero los nuevos modelos soportan los formatos IEEE. El antiguo TMS320C4x consigue hasta 80 Mops usando el formato punto otante simple precisin especco de Texas Instruments; en constraste, el TMS320C67x proporciona hasta 1Gop simple precisin o 420 Mops doble precisin para los clculos en formato punto otante IEEE. No slo es fcil congurar un grupo de estos chips como un multiprocesador, si no que adems existen chips multiprocesadores, como el TMS320C8x que combina en paralelo un procesador RISC maestro con unidad de punto otante IEEE a 100 Mops con dos o cuatro DSPs esclavos con unidad de entero.
Disminuye costes
Muchos de ellos, como los Texas Instruments TMS320 y los Analog Devices SHARC DSP, estn diseados para construir mquinas paralelas con poca o ninguna lgica de enlace. Son econmicos, especialmente por MIP o MFLOP. Incluyendo el coste de la lgica de soporte bsica, suele decirse que su coste es una dcima parte de lo que cuesta un procesador para PC con un rendimiento comparable. No utilizan mucha energa ni desprenden demasiado calor. Esto signica que es posible tener un grupo de estos chips alimentados por una fuente de alimentacin convencional para PCs, y encerrarlos dentro del chasis del PC sin que se convierta en un horno. Existen algunos elementos en los juegos de instrucciones de los DSP que los compiladores de alto nivel no suelen usar de manera apropiada, como por ejemplo la operacin Bit Reverse Addressing. Usando un sistema paralelo auxiliar, es posible compilar y ejecutar la mayora del cdigo en el servidor, ejecutando aquellos algoritmos que hacen un mayor consumo de tiempo en los DSPs. Dichos algoritmos pueden ser implementados mediante un cdigo cuidadosamente adaptado. Los procesadores DSP no estn diseados para ejecutar un sistema operativo UNIX, y generalmente no son muy buenos como procesadores de propsito general. Por ejemplo, muchos de ellos no tienen hardware de manejo de memoria. En otras palabras, funcionan mejor como clientes de un servidor de propsito ms general... como un PC bajo Linux.
18
CAPTULO 1. INTRODUCCIN
Analog Devices SHARC Estos chips pueden ser utilizados como un multiprocesador de 6 procesadores con memoria compartida y sin lgica de conexionado externa. Sistemas mayores pueden ser construidos usando 6 enlaces de 4 bits por chip. Muchos de los sistemas ms grandes son empleados en aplicaciones militares, y resultan econmicos. En esta lnea la compaa Integrated Computing Engines, llamada en la actualidad Media100, ofrece una gama de tarjetas PCI llamadas GreeICE y BlueICE, sta ltima ms actual. La primera versin (GreenICE) contiene una matriz de 16 procesadores SHARC y es capaz de proporcionar picos de velocidad de hasta 1,9 Gops usando el formato IEEE simple precisin. BlueICE triplica dicha velocidad, y su coste no es elevado.
1.4.3.3.
Si el paralelismo consiste en conseguir la mxima velocidad, por qu no construimos nuestro propio hardware? El problema es que cuesta mucho, lleva mucho tiempo su desarrollo, se vuelve inservible cuando cambiamos el algoritmo aunque sea slo un poco, etc. Sin embargo recientes avances en los FPGAs (Field Programmable Gate Array, Matriz de Compuertas Lgicas Programable) elctricamente reprogramables han anulado dichas objeciones. Ahora la densidad de compuertas es lo sucientemente alta como para un procesador simple pueda ser construido en un nico FPGA. Adems el tiempo de reconguracin (reprogramacin) de los FPGAs ha bajado a un nivel en el que es razonable incluso recongurar el FPGA cuando pasamos de una fase de un algoritmo a otra. Normalmente debemos trabajar con lenguajes de descripcin de hardware como VHDL para la reconguracin del FPGA, as como escribir cdigo de bajo nivel que haga de interfaz con los programas del sistema host Linux. Pero el esfuerzo merece la pena, ya que el coste de los FPGAs es bajo, especialmente para algoritmos que operen con enteros de baja precisin (en realidad un subconjunto de aquellas operaciones para las que fu diseado SWAR). Los FPGAs pueden realizar complejas operaciones tan rpido como podamos introducir los datos. Por ejemplo, sistemas basados en un nico FPGA han alcanzado tiempos mejores que los supercomputadores en la bsqueda de bases de datos genticas. Las siguientes dos compaas desarrollan hardware basado en FPGA: Virtual Computer Company Esta compaa ofrece una variedad de productos que usan FPGAs Xilinx dinmicamente recongurables basados en SDRAM. Destaca su tarjeta Virtual ISA Proto Board de 8/16 bit para el puerto ISA. Altera El ARC-PCI (Altera Recongurable Computer PCI bus, Computador Recongurable Altera para bus PCI) es una tarjeta del mismo tipo que la Virtual ISA Proto Board de Virtual Computer Company, pero utiliza FPGAs Altera y el interfaz PCI en vez del ISA. Muchas de las herramientas de diseo, lenguajes de descripcin de hardware, compiladores, etc. funcionan slo bajo Windows o DOS, por lo que podramos utilizar dosemu o wine para ejecutarlos bajo Linux.
19
CPU
CPU
CPU
E/S
E/S
Interconexin
E/S
Memoria Principal
4.
La gura 1.8 describe en trminos generales la organizacin de un sistema multiprocesador. Hay dos o ms CPUs. Cada CPU es autnoma, incluyendo una unidad de control, una
20
CAPTULO 1. INTRODUCCIN
CPU
CPU
E/S
E/S
Memoria
Memoria
Figura 1.9: Organizacin Bsica Bus de Tiempo Compartido ALU, registros y posiblemente una cach. Cada CPU tiene acceso a una memoria principal compartida y a los dispositivos de E/S a travs de algn mecanismo de interconexin. Los procesadores pueden comunicarse entre s a travs de la memoria (mensajes de informacin de control almacenada en reas comunes de datos). Tambin es posible que las CPUs intercambien seales directamente, como indican las lneas discontinuas. La memoria a menudo se organiza de forma que sean posibles los accesos simultneos a bloques de memoria separados. En algunas conguraciones cada CPU puede tener tambin su propia memoria principal privada y sus canales de E/S adems de los recursos compartidos. 1.5.1.1. Organizacin
Bus de Tiempo Compartido El Bus de Tiempo Compartido es el mecanismo ms simple para construir un sistema multiprocesador (gura 1.9). La estructura y las interfaces son bsicamente las mismas que las de un sistema monoprocesador que utilice un bus para la interconexin. El bus consta de lneas de control, direccin y datos. Para facilitar las transferencias DMA (Direct Memory Access, Acceso Directo a Memoria) con los procesadores de E/S se proporcionan los siguientes elementos:
Direccionamiento: Debe ser posible distinguir los mdulos del bus para determinar la fuente y el destino del mensaje. Arbitraje: Cualquier mdulo de E/S puede funcionar temporalmente como maestro. Se proporciona un mecanismo para arbitrar entre las peticiones que compiten por el control del bus, utilizando algn tipo de esquema de prioridad.
21
E/S
E/S
Memoria
Memoria
Estos elementos son utilizables directamente en una conguracin de multiprocesador. En este caso hay varias CPUs adems de varios procesadores de E/S que intentan acceder a uno o ms mdulos de memoria a travs del bus. La organizacin de Bus de Tiempo Compartido presenta diversas ventajas en comparacin con otras aproximaciones:
La principal desventaja de la organizacin de bus compartido son las prestaciones. Todas las referencias a memoria pasan por el bus. En consecuencia, la velocidad del sistema est limitada por el tiempo de ciclo. Para mejorar las prestaciones es deseable equipar a cada CPU con una memoria cach (gura 1.10). sta reducira considerablemente el nmero de accesos. El uso de cachs introduce algunas consideraciones de diseo nuevas. Puesto que cada cach local contiene una imagen de una parte de la memoria, si se altera una palabra en una cach es posible que quede invalidada una palabra en otra cach. Para evitarlo debe avisarse a las otras CPUs de que se ha producido una actualizacin de la memoria. Esto por lo general complica el diseo del sistema. Memorias Multipuerto La organizacin de memorias multipuerto permite el acceso directo e independiente a los mdulos de memoria desde cada una de las CPUs y los mdulos de E/S (gura 1.11). Se necesitar un sistema de arbitraje para resolver los conictos. El mtodo que se utiliza a menudo para ello consiste en asignar prioridades jas a cada puerto de memoria. Normalmente
Tiempo Compartido: Cuando un mdulo est controlando el bus, los dems mdulos no tienen acceso al mismo y deben, si es necesario, suspender su funcionamiento hasta que dispongan del bus.
Simplicidad: Es la aproximacin ms sencilla para organizar el multiprocesador. La interfaz fsica y la lgica de cada procesador para el direccionamiento, el arbitraje, y para compartir el tiempo del bus es la misma que la de un sistema con un solo procesador. Flexibilidad: Es generalmente sencillo expandir el sistema conectando ms CPUs al bus. Fiabilidad: El bus es esencialmente un medio pasivo, y el fallo de cualquiera de los dispositivos conectados no provocara el fallo de todo el sistema.
22
CAPTULO 1. INTRODUCCIN
M1
M2
Mk
CPU1
E/S 1
CPUn
E/S m
Figura 1.11: Organizacin Memorias Multipuerto la interfaz fsica y elctrica en cada puerto es idntica a la que aparece en un mdulo de memoria de un slo puerto. As, se necesitan pocas o ninguna modicacin en las CPUs o en los mdulos de E/S para adaptarlas a este modelo de organizacin. La organizacin de memorias multipuerto es ms compleja que la organizacin de bus compartido, precisndose aadir al sistema una buena cantidad de lgica. No obstante se consiguen mejores prestaciones puesto que cada procesador tiene un camino especco a cada mdulo de memoria. Otra ventaja del multipuerto es que permite congurar partes de la memoria como privadas para una o ms CPUs y/o mdulos de E/S. Estas caractersticas permiten incrementar la seguridad frente a accesos no autorizados y para el almacenamiento de rutinas de restablecimiento en zonas de memoria no susceptibles de ser modicadas por otros procesadores. Unidad de Control Central La unidad de control central encauza las distintas secuencias de datos entre los distintos mdulos independientes: CPU, memoria, E/S. El controlador puede almacenar temporalmente peticiones y realizar las funciones de arbitraje y temporizacin. Adems puede transmitir mensajes de estado y control entre las CPUs y alertar sobre cambios en las cachs. Puesto que toda la lgica de coordinacin de la conguracin de multiprocesador se concentra en la unidad de control central, las interfaces de E/S, memoria, y CPU no sufren cambios esenciales. Esto proporciona la exibilidad y simplicidad de conexin propias de la aproximacin del bus compartido. Las desventajas clave de esta aproximacin son que la unidad de control es bastante compleja y que representa un cuello de botella potencial para las prestaciones.
23
SMP (Symmetric Multi-Processor, Multiprocesadores Simtricos) se reere, en trminos de sistemas operativos, al concepto de grupo de procesadores trabajando juntos como pares, de manera que cualquier parte del trabajo puede ser realizada por cualquiera de los procesadores sin diferencia alguna. Este tipo de sistemas son multiprocesadores, es decir, pertenecen al modelo MIMD con memoria compartida. En el mundo IA32, SMP signica cumplir con la norma MPS (Intel MultiProcessor Specication, Especicacin Multiprocesador de Intel). En un SMP todos los procesadores pueden acceder a la misma memoria, generalmente mediante un bus compartido de alta velocidad. La comunicacin entre los procesadores es fcil en principio. Cualquier procesador puede dejar datos o mensajes en una posicin determinada y luego indicar a otro procesador la direccin en la que puede encontrar los datos. Esto es tpico del multiprocesamiento; as, un computador ejecuta una o ms aplicaciones que se componen de una serie de procesos secuenciales que cooperan entre s. Este esquema se puede implementar en un sistema monoprocesador, pero tambin se puede implementar fcilmente en un sistema multiprocesador SMP: en cualquier momento cada uno de los mltiples procesadores est ejecutando un proceso distinto. La comunicacin entre procesos se realiza mediante mensajes y seales de estado que pueden intercambiarse los procesadores a travs de la memoria. En la prctica el nivel de prestaciones deseado complica la comunicacin entre los procesadores. Cuando se tienen muchos procesadores rpidos compitiendo por acceder a la misma memoria a travs del mismo bus, los conictos pueden degradar seriamente el rendimiento del conjunto del sistema. La solucin, como hemos visto, es aadir una cach local a cada procesador. Esta solucin ocasiona el problema adicional de la coherencia de cach. La coordinacin entre los procesadores que se requiere para resolver el problema origina un cuello de botella en el bus compartido. El resultado es que los multiprocesadores tpicos estn limitados a unas pocas decenas de procesadores. Un multiprocesador SMP con miles de procesadores no parece que sea muy prctico. 1.5.1.3. Soporte SMP Bajo Linux
Antes de entrar a discutir aspectos ms tcnicos, debemos hacernos primero un par de cuestiones acerca de esta arquitectura que, si bien es una de las ms extendidas en procesamiento paralelo, tiene un soporte relativamente reciente en Linux. Funciona realmente SMP en Linux? Funciona. Adems es una opcin con una buena relacin coste/rendimiento para paralelizar nuestro sistema, ya que una placa base con soporte para varios procesadores y sus correspondientes micros normalmente elevar poco el precio del sistema con respecto a un sistema uniprocesador. En la mayora de las ocasiones para hacer que Linux se ejecute en dicho hardware slo necesitamos realizar una instalacin de Linux con soporte para un solo procesador, y luego recompilar el ncleo con la la SMP=1 del chero Makele activa. Entonces informaremos a lilo o nuestro gestor de arranque acerca del nuevo ncleo compilado, y a disfrutar. En cuanto a rendimiento y estabilidad podemos decir son sistemas bastante rmes. En resumen, SMP Linux realmente funciona.
24
CAPTULO 1. INTRODUCCIN
La siguiente cuestin es cunto soporte de alto nivel est disponible para escribir y ejecutar programas paralelos con memoria compartida en SMP Linux. Actualmente existe bastante software dedicado a este propsito. Por ejemplo, ahora podemos contar con una librera muy completa para el manejo de hilos POSIX. Aunque el rendimiento puede ser menor que utilizando mecanismos especialmente creados para trabajar con memoria compartida, un sistema SMP Linux tambin puede usar la mayora del software de procesamiento paralelo desarrollado originalmente para clusters de estaciones de trabajo. Dicho tipo de software utiliza comunicacin va sockets, y puede funcionar en un sistema SMP Linux e incluso en mltiples SMP conectados en red formando un cluster. De todas formas la comunicacin va sockets implica mucha sobrecarga innecesaria en un sistema SMP. Gran parte de esta sobrecarga se produce dentro del ncleo y en el manejo de interrupciones; sto empeora el problema ya que SMP Linux generalmente slo admite un procesador en el ncleo al mismo tiempo y el manejador de interrupciones est implementado de manera que slo el procesador de arranque (boot processor) puede procesar interrupciones. A pesar de ello el hardware de comunicacin de un SMP tpico es tan superior a la mayora de las redes de comunicacin de los clusters, que el software diseado para dichos clusters a menudo funcionar mejor en los sistemas SMP que en los clusters para los que fu creado. En el resto de esta seccin estudiaremos qu tipo de sistemas SMP soporta Linux, aclararemos qu es la Especicacin Multiprocesador de Intel, y haremos algunas observaciones acerca del uso de la memoria cach y la conguracin del bus a utilizar. Especicacin Multiprocesador de Intel Aunque los sistemas SMP han existido desde hace muchos aos, hasta hace poco cada mquina tenda a implementar sus funciones bsicas de manera distinta al resto, de forma que el soporte del sistema operativo no era portable. Lo que ha cambiado esta situacin es la MPS (Intel MultiProcessor Specication, Especicacin Multiprocesador de Intel). Los nicos sistemas que no cumplen la norma MPS ni la IA32 y tienen soporte bajo Linux son las mquinas multiprocesador Sun4m de SPARC. Linux tiene soporte para la mayora de las mquinas que cumplen la norma MPS 1.1 y MPS 1.4 con hasta 16 procesadores 486DX, Pentium, Pentium Pro o superiores. Los procesadores IA32 que no tienen soporte son los procesadores Intel 386, Intel 486SX/SLC (la falta de unidad de punto otante interere en los mecanismos SMP) y los procesadores AMD y Cyrix (requieren chips de soporte SMP que no parecen estar disponibles por el momento). Es importante entender que el rendimiento de los sistemas que cumplen la norma MPS puede variar ampliamente. Como era previsto, una causa de las diferencias de rendimiento es la velocidad del procesador: mayores frecuencias de reloj tienden a proporcionar sistemas ms potentes, teniendo en cuenta que un procesador Pentium Pro es ms rpido que un Pentium. De todas formas la norma MPS no especica realmente cmo implementa el hardware la memoria compartida; lo que s especica es la manera en la que esta implementacin debe funcionar desde el punto de vista del software. Esto signica que el rendimiento est tambin en funcin de cmo interacta la implementacin de la memoria compartida con las caractersticas SMP Linux y nuestro sistema particular. La principal diferencia entre los sistemas que cumplen la norma MPS es la manera en la que implementan fsicamente el acceso a la memoria compartida.
25
Algunos sistemas MPS con procesadores Pentium y todos los que llevan procesadores Pentium Pro y superiores tienen cachs L2 (Level 2, De Nivel 2) independientes (la memoria cach L2 va dentro del mdulo que contiene el procesador). El hecho de tener cachs L2 separadas es considerado generalmente como una optimizacin del rendimiento; sin embargo sto no es tan obvio bajo Linux. La principal complicacin est en que el planicador de SMP Linux no intenta mantener cada proceso en el mismo procesador, siendo ste un concepto denominado anidad con el procesador. sto podra cambiar pronto; recientemente se han generado discusiones sobre el tema en la comunidad SMP Linux bajo el ttulo Enlace con el procesador. Sin anidad con el procesador, el hecho de tener cachs L2 separadas podra introducir una sobrecarga importante cuando le demos ciclos de reloj a un proceso en un procesador distinto al que estaba ejecutando dicho proceso anteriormente. Muchos sistemas relativamente econmicos estn organizados de manera que dos procesadores Pentium comparten una memoria cach L2. Lo malo es que sto provoca competencia entre los procesadores por el uso de la cach, degradando seriamente el rendimiento cuando se ejecutan mltiples programas secuenciales independientes. Sin embargo la mayora de los programas paralelos se benecian de la memoria cach compartida en situaciones en las que ambos procesadores intentan acceder a la misma lnea de la memoria compartida; en dichas situaciones slo uno de los procesadores debe acceder a la cach y la competencia entre los procesadores es evitada. De este modo se crea el efecto bsqueda compartida. Adems la falta de anidad con el procesador provoca menos dao con una cach L2 compartida. As, en programas paralelos no est realmente claro que la comparticin de cach L2 sea tan daina como cabe esperar. La experiencia demuestra que la cach de los sistemas SMP Linux muestran grandes diferencias en su rendimiento dependiendo del nivel de actividad del ncleo requerida. En el peor de los casos el aumento es 1.2 veces la velocidad del procesador. De todas maneras tambin se han observado picos de aumento de hasta 2.1 veces la velocidad del procesador, lo cual sugiere que el cmputo intensivo de cdigo con el modelo SPMD saca provecho del efecto bsqueda compartida. Conguracin del Bus Lo primero que hay que decir es que la mayora de los sistemas modernos conectan los procesadores (en turnos) a uno o ms buses PCI que hacen de puente hacia uno o ms buses ISA/EISA. Estos puentes aaden latencia, y adems los buses EISA e ISA ofrecen generalmente una menor velocidad de transferencia de datos que los PCI (ISA es el de menor velocidad), de manera que las unidades de disco, tarjetas de vdeo y otros componentes de alto rendimiento deben ser conectados al bus PCI. Aunque un sistema MPS puede alcanzar una buena velocidad en la ejecucin de muchos programas paralelos de cmputo intensivo (incluso si slo hay un bus PCI de tiempo compartido), las operaciones de E/S no se ejecutan mejor que en los sistemas uniprocesador... de hecho irn probablemente peor debido a la competencia por el bus entre los procesadores. As, si lo que buscamos es mejorar el rendimiento de las operaciones E/S debemos emplear un sistema MPS con mltiples buses PCI independientes y controladoras E/S (por ejemplo, mltiples controladoras SCSI). Antes que nada necesitaremos estar seguros de que SMP Lin-
26
CAPTULO 1. INTRODUCCIN
ux soporta el sistema que se desea emplear. Adems debemos tener en cuenta que actualmente Linux permite slo un procesador en el ncleo al mismo tiempo, de manera que elegiremos aquellas controladoras E/S que minimicen el tiempo requerido en el ncleo para realizar cada operacin E/S. Para conseguir un alto nivel de rendimiento tendremos que considerar la posibilidad de manejar la E/S de los dispositivos directamente, sin hacer llamadas al sistema... esto no es tan difcil como parece, y tampoco debera comprometer la seguridad. Es importante hacer notar que la relacin entre la velocidad del bus y la frecuencia de reloj del procesador se ha vuelto ms difusa durante los ltimos aos. Actualmente no es extrao encontrar sistemas con mayor frecuencia de reloj en el procesador y a la vez menor frecuencia en el bus, en comparacin con otros sistemas. El ejemplo clsico de sto es el Pentium 133, el cual usa generalmente un bus ms rpido que el Pentium 150, debido a la bsqueda de un mayor rendimiento en varios bancos de prueba. Estos efectos se amplican en los sistemas SMP. De todos modos, en la mayora de los casos es ms importante tener un bus rpido.
1.5.2. Multicomputadores
Un sistema multicomputador es aquel que est formado por un conjunto de sistemas relativamente autnomos, en los que cada CPU dispone de su propia memoria principal y sus canales de E/S. En este tipo de sistemas, cada procesador tiene su propio espacio de memoria privado, que no resulta visible para los otros procesadores. Segn sto los resultados y la informacin de coordinacin debe pasarse entre los nodos a travs de una red de interconexin, usualmente en forma de mensajes con un formato determinado. Una de las motivaciones principales para el desarrollo de organizaciones de multicomputador es la de superar las limitaciones de escala de los multiprocesadores; de ste modo los multicomputadores poseen una mayor escalabilidad. Se dene como escalabilidad de un sistema a su capacidad para responder a cargas de trabajo crecientes. En un sistema de procesamiento paralelo, se mide mediante el nmero de mquinas que pueden conectarse al sistema sin que el rendimiento del sistema caiga. El objetivo es desarrollar una organizacin escalable que pueda dar cabida a un amplio rango de nmero de procesadores. Puesto que los procesadores en un multicomputador deben comunicarse mediante el intercambio de mensajes, un elemento clave en el diseo es la red de interconexin, que debe realizarse para operar lo ms ecientemente posible. En general existe un compromiso entre la distancia mxima entre dos nodos y el nmero de conexiones fsicas que se desea en cada nodo. Se han explorado varias tecnologas de interconexin para proporcionar escalabilidad y hacer posible un comportamiento eciente. A continuacin describiremos las topologas ms extendidas:
@6 A9)
Anillo: Si la comunicacin es bidireccional a lo largo del anillo, entonces la distancia mxima entre dos nodos cualesquiera para un anillo de nodos es . Usualmente se utilizan paquetes de mensajes de tamao jo que contienen la direccin del destino deseado. Esta topologa es apropiada para un nmero relativamente pequeo de procesadores con una comunicacin de datos mnima. La gura 1.12 ilustra un anillo con cuatro nodos.
27
rbol: Las redes con topologa de rbol se han investigado para ejecutar algoritmos de tipo divide-y-vencers, tales como los de bsqueda y ordenacin. La gura 1.14 ilustra
) B %C)
Q @ 6 )D SA9FE@
Q I G )D RPHFE@
Malla: La forma ms simple de una malla es una matriz bidimensional en la que cada nodos, la distancia nodo se conecta a cuatro vecinos. En una malla simple de mxima entre dos nodos es . Si hay conexiones cclicas utilizando los nodos de los bordes, la distancia mxima se reduce a . La organizacin en malla es adecuada para ejecutar algoritmos orientados a matrices. La gura 1.13 ilustra una malla de 3*3 nodos.
28
CAPTULO 1. INTRODUCCIN
Figura 1.15: Topologa Hipercubo Nmero de nodos 16 256 1024 2048 16384 Malla 6 saltos 30 saltos 62 saltos 126 saltos 254 saltos Hipercubo 4 saltos 8 saltos 10 saltos 11 saltos 16 saltos
Cuadro 1.1: Dimetros Topologas Hipercubo y Malla un rbol binario sencillo. Hipercubos: Una topologa hipercubo utiliza procesadores distribuidos en un hipercubo de dimensin . Cada enlace tiene enlaces bidireccionales a nodos adyacentes. Tambin representa la distacia mxima entre dos nodos de dicho hipercubo. En la gura 1.15 mostramos un hipercubo de dimensin 4, con procesadores.
Desde la perspectiva de la implementacin hardware de una topologa, la topologa hipercubo es la ms atractiva. En el cuadro 1.1 comparamos la comunicacin en el peor caso en las topologas hipercubo y malla. El hipercubo se escala bien: el dimetro del sistema crece lentamente con el nmero de nodos, en comparacin con la malla. Recientemente ha surgido un inters creciente por pasar de topologas jas a topologas seleccionables por el usuario y controladas por una red de enrutamiento. En lugar de conectar todos los procesadores juntos mediante enlaces directos, se conectan a una red de enrutamiento rpida que utiliza conmutadores para establecer e interrumpir las conexiones virtuales, de una forma similar a la conmutacin de paquetes. Si los conmutadores se disean para que ocasionen retardos mnimos en los mensajes, el retardo de comunicacin se incrementar ligeramente al aadir ms nodos al sistema. Otra propiedad atractiva es que cada procesador necesita slo una conexin bidireccional a la red de conmutadores.
W XI @ T !
) U V@ T
29
Seguramente quedemos sorprendidos al comprobar que estos sistemas no necesitan CPUs de gama alta. La mayora de los mejores sistemas MPPs tienen miles de CPUs, siendo ms importante para el rendimiento del sistema la calidad de las interconexiones y su topologa. 1.5.2.1. Clusters o Agrupamientos de Nodos
Una de las posibilidades de mejor relacin coste/rendimiento es la proporcionada por los clusters, grupos de nodos conectados a travs de una interfaz de red. Dicha organizacin crea un sistema multicomputador, es decir, un sistema de procesamiento paralelo perteneciente al modelo MIMD con memoria distribuida. Por supuesto su tipologa puede ser muy variada, as como el soporte tanto hardware como software. Afortunadamente existe mucho y variado soporte software para el procesamiento paralelo usando PCs bajo Linux, gracias a la popularidad de esta tecnologa. La utilizacin de clusters en procesamiento paralelo supone muchas ventajas, como son:
Cada una de las mquinas de un cluster puede ser un sistema completo, que puede ser utilizado para ejecutar una amplia gama de aplicaciones. sto lleva a pensar que el procesamiento paralelo bajo clusters no es ms que una manera de aprovechar los ciclos desperdiciados por los usuarios de PCs. Sin embargo no es tan sencillo aprovechar estos ciclos sin ralentizar el trabajo primario para el que se utilizan dichas estaciones de trabajo, pero puede hacerse.
La creciente popularidad de los sistemas en red hace que la mayora del hardware que necesitamos para construir un cluster se fabrique a gran escala, con la correspondiente bajada de precios como resultado. Tambin reduce el coste del sistema el hecho de que slo necesitamos una consola (es decir, una tarjeta de vdeo, un monitor y un teclado) para todo el cluster, aunque necesitemos conectar dicha consola a cada mquina al principio para hacer una instalacin inicial; una vez hecha la instalacin, un PC bajo Linux no necesita una consola para funcionar. En comparacin, los SMP y los Procesadores Auxiliares pertenecen a mercados mucho ms restringidos, con lo que suelen tener precios ms elevados.
Clusters (o agrupamientos de nodos). Estos sistemas son grupos de nodos que se comunican a travs de una interfaz de red. Deben tener un buena relacin coste/rendimiento, por lo que en principio slo debemos utilizar para su montaje componentes hardware relativamente comunes. MPPs (Massively Parallel Processors, Procesadores Masivamente Paralelos). Estos sistemas pueden distinguirse de los anteriores por las propiedades que los hacen Masivamente Paralelos: Utilizacin de interconexiones de muy alto rendimiento Capacidad de E/S inmensa Tolerancia a fallos
30
CAPTULO 1. INTRODUCCIN
La conclusin es que los clusters son econmicos, que los dispositivos necesarios para construirlo estn disponibles, y que se pueden construir sistemas verdaderamente amplios; pero por supuesto no todo son ventajas. Tambin existen una serie de problemas:
Los clusters pueden llegar a formar sistemas verdaderamente amplios, no teniendo las limitaciones de escala de los SMP. Mientras que es complicado encontrar sistemas SMP compatibles con Linux con ms de 4 procesadores, podemos construir un cluster de hasta 16 sistemas con casi cualquier hardware de red comn. Con no mucho trabajo, cientos e incluso miles de mquinas pueden ser interconectadas. De hecho, Internet entero puede ser vista como un cluster verdaderamente gigantesco. El hecho de que sustituir un computador estropeado en un cluster sea trivial comparado con arreglar un SMP parcialmente estropeado hace que la disponibilidad sea mucho mayor en los clusters cuidadosamente diseados. sto es importante no slo en aplicaciones particulares que no toleren interrupciones en el servicio, si no que tambin en sistemas de uso general que contengan sucientes procesadores como para que sean muy comunes los fallos aislados. Por ejemplo, incluso cuando la media de fallo de un PC sea de dos aos, en un cluster con 32 mquinas la probabilidad de que una falle en los primeros 6 meses es muy alta.
Excepto muy pocas excepciones, el hardware de red no est diseado para el procesamiento paralelo. Normalmente la latencia es muy alta y la velocidad de transferencia de datos relativamente baja comparada con la proporcionada por los SMPs y los procesadores auxiliares. Por ejemplo, la latencia casi nunca supera unos pocos microsegundos en los SMPs, pero casi siempre es igual o mayor a cientos o miles de microsegundos en un cluster. La velocidad de transferencia de datos en los SMP es mayor de 100
31
Mbytes/seg; aunque el hardware de red ms rpido (Gigabyte Ethernet) ofrece una velocidad comparable, la mayora de las redes comunes son entre 10 y 1000 veces ms lentas. El rendimiento del hardware de red puede ser suciente si es una red aislada para cluster. Si la red no est aislada de otro trco, el rendimiento puede ser sustancialmente peor.
Con todo sto, podemos decir que los clusters ofrecen una gran potencia, pero dicha potencia puede ser difcil de alcanzar en la mayora de las aplicaciones. Lo bueno es que existe una gran cantidad de software que nos puede ayudar a conseguir un alto rendimiento en programas bien adaptados a este entorno, y que existen redes diseadas especcamente para ampliar el rango de programas que pueden alcanzar un buen rendimiento. 1.5.2.2. Sistemas Beowulf
Un sistema Beowulf es bsicamente un cluster dedicado al procesamiento paralelo. Es un sistema que usualmente consta de un nodo servidor y uno o ms nodos clientes conectados va Ethernet o algn otro tipo de red. Es un tipo de sistema que se construye empleando hardware comn, como por ejemplo PCs bajo Linux, adaptadores Ethernet estndar y hubs convencionales. No contiene ningn hardware especializado y es trivialmente reproducible. Adems Beowulf usa software comn como Linux, PVM y MPI. El nodo servidor controla todo el cluster y ofrece cheros a los nodos clientes. Tambin es la consola del cluster y su conexin al exterior. Los sistemas Beowulf ms grandes pueden tener ms de un nodo servidor, y posiblemente otros nodos dedicados a tareas particulares, por ejemplo consolas o estaciones de monitorizacin. En la mayora de los casos los nodos clientes no tienen dispositivos directos de E/S; son controlados y congurados por el nodo servidor. En una conguracin de clientes sin disco, los clientes no conocen su IP ni su nombre hasta que el nodo servidor se lo enva. Una de las principales diferencias entre un Beowulf y un COW(Cluster Of Workstations, Cluster de Estaciones de Trabajo) es que el comportamiento de un Beowulf es ms parecido al de una nica mquina que al de un grupo de estaciones de trabajo. En la mayora de los casos los clientes no tienen teclado ni monitor, y son accedidos slo a travs de login remoto o posiblemente mediante un terminal serie. Podemos pensar en los nodos de un sistema Beowulf como en paquetes CPU+Memoria que pueden ser agregados al cluster, de la misma manera que una CPU o un mdulo de memoria puede ser agregado a una placa base. Beowulf no es un paquete especial de software, ni una nueva topologa de red, ni la ltima modicacin del ncleo de Linux. Beowulf es una manera de crear clusters de PCs bajo Linux para formar un supercomputador virtual paralelo. Existen muchos paquetes software como modicaciones del ncleo de Linux, libreras PVM y MPI, y herramientas de conguracin que hacen la arquitectura Beowulf ms rpida, fcil de congurar y til. Sin embargo podemos construir una mquina de tipo Beowulf usando una distribucin estndar Linux sin software adicional. Si tenemos dos ordenadores con Linux en red que comparten un sistema de cheros
Existe poco soporte de software para manejar un cluster como si se tratara de un slo sistema. Por ejemplo, el comando ps nos informa de los procesos que concurren en un sistema Linux, pero no nos informa de todos los procesos que concurren en el cluster de sistemas Linux.
32
CAPTULO 1. INTRODUCCIN
/home va NFS (Network File System, Sistema de Ficheros en Red) y podemos ejecutar shell remoto (rsh) desde una mquina a otra, entonces podemos argumentar que tenemos un sistema Beowulf simple de dos nodos. Clasicacin Sistemas Beowulf En la prctica los sistemas Beowulf han sido construidos de distintas maneras. Debido a la bsqueda de un mayor rendimiento a veces han sido empleados componentes no comunes, como por ejemplo aquellos que son comercializados por slo un fabricante. Para tener en cuenta los diferentes tipos de sistemas existe la siguiente clasicacin. BEOWULF CLASE I: Este tipo de mquinas son construidas a base de componentes sacados del mercado comn. La denicin estricta es que un Beowuf CLASE I debe se ensamblado a partir de componentes que se puedan encontrar en al menos tres catlogos de publicidad nacionales o internacionales. Las ventajas de los sistemas de CLASE I son:
BEOWULF CLASE II: Un Beowulf de CLASE II es simplemente cualquier mquina que no pueda ser ensamblada utilizando nicamente hardware comn. sto no es un impedimento. De hecho sto es slo una clasicacin. Las ventajas de los sistemas de CLASE II son:
Una clase no tiene porqu ser necesariamente mejor que la otra. Todo depende de nuestras necesidades y nuestro presupuesto. sta clasicacin slo pretende que las discusiones sobre los sistemas Beowulf sean coherentes y detalladas.
El hardware est disponible en mltiples fuentes (bajo precio, fcil mantenimiento). Ausencia de dependencia con respecto a un nico fabricante. Soporte bajo Linux garantizado en sus distribuciones ms comunes. Usualmente basado en estndares (SCSI, Ethernet, etc.).
El soporte bajo Linux puede variar de una distribucin a otra. Existencia de dependencia con respecto a un nico fabricante. Suelen ser sistemas ms caros que los de CLASE I.
33
Las redes de ordenadores pertenecen a un campo en pleno auge. El desarrollo de las tecnologas y la aparicin de nuevos productos hacen que cada vez est ms al alcance de todos generar procesamiento paralelo a travs de un cluster. Sin embargo no existe una tecnologa de red que resuelva todos los problemas de la mejor manera; de hecho, la variedad de posibilidades, costes y rendimientos es tremenda. A continuacin deniremos las caractersticas de algunos de los tipos de red ms populares: ATM
Interfaz: PCI
Al menos en parte podra decirse que la tecnologa ATM (Asynchronous Transfer Mode, Modo de Transferencia Asncrona) es el futuro. ATM no tiene un coste elevado y es ms rpida que Fast Ethernet; adems puede ser usada a travs de las largas distancias que las compaas de telfono pueden cubrir. El protocolo de red ATM est diseado para proporcionar una interfaz software con poca sobrecarga y un manejo ms eciente de los mensajes pequeos y de las comunicaciones en tiempo real (p.ej. vdeo y audio digital). Adems es una de las redes con mayor velocidad de transferencia de datos que Linux soporta actualmente. Lo malo es que no es una tecnologa barata y que an existen algunos problemas de compatibilidad entre los distintos fabricantes. Ethernet
Interfaz: PCI
eca (db`
Latencia: 100
eca (db`
Soporte bajo Linux: controladores del ncleo, librera AAL Velocidad de Transferencia de Datos: 155 Mb/seg Latencia: 120
34
CAPTULO 1. INTRODUCCIN
Durante algunos aos, la Ethernet de 10 Mb/seg ha sido la tecnologa estndar de red. De hecho un gran nmero de PCs tienen su controladora Ethernet integrada en la placa base. En redes con poca carga podemos organizar las conexiones Ethernet como un bus multipuerto sin hub; esta conguracin puede servirnos para conectar hasta 200 ordenadores con un coste mnimo, pero no es apropiado para procesamiento paralelo. Aadir un hub compartido no va a mejorar el rendimiento en realidad. Sin embargo los hubs dedicados proporcionan la mxima velocidad de transferencia de datos a conexiones simultneas y no tienen un alto coste por ordenador. Linux soporta un amplio rango de interfaces Ethernet, pero es importante recordar que las variaciones en el hardware de la interfaz pueden suponer importantes diferencias en el rendimiento. Fast Ethernet
Interfaz: PCI
Aunque existen varias tecnologas que se llaman a s mismas Fast Ethernet este trmino se usa principalmente para referirnos a las Ethernet de 100 Mb/seg basadas en hub que son compatibles con los dispositivos y cables utilizados para las Ethernet 10 BaseT de 10 Mb/seg. Como podamos esperar esta tecnologa posee un enorme mercado, con lo cual su relacin prestaciones/precio es bastante mejor que en otras conguraciones. Sin embargo la trampa est en que al dividir el ancho de banda de un nico bus de 100 Mb/seg entre un grupo de ordenadores mediante un hub compartido, el rendimiento puede quedar por debajo del que obtendramos al utilizar una Ethernet de 10 Mb/seg con un hub dedicado, la cual proporciona a cada ordenador una conexin completa de 10 Mb/seg. Los hubs dedicados que proporcionan 100 Mb/seg a cada computador simultneamente son caros, aunque sus precios bajan a diario y proporcionan un rendimiento muy superior al que obtenemos utilizando los hubs compartidos. Gigabit Ethernet
Interfaz: PCI
eca f8b`
Latencia: 300
eca f8b`
Soporte bajo Linux: controladores del ncleo Velocidad de Transferencia de Datos: 100 Mb/seg Latencia: 80
35
En principio Gigabit Ethernet no tiene buenas razones tecnolgicas para ser llamada Ethernet. Sin embargo dicho nombre reeja la intencin de que en un futuro sea una tecnologa barata y destinada a un amplio mercado, con soporte nativo para IP. Sin embargo su precio actual hace que no resulte econmica su utilizacin. Al contrario que en otras tecnologas Ethernet, Gigabit Ethernet ofrece un control a bajo nivel que aporta abilidad a dicho tipo de red. Los FDRs (Full Duplex Repeaters, Repetidores Full Duplex) multiplexan las lneas utilizando buffers y control de ujo localizado para mejorar el rendimiento. La mayora de los hubs dedicados estn siendo construidos con nuevos mdulos interfaces para que sean compatibles con los dispositivos Gigabit. Existe un driver bajo Linux para la interfaz Yellown G-NIC de Packet Engines (URL [13]). Los primeros test bajo Linux arrojaron un ancho de banda unas 2,5 veces superior a la 100 Mb/seg Fast Ethernet; en las redes Gigabit la conguracin del bus PCI es un factor crtico. FireWire (IEEE 1394)
FireWire (URL [2]), el estndar IEEE 1394-1995, est destinado a ser la red digital de bajo coste y alta velocidad para consumidores en general. Aunque suela promocionarse como la interfaz a la cual conectar cmaras de vdeo digitales a nuestro ordenador, FireWire est pensada para ser utilizada en aplicaciones que van desde ser el sustituto de SCSI hasta conectar los componentes de reproduccin de vdeo y audio. Permite conectar hasta 64k dispositivos utilizando cualquier topologa que haga uso de buses y puentes sin ciclos, y automticamente detecta los componentes cuando son conectados o desconectados (conexin en caliente). Soporta mensajes cortos con baja latencia as como trasmisiones asncronas al estilo ATM (usadas para mantener sincronizados los mensajes multimedia). Adaptec tiene productos FireWire que permiten la conexin de hasta 63 dispositivos a una tarjeta PCI. Aunque FireWire no ser la red de mayor ancho de banda disponible dentro de un tiempo, el mercado de consumo (que puede abaratar bastante los precios) y el soporte para mensajes con baja latencia hacen de sta una de las mejores tecnologas para construir clusters de PCs bajo Linux utilizando redes de paso de mensajes, al menos durante los prximos aos. PLIP
eca (db`
Soporte bajo Linux: no Velocidad de Transferencia de Datos: 394 Mb/seg Disponibilidad: varios fabricantes Interfaz: PCI Estructura de Red: aleatorio sin ciclos (conguracin automtica)
Soporte bajo Linux: controladores del ncleo Velocidad de Transferencia de Datos: 1,2 Mb/seg Latencia: 1000
36
CAPTULO 1. INTRODUCCIN
Slo por el coste de un cable LapLink, PLIP (Parallel Line Interface Protocol, Protocolo de Interfaz de Lnea Paralela) permite comunicar dos mquinas Linux a travs del puerto paralelo estndar utilizando software basado en sockets. En trminos de velocidad de transferencia de datos, latencia y escalabilidad, no es una tecnologa de redes seria; sin embargo, su bajsimo coste y alta compatibilidad lo hacen til. El controlador forma parte de las distribuciones estndar del ncleo de Linux. SLIP
Interfaz: RS232C
Aunque SLIP (Serial Line Interface Protocol, Protocolo de Interfaz de Lnea Serie) est situado al nal del espectro de rendimiento, SLIP (o CSLIP o PPP) permite establecer comunicacin mediante sockets entre dos ordenadores a travs del puerto serie RS232 ordinario. Los puertos RS232 pueden ser conectados mediante un cable serie null-modem RS232 o incluso a travs de un mdem. En cualquier caso la latencia es alta y la velocidad de transferencia de datos baja, de manera que SLIP slo debe ser usado cuando no exista otra alternativa disponible. Sin embargo es mejor que nada; adems la mayora de los PCs tienen dos puertos RS232, de manera que podemos crear una red conectando un grupo de ordenadores de manera linear o en topologa de anillo. Tambin existe un software de comparticin llamado EQL. USB
Interfaz: USB
eca f8b`
Soporte bajo Linux: controladores del ncleo Velocidad de Transferencia de Datos: 0,1 Mb/seg Latencia: 1000
37
UNIDAD DE CONTROL
DISTRIBUIDOR DE LA RED
PE
PE
PE
PE
PE
PE
PE
PE
PE
PE
PE
PE
ELEMENTOS PROCESADORES
Figura 1.17: Esquema Procesador Matricial USB (Universal Serial Bus, Bus Serie Universal) (URL [20]) es un bus serie que proporciona la velocidad de una interfaz ethernet convencional. Soporta conexin en caliente (podemos enchufar cualquier dispositivo USB con el ordenador encendido) y puede manejar simultneamente hasta 127 perifricos que van desde teclados hasta cmaras de videoconferencia. En realidad no existe una especicacin clara sobre la metodologa a seguir para conectar varios PCs mediante este puerto; sin embargo la importancia del estndar y su comodidad hacen de esta interfaz una alternativa a tener en cuenta. Se puede decir que USB es la versin barata y de bajo rendimiento de FireWire que podemos utilizar en casi cualquier PC.
38
CAPTULO 1. INTRODUCCIN
instrucciones escalares y de control de ujo como saltos, etc. se ejecutan en la UC, mientras que las instrucciones aritmtico-lgicas, las de enrutado de datos y otras operaciones locales son transmitidas a los EPs y ejecutadas por stos sobre su memoria local. Respecto a los datos, los EPs tienen sus propios canales de E/S. De esta manera, la instruccin que ejecutan simultneamente los EPs es la misma, mientras que los datos sern los de la memoria de cada EP, y por tanto sern diferentes. Por todo ello un procesador slo requiere un nico programa para controlar todos los EPs. La idea de utilizacin de los procesadores matriciales es la de explotar el parlalelismo en los datos de un problema ms que la de paralelizar la secuencia de ejecucin de las instrucciones. El problema se paraleliza dividiendo los datos en particiones sobre las que se pueden realizar las mismas operaciones. Un tipo de datos altamente particionable es el formado por vectores y matrices, siendo ste ltimo el tipo de datos hacia el cual estn ms orientadas este tipo de arquitecturas. Por ello a estos procesadores se les llama matriciales. Aparte del propio paralelismo obtenido por el clculo en paralelo sobre los elementos de un vector o matriz, la propia red de interconexin entre los EPs reduce el tiempo de ejecucin en determinadas tareas. Dicha red se encarga de conectar a los EPs con sus propios vecinos. De esta manera la topologa de la red de interconexin determinar qu tipo de clculos sacan el mximo partido a determinado procesador matricial. Por ejemplo, en el tratamiento de imgenes, donde muchas operaciones son clculos entre pxels vecinos, una arquitectura matricial con una topologa adecuada paralelizara con facilidad dichos clculos. Un caso particular de los procesadores matriciales son los Procesadores Asociativos o Associative Processors cuya principal caracterstica es la utilizacin de memorias asociativas. La ejecucin de la misma operacin sobre distintas informaciones se usa en la simulacin de condiciones climatolgicas, control de trco areo, operaciones con matrices, etc. Ejemplos de computadores con esta organizacin son el ILLIAC IV, PEPE, BSP STARAN y ICLDAP.
39
cin de ALUs y de su segmentacin. Sin embargo es la segmentacin la que hace que varias instrucciones puedan ser ejecutadas al mismo tiempo sobre un determinado vector. Dependiendo del tipo de procesador vectorial cada ALU ser totalmente funcional o bien se encargar de realizar una funcin especca, como suma/resta, multiplicacin, divisin, etc. Adems debe existir una unidad de Carga/Almacenamiento encargada de leer los vectores desde la memoria y almacenarlos en ella. La diferencia entre este tipo de procesadores y los matriciales es que mientras los matriciales son comandados por las instrucciones, los vectoriales son comandados por ujos de datos continuos. As mientras en los procesadores matriciales slo existe un ujo de instrucciones entre la unidad de control y los elementos procesadores, en los computadores vectoriales tenemos dos ujos separados: el de instrucciones y el de datos. En este caso, el procesador escalar enva un ujo de datos continuo hacia el procesador vectorial, indicndole la operacin que debe realizar mediante el ujo de instrucciones. En la gura 1.18 mostramos el diseo tpico de un procesador vectorial con registros.
40
Procesador escalar Cauces funcionales escalares Instrucciones escalares Unidad de control escalar Instrucciones Memoria principal (Programa y datos) Cauce func. vectorial Datos vectoriales Registros vectoriales
CAPTULO 1. INTRODUCCIN
Datos escalares
Almacenamiento masivo
41
Figura 1.19: Cray SX-6 Los procesadores vectoriales, segn el mtodo de almacenamiento de los operandos, se clasican en:
Los supercomputadores vectoriales empezaron con modelos monoprocesadores como el Cray 1 en 1976. Los supercomputadores vectoriales recientes ofrecen ambos modelos, el monoprocesador y el multiprocesador. La mayora de supercomputadores de altas prestaciones modernos ofrecen multiprocesadores con hardware vectorial como una caracterstica ms de los equipos. En el cuadro 1.2 vemos algunos ejemplos de procesadores vectoriales con sus caractersticas principales.
Mquinas vectoriales con registros : En una mquina de este tipo todas las operaciones vectoriales excepto las de carga y almacenamiento operan con vectores almacenados en registros. La mayora de mquinas vectoriales modernas utilizan este tipo de arquitectura. Ejemplos: Cray Research (CRAY1, CRAY-2, X-MP, Y-MP y C90), supercomputadores japoneses (NEC SX Series, las Fujitsu VP200 y VP400 y la Hitachi S820). Mquinas vectoriales memoria-memoria : En este tipo de mquinas, todas las operaciones vectoriales son de memoria a memoria. Como la complejidad interna as como el coste son menores, es la primera arquitectura vectorial que se emple. Ejemplo: el CDC.
42
CAPTULO 1. INTRODUCCIN
Computadora Hitachi S820 Cray 2 Cray Y-MP NEC SX-3 Cray C90 Cray 3
mx CPUs 1 4 8 4 16 16
Captulo 2
A continuacin estudiaremos las caractersticas bsicas de los dos modelos de interaccin antes mencionados, para luego centrarnos en las utilidades de desarrollo ms populares que existen en la actualidad.
Por un lado podemos implementar dichos modelos a bajo nivel, utilizando cdigo mquina, ensamblador o compiladores de lenguajes no especializados. Dicha alternativa nos permite desarrollar un cdigo ms adaptado y optimizado para el hardware que vayamos a usar. Por otro lado podemos emplear utilidades de desarrollo de software paralelo, que son bsicamente facilidades para la programacin a alto nivel de aplicaciones distribuidas (compiladores, libreras, etc.) y herramientas para su ejecucin y monitorizacin. Dichas utilidades de programacin permiten al programador generar de manera automtica comunicacin mediante paso de mensajes y memoria compartida sin que deba preocuparse de los detalles. Las ventajas de emplear dichas utilidades son su facilidad de manejo y la portabilidad de los algoritmos desarrollados.
44
Figura 2.1: Modelo Bsico para Paso de Mensajes Todas las unidades de proceso pueden ser origen o destino de mensajes en cualquier momento y todas pueden intercambiar datos entre s. El enrutamiento de mensajes se le deja al sistema operativo y el nmero de saltos o puntos de intercomunicacin por los que el mensaje debe pasar dependern de la topologa de la mquina en uso. Este sistema puede utilizarse alcanzando un rendimiento ptimo en multicomputadores y en multiprocesadores con memoria distribuida. Aunque la sobrecarga en la comunicacin (latencia) en cada paso de mensaje puede ser alta normalmente hay pocas restricciones sobre la cantidad de informacin que pueden contener dichos mensajes. De este modo si contamos con un ancho de banda amplio el paso de mensajes puede ser un mtodo muy efectivo para transmitir grandes bloques de datos de entre los procesadores. Sin embargo para minimizar la necesidad de costosas operaciones de paso de mensajes los datos deben estar distribuidos entre los procesadores, de modo que el conjunto de datos referenciados por cada procesador est en su memoria local. A sto se le conoce como distribucin de datos (data layout). Una gran ventaja del paso de mensajes reside en su elevada portabilidad, puesto que por lo general consiste en el protocolo de comunicaciones estndar de la red ms las rutinas de sincronizacin y comunicacin de procesos, que se ejecutan sobre dicho protocolo. Adems dicho modelo puede usarse en una red de computadores heterognea. 2.1.1.1. Comunicacin mediante Sockets
En un sistema multitarea como Linux los sockets son la base para la comunicacin mediante paso de mensajes. Un socket es un punto de comunicacin que se comunica con otro socket para enviarle mensajes. Son bidireccionales, los hay de varios tipos y nos permiten comunicarnos con un proceso que est en otro ordenador o en el mismo. Cuando queremos recibir datos por un socket creamos uno y escuchamos por l hasta que nos lleguen datos. En caso de querer enviar datos lo que hacemos es crear un socket, cumplimentar los datos de la direccin de destino y enviar los datos al otro socket a travs del nuestro. Por consiguiente para que dos procesos se comuniquen mediante sockets cada uno debe crear el suyo. Para transmitir datos entre nodos bajo Linux usaremos normalmente la familia de sockets AF_INET. Este tipo de sockets se usan principalmente en redes IP, como por ejemplo la extensa Internet. En estas redes los ordenadores se identican mediante una direccin IP que es propia de cada nodo, o sea, no existen dos nodos con la misma direccin IP en una misma red. De esta manera los sockets pueden ser identicados unvocamente en toda la red. Ello es
45
importante ya que, conociendo todos los datos necesarios, podemos ponernos en contacto con cualquier punto de comunicacin de cualquier nodo de nuestra red. Los datos que identican unvocamente a estos puntos de transmisin son:
Para referirnos a un socket usaremos la direccin de socket. Las direcciones de socket son diferentes segn la familia. Llevan todos un primer parmetro que identica la familia de socket y luego, segn sta, los datos correspondientes. En el caso de la familia de sockets para redes IP estos datos son la direccin del ordenador y el nmero de puerto. Los tipos de sockets de esta familia son dos, que se corresponden con los dos tipos transmisin de datos en una red de paquetes, y son los que deniremos a continuacin. Datagramas (UDP) Es el modelo ms sencillo y tambin el menos robusto. Consiste en enviar paquetes de datos a un destino determinado. Cada paquete que enviamos ha de llevar la direccin de destino y es guiado por la red de manera independiente. Estos paquetes con la direccin de destino incluida se llaman datagramas. Los datagramas tienen una longitud limitada, por lo que los datos que enviamos no pueden exceder de esa longitud. Adems hay ciertos problemas derivados del hecho de que los paquetes transiten por una red, que se agravan cuanto ms extensa sea sta:
La direccin IP del nodo en donde reside el proceso que est usando ese punto de conexin. El nmero del puerto. El puerto es un nmero entero sin signo de 16 bits cuyo propsito es el de permitir que en un ordenador puedan existir 65536 puntos posibles de comunicacin para cada tipo de socket AF_INET. Esto es suciente para que no suponga un lmite (en la prctica) para el nmero de puntos de comunicacin diferentes que puede haber al mismo tiempo en un ordenador. Y el tipo de socket, dato que no reside en la informacin de direccionamiento, ya que es algo implcito al socket. Si usamos un socket de un tipo, ste slo se comunicar con sockets del mismo tipo.
Prdida de paquetes. En el nivel de red y en los nodos de enrutamiento se pueden perder paquetes debido a congestin, problemas en la transmisin, etc. Orden de los paquetes. En una red de rea extensa los paquetes atraviesan varios nodos para llegar a su destino. En estos nodos los algoritmos de enrutamiento no suelen ser estticos. De este modo para llegar al mismo destino un paquete puede seguir diferentes rutas, debido a que en un momento dado un nodo puede decidir encaminar el paquete por un sitio y luego por otro. Esto obedece sobre todo a causas derivadas del control de la congestin (el congestionamiento de las lneas inuye a la hora de determinar por cual de ellas se enva el paquete) y de la robustez del sistema (si un nodo se cae se encaminan los paquetes por otro sitio). La consecuencia es que dos paquetes que fueron enviados pueden llegar desordenados por haber seguido distintas rutas.
46
Estos problemas no suceden si las transmisiones se realizan dentro de una red de rea local, ya que no es necesario encaminar los paquetes. El protocolo de soporte sobre IP que sigue este esquema se llama UDP (User Datagram Protocol, Protocolo de Datagramas de Usuario) y por consiguiente hablaremos de UDP/IP. Comunicaciones Orientadas a Conexin (TCP) Consiste en realizar una conexin entre las dos partes. Tiene la desventaja de que se pierde tiempo en establecer la conexin, pero despus la comunicacin es able, ordenada y utiliza cabeceras ms pequeas. El protocolo de soporte sobre IP que sigue este esquema se denomina TCP (Transfer Data Protocol, Protocolo de Transferencia de Datos); hablaremos de ujos TCP/IP debido a que se establece un canal por donde los datos uyen de manera continua y ordenada. El protocolo TCP es bastante ms complejo que UDP e implementa segmentacin, lo cual nos permite pasar datos de gran longitud. Dichos datos sern segmentados en partes ms pequeas, enviados conservando el orden y ensamblados en el destino.
47
Hilo 1 Hilo 2 Hilo sencillo Hilo 3 Hilo 4 Regin secuencial Regin paralela Regin secuencial Hilo sencillo
Figura 2.2: Modelo Bsico para Memoria Compartida para paso de mensajes es considerablemente ms simple, pues consistir slo en un compilador base y las libreras para comunicaciones. La sincronizacin es un concepto altamente importante en este tipo de sistemas. La comparticin de recursos globales est llena de riesgos. Por ejemplo, si dos procesos hacen uso al mismo tiempo de la misma variable global y ambos llevan a cabo tanto lecturas como escrituras sobre la variable, el orden en el que se ejecuten las lecturas y escrituras es crtico. As surge el concepto de exclusin mutua. Dos o ms procesos no pueden acceder a determinados recursos al mismo tiempo. As, existen varias maneras de conseguir la exclusin mutua. Por un lado podemos hacerlo a nivel hardware, a travs de instrucciones mquina especiales o de inhabilitacin por interrupciones. Tambin a nivel de sistema operativo, con la utilizacin de semforos u otros mecanismos. A nivel de compilador contamos con la ayuda de los monitores. Como vemos existen varios mecanismos para conseguir la sincronizacin de los procesos en este tipo de sistemas. 2.1.2.1. Todo Compartido Vs. Algo Compartido
Hay dos modelos fundamentales usados comnmente en programacin con memoria compartida: Todo Compartido y Algo Compartido. Ambos modelos permiten la comunicacin entre procesadores mediante lecturas y escrituras de/en la memoria compartida; la diferencia consiste en que el modelo Todo Compartido ubica todos los datos en memoria compartida, mientras que el modelo Algo Compartido requiere que el usuario indique explcitamente qu datos pueden ser compartidos y cules son privados para un nico procesador. Qu modelo de datos debemos usar? Lgicamente debemos usar el modelo que mejor se adapte a nuestras necesidades, aunque muchas veces sto es slo cuestin de gustos. Mucha gente preere el modelo Todo Compartido porque no hay necesidad de identicar qu datos deben ser compartidos en el momento de su declaracin... simplemente bloqueamos los accesos potencialmente conictivos a objetos compartidos para asegurarnos de que slo un procesador tenga acceso en un momento dado. De nuevo, sto no es tan simple... por ello mucha gente preere la relativa seguridad del modelo Algo Compartido.
48
Modelo Todo Compartido Lo mejor de este modelo es que fcilmente podemos analizar un programa secuencial existente y convertirlo incrementalmente en un programa paralelo bajo el modelo Todo Compartido. No hay necesidad de determinar qu datos deben ser accesibles por cada uno de los procesadores. En principio el principal problema de este modelo es que cualquier accin ejecutada por un procesador podra afectar a otros procesadores. El problema sale a la luz de dos maneras:
Ninguno de estos dos tipos de problemas son usuales cuando se emplea el modelo Algo Compartido, debido a que slo los datos explcitamente marcados son compartidos. Adems resulta obvio que el modelo Todo Compartido slo funciona si todos los procesos tienen exctamente la misma imagen de la memoria; de este modo no es posible usar el modelo Todo Compartido con diferentes imgenes del cdigo (slo se puede usar SPMD, no MIMD en general). El soporte ms comn en programacin bajo el modelo Todo Compartido son las libreras de hilos. Los hilos son esencialmente procesos poco pesados que podran no ser planicados de la misma manera que los procesos UNIX y, lo que es ms importante, pueden tener acceso compartido a un mismo mapa de memoria. La primera librera que soport paralelismo en SMP Linux es la ahora algo obsoleta bb_threads, una librera muy pequea que utiliza la llamada clone() para crear nuevos procesos planicados independientemente que comparten un mismo espacio de direcciones. Los computadores SMP Linux pueden ejecutar mltiples hilos de este tipo en paralelo, ya que en este caso cada hilo es en realidad un proceso Linux completo; la desventaja es que no obtenemos la misma planicacin optimizada que realizan otras libreras de hilos. Ms recientemente ha sido desarrollada una versin de la librera de hilos POSIX. Esta librera, LinuxThreads, es claramente la librera preferida para ser usada bajo el modelo Todo Compartido bajo SMP Linux. Dicha librera de hilos POSIX est bien documentada. Ahora el principal problema es que la librera tiene muchos detalles por denir y acabar, de modo que LinuxThreads est todava en proceso de desarrollo. Adems tenemos el problema de
Muchas libreras contienen estructuras de datos que simplemente no se pueden compartir. Por ejemplo, una convencin UNIX es que la mayora de las funciones retornan su cdigo de error en una variable llamada errno; si dos procesos bajo el modelo Todo Compartido ejecutan varias llamadas, tendran conictos entre ellas porque en realidad comparten la misma variable errno. Aunque ahora existe una versin de la librera que corrige sto, todava existen otros muchos problemas similares en la mayora de las libreras. Por ejemplo, a menos que sean tomadas precauciones especiales la librera X no funcionar si las llamadas son hechas por mltiples procesos bajo el modelo Todo Compartido. Normalmente en cualquier otro modelo de programacin el peor caso para un programa con un puntero defectuoso o un error de segmentacin es que el proceso que contiene el cdigo errneo muera. Incluso en este caso el ncleo podra generar un chero que nos d una pista de lo sucedido. En procesamiento paralelo bajo el modelo Todo Compartido es comn que los accesos perdidos provoquen el fallecimiento de un proceso distinto al que contiene el error, haciendo casi imposible localizar y corregir el error.
49
que la librera POSIX se ha visto involucrada en el proceso de estandarizacin, de manera que tenemos que ser cuidadosos para no programar utilizando versiones obsoletas del estndar. Modelo Algo Compartido El modelo Algo Compartido en realidad signica compartir slo lo necesario. Este planteamiento puede funcionar en MIMD de manera general (no slo en SPMD) teniendo en cuenta que debemos ubicar los objetos compartidos en la misma posicin de memoria para cada uno de los mapas de memoria de cada procesador. Y lo que es ms importante, el modelo Algo Compartido hace ms fcil la prediccin y puesta a punto del rendimiento, el ltrado de errores, etc. Los nicos problemas son:
Hoy da existen dos mecanismos muy parecidos para permitir a grupos de procesos de Linux tener espacios de memoria independientes, compartiendo slo un pequeo segmento de memoria. Asumiendo que no hemos excluido el System V IPC en el momento de la conguracin de nuestro sistema Linux, tendremos un mecanismo muy portable que ha venido a denominarse System V Shared Memory. La otra alternativa es una utilidad de mapeo de memoria cuya implementacin vara ampliamente entre distintos sistemas UNIX: la llamada al sistema mmap().
Puede ser difcil saber de antemano qu necesita realmente ser compartido. La verdadera posicin de los objetos en memoria compartida puede ser difcil de establecer, especialmente para los objetos ubicados en una pila. Por ejemplo, puede ser necesario ubicar explcitamente objetos compartidos en un segmento de memoria separado, requiriendo de este modo rutinas de ubicacin en memoria separada e introduciendo punteros indirectos extra en cada referencia.
50
El modelo de funcionamiento de PVM es simple pero muy general, y se acomoda a una amplia variedad de estructuras de programas de aplicacin. La interfaz de programacin es muy sencilla, permitiendo que las estructuras de los programas sencillos sean implementadas de manera intuitiva. El usuario escribe su aplicacin como un conjunto de tareas que cooperan. Dichas tareas acceden a los recursos de PVM a travs de una librera de funciones con una interfaz estndar. Estas funciones permiten la inicializacin y nalizacin de las tareas a travs de la red, as como la comunicacin y la sincronizacin entre dichas tareas. Las operaciones de comunicacin utilizan estructuras predenidas, tanto las encargadas del envo y recepcin de datos como aquellas ms complejas (sincronizacin en barrera, suma global, broadcast, etc.). Debido a su portabilidad, su disponibilidad y su simple pero completa interfaz de programacin, el sistema PVM ha ganado una amplia aceptacin en la comunicad de clculo cientco de alto rendimiento.
2.2.2. MPI
MPI (Message Passing Interface, Interfaz de Paso de Mensajes) es un estndar que dene la sintaxis y la semntica de las funciones contenidas en una librera de paso de mensajes, diseada para ser usada en programas que exploten la existencia de mltiples procesadores. Aunque la interfaz no cambie, puede implementarse tanto en sistemas que utilicen paso de mensajes, como sistemas de memoria compartida. La primera versin de MPI fu desarrollada en 1993-1994 por un grupo de investigadores al servicio de la industria, el gobierno y el sector acadmico. Debido al apoyo recibido MPI es relativamente el nuevo estndar para la programacin de procesadores paralelos basado en el paso de mensajes, tomando el testigo de PVM. Sin embargo existen frecuentes dudas y discusiones por parte de los usuarios acerca de cul es el estndar a utilizar. As pues haremos un resumen de las diferencias ms caractersticas entre los sistemas ms utilizados, PVM y MPI: Entorno de Ejecucin: Simplemente PVM tiene uno denido, mientras que MPI no especica cmo debe ser implementado. As el inicio de la ejecucin de un programa PVM ser realizado de manera idntica en cualquier plataforma, mientras que para MPI depende de la implementacin que estemos utilizando. Soporte para Clusters Heterogneos: PVM fu desarrollado para aprovechar ciclos de CPU de estaciones de trabajo ociosas, por lo que maneja de manera directa mezclas heterogneas de mquinas y sistemas operativos. En contraste MPI asume que su principal objetivo son los MPPs y los clusters dedicados de estaciones de trabajo casi idnticas. Sin embargo, dependiendo de la implementacin que utilicemos, tendremos un soporte ms o menos adecuado. Amplitud del Campo de Estudio: PVM evidencia una unidad de propsito que MPI no tiene. Como veremos en el captulo 3 la especicacin MPI-1 centra su atencin en el modelo de paso de mensajes, al igual que PVM. Sin embargo la especicacin MPI-2 incluye muchas caractersticas que van
51
MPI SO
MPI SO
Figura 2.3: Esquema Bsico Utilizacin MPI ms all del modelo de paso de mensajes, como el acceso paralelo a cheros de E/S o el acceso a memoria remota, entre otros muchos ejemplos. Diseo de Interfaz de Usuario: MPI fu diseado despus de PVM, y claramente aprendi de l. MPI ofrece una interfaz ms clara y eciente, con manejo de buffers y abstracciones de alto nivel que permiten denir las estructuras de datos a ser transmitidas por los mensajes. Importancia del Estndar: El hecho de que MPI sea respaldado por un estndar formal ampliamente apoyado signica que el uso de MPI es, en muchas instituciones, cuestin de poltica. MPI no est concebido para ser una infraestructura software aislada y autosuciente para ser usada en procesamiento distribuido. MPI no necesita planicacin de procesos, herramientas de conguracin de la plataforma a usar, ni soporte para E/S. Como resultado MPI es implementado normalmente como interfaz de comunicaciones, utilizando las facilidades ofrecidas por el sistema que vayamos a usar, tal como se indica en la gura 2.3 (comunicacin va sockets, operaciones de memoria compartida, etc). ste escenario es ideal para que los programas PVM sean portados a MPI, de manera que se aproveche el alto rendimiento de comunicacin que ofrecen algunas compaas en sus arquitecturas. Dado que ste es el estndar en el que nos basaremos para el desarrollo del presente documento, en el captulo 3 haremos una descripcin ms elaborada de sus caractersticas.
2.2.3. P4
El sistema p4 es una librera de macros y funciones desarrollada por el Argonne National Laboratory 1 destinadas a la programacin de una gran variedad de mquinas paralelas. El sistema p4 soporta tanto el modelo de memoria compartida (basado en monitores) como el modelo de memoria distribuida (basado en paso de mensajes). Para el modelo de memoria compartida, p4 proporciona un conjunto de monitores as como funciones desarrolladas para crearlos y manipularlos; un monitor es un mecanismo de sincronizacin de procesos en sistemas con memoria compartida. Para el modelo de memoria distribuida, p4 proporciona operaciones de envo y recepcin, y un mtodo de administracin
1
52
de procesos basado en un chero de conguracin que describe la estructura de los grupos y procesos. Dicho chero especica el nombre del servidor, el chero que ser ejecutado en cada mquina, el nmero de procesos que sern iniciados en cada servidor (principalmente para sistemas multiprocesador) e informacin auxiliar. Un ejemplo de chero de conguracin es: # start one eslave on each of sun2 and sun3 local 0 sun2 1 /home/mylogin/pupgms/sr_test sun3 1 /home/mylogin/pupgms/sr_test Dos cosas son notables en lo que se reere al mecanismo de administracin de los procesos en p4. Primero, existe la nocin de procesos maestros y procesos esclavos, y pueden formarse jerarquas multinivel para implementar el denominado modelo de cluster de procesamiento. Segundo, el principal modo de creacin de procesos es esttico, a travs del chero de conguracin; la creacin dinmica de procesos es posible slo mediante procesos creados estticamente que deben invocar una funcin p4 que expande un nuevo proceso en la mquina local. A pesar de estas restricciones una gran variedad de paradigmas de aplicacin pueden ser implementados en el sistema p4 de una manera bastante sencilla. El paso de mensajes es conseguido en el sistema p4 a travs del uso de primitivas send y receive tradicionales, con casi los mismos parmetros que los dems sistemas de paso de mensajes. Algunas variantes han sido proporcionadas por cuestiones semnticas, como el intercambio heterogneo y las transferencias bloqueantes o no bloqueantes. Sin embargo una proporcin signicativa de la administracin del buffer y su carga se le deja al usuario. Aparte del paso de mensajes bsico, p4 ofrece tambin una variedad de operaciones globales incluyendo broadcast, mximo y mnimo globales, y sincronizacin por barrera.
2.2.4. Express
En contraste con lo que sucede con otros sistemas de procesamiento paralelo descritos en esta seccin, Express es una coleccin de herramientas que individualmente dirigen varios aspectos del procesamiento concurrente. Dicho paquete software es desarrollado y comercializado por Parasoft Corporation, una compaa creada por algunos miembros del proyecto de procesamiento concurrente de Caltech. La losofa de Express se basa en comenzar con la versin secuencial de un algoritmo y aplicarle un ciclo de desarrollo recomendado, para as llegar a la versin paralela de dicho algoritmo de manera ptima. Los ciclos de desarrollo tpicos comienzan con el uso de la herramienta VTOOL, una aplicacin grca que permite mostrar por pantalla el progreso de los algoritmos secuenciales dinmicamente. Puede mostrar actualizaciones y referencias a estructuras de datos individuales, con la intencin de demostrar la estructura de los algoritmos y proporcionar la informacin necesaria para su paralelizacin. En relacin con este programa tenemos la herramienta FTOOL, que proporciona un anlisis en profundidad de los programas. Dicho anlisis incluye informacin acerca del uso de variables, la estructura de ujo de control, etc. FTOOL opera tanto en las versiones secuenciales de los algoritmos como en las paralelas. Una tercera herramienta llamada ASPAR es
53
usada entonces; esta herramienta es un paralelizador automtico que convierte programas secuenciales escritos en C o Fortran en sus versiones paralelas o distribuidas, usando los modelos de programacin Express. El ncleo del sistema Express es un conjunto de libreras de comunicacin, E/S y grcos paralelos. Las primitivas de comunicacin son parecidas a las encontradas en otros sistemas de paso de mensajes e incluyen una variedad de primitivas para realizar operaciones globales y de distribucin de datos. Las funciones de E/S extendida permiten la E/S paralela. Un conjunto de funciones similar es proporcionado para mostrar grcos de mltiples procesos concurrentes. Express contiene adems la herramienta NDB, un depurador paralelo que utiliza comandos basados en la popular interfaz dbx.
2.2.5. Linda
Linda es un modelo concurrente de programacin fruto de la evolucin de un proyecto de investigacin de la Universidad de Yale. El concepto principal en Linda es el espacio de tuplas, una abstracin a travs de la cual se comunican los procesos. Este tema central de Linda ha sido propuesto como paradigma alternativo a los dos mtodos tradicionales de procesamiento paralelo: el basado en memoria compartida, y el basado en paso de mensajes. El espacio de tuplas es esencialmente una abstraccin de la memoria compartida/distribuida, con una diferencia importante: los espacios de tuplas son asociativos. Tambin existen otras distinciones menores. Las aplicaciones utilizan el modelo Linda introduciendo en los programas secuenciales estructuras que manipulan el espacio de tuplas. Desde el punto de vista de las aplicaciones, Linda es un conjunto de extensiones para lenguajes de programacin que facilitan la programacin paralela. Proporciona una abstraccin de la memoria compartida que no requiere la existencia de hardware especco que comparta memoria fsicamente. El trmino Linda se reere a menudo a implementaciones especcas software que soportan el modelo de programacin Linda. Este tipo de software establece y mantiene espacios de tuplas, siendo utilizado en conjuncin con libreras que interpretan y ejecutan primitivas Linda. Dependiendo del entorno (mutiprocesadores con memoria compartida, sistemas de paso de mensajes, etc.) el macanismo de espacio de tuplas ser implementado utilizando diferentes tcnicas con varios grados de eciencia. Recientemente ha sido propuesto un nuevo esquema relacionado con el proyecto Linda. Este esquema, denominado Pirhana, propone un planteamiento revolucionario en el procesamiento concurrente: los recursos computacionales (vistos como agentes activos) eligen a los procesos basndose en su disponibilidad y conveniencia. Este esquema puede ser implementado en mltiples plataformas y es conocido como Sistema Pirhana o Sistema Linda-Pirhana.
54
Parte II
Gua MPI
55
Captulo 3
El Estndar MPI
MPI (Message Passing Interface, Interfaz de Paso de Mensajes) es un estndar que dene la sintaxis y la semntica de las funciones contenidas en una librera de paso de mensajes diseada para ser usada en programas que exploten la existencia de mltiples procesadores. Dicha librera puede ser utilizada por una amplia variedad de usuarios para implementar programas que utilicen paso de mensajes. Desde la nalizacin de su primera versin en Junio de 1994, MPI ha sido ampliamente aceptado y usado. Existen implementaciones muy estables y ecientes, incluyendo algunas de dominio pblico. Adems dichas implementaciones estn disponibles para un amplia variedad de mquinas. Gracias a ello MPI ha alcanzado uno de sus principales objetivos: darle credibilidad al procesamiento paralelo. Ahora las companas y los investigadores tienen una manera sencilla y segura para desarrollar programas paralelos portables de paso de mensajes.
3.1. Origen
El paso de mensajes es un paradigma de programacin ampliamente utilizado en computadores paralelos, especialmente en aquellas con memoria distribuida. Aunque existen muchas variantes, el concepto bsico de procesos comunicndose mediante mensajes est muy consolidado. Durante los aos anteriores a la aparicin del estndar MPI se perciba un progreso sustancial en proyectar aplicaciones importantes en este paradigma. De hecho, cada compaa haba implementado ya su propia variante. Ms recientemente algunos sistemas de dominio pblico haban demostrado que el paso de mensajes poda implementarse ecientemente de manera portable.
58
Por todo ello comprendemos que ste era el momento apropiado para denir tanto la sintaxis como la semntica de una librera estndar de funciones que fuera til a una amplia variedad de usuarios y que pudiera implementarse ecientemente en una amplia gama de computadores. Y de esa idea naci el estndar MPI. Los diseadores de MPI pretendieron incorporar la mayora de las caractersticas ms atractivas de los sistemas existentes de paso de mensajes, antes que seleccionar uno de ellos y adoptarlo como el estndar. As, en su origen MPI estuvo muy inuenciado por el trabajo del Centro de Investigacin T.J.Watson de IBM, el sistema NX/2 de Intel, Express, Vertex de nCUBE y PARMACS. Otras contribuciones importantes fueron las realizadas por Zipcode, Chimp, PVM, Chameleon y PICL. Los diseadores de MPI identicaron algunos defectos crticos de los sistemas de paso de mensajes existentes en reas como la composicin de datos complejos, la modularidad y las comunicaciones seguras. sto permiti la introduccin de nuevas caractersticas en MPI.
3.2. Historia
El esfuerzo de estandarizacin de MPI involucr a unas 60 personas procedentes de 40 organizaciones, principalmente de EEUU y Europa. La mayora de las principales compaas de computadores paralelos del momento estuvieron involucradas en MPI, as como investigadores provenientes de universidades, laboratorios de gobierno y la industria. El proceso de estandarizacin comenz con el Seminario sobre Estndares de Paso de Mensajes en Entornos de Memoria Distribuida, patrocinado por el Centro de Investigaciones sobre Procesamiento Paralelo, mantenido durante los das 29-30 de Abril de 1992 en Williansburg, Virginia (EEUU). En este seminario se discutieron las caractersticas esenciales que deba tener una interfaz estndar de paso de mensajes y se estableci un grupo de trabajo para continuar con el proceso de estandarizacin. Un borrador preliminar, conocido como MPI1, fu propuesto por Dongarra, Hempel, Hey y Walker en Noviembre de 1992 y una versin revisada fu completada en Febrero de 1993. MPI1 abarcaba las caractersticas principales que fueron identicadas en el seminario de Williansburg como necesarias en un estndar de paso de mensajes. Dado que fu generado para promover la discusin, este primer borrador se centr principalmente en las comunicaciones punto-a-punto. Aunque tocaba muchos asuntos referentes a la estandarizacin, no inclua operaciones colectivas ni tena en cuenta la utilizacin de hilos. En Noviembre de 1992 una reunin del grupo de trabajo de MPI tuvo lugar en Minneapolis, en la cual se decidi hacer el proceso de estandarizacin de una manera ms formal, adoptando la organizacin y los procedimientos del High Performance Fortran Forum (Foro Fortran de Alto Rendimiento). Fueron formados subcomits para cada una de las principales reas que componen el estndar, y se estableci un foro de discusin va e-mail para cada una de ellas. De esta manera qued conformado el Foro MPI (URL [8]), a cuyo cargo quedara el proceso de estandarizacin de MPI. En dicha reunin se propuso el objetivo de presentar un borrador del estndar MPI en el otoo de 1993. Para conseguirlo el Foro MPI mantuvo reuniones cada 6 semanas durante los primeros 9 meses de 1993, presentando el borrador del estndar MPI en la conferencia Supercomputing 93 en Noviembre de 1993. Despus de un perodo de comentarios pblicos,
3.3. OBJETIVOS
59
que resultaron en algunos cambios en MPI, la versin 1.0 de MPI fu presentada en Junio de 1994. A principios de Marzo de 1995 el Foro MPI empez a reunirse de nuevo para considerar correcciones y extensiones al documento original del estndar MPI. El primer producto fruto de estas deliberaciones fu la versin 1.1 de MPI, presentada en Junio de 1995. En Julio de 1997 aparecen al mismo tiempo la versin 1.2 de MPI y la especicacin MPI2. La versin 1.2 de MPI contiene correcciones y claricaciones referentes a la versin 1.1. Sin embargo MPI-2 aade nuevos elementos al estndar MPI-1, deniendo la versin 2.0 de MPI. Todava hoy continan las discusiones acerca de las reas hacia las cuales podra ser til expandir el estndar MPI; sin embargo en muchas de ellas es necesario obtener ms experiencia y realizar ms discusiones. De todo ello se encarga un documento separado, el MPI Journal Of Development (Peridico de Desarrollo), que no forma parte de la especicacin MPI-2. Y por supuesto el Foro MPI sigue abierto a las aportaciones que puedan realizar los usuarios del estndar, con el objetivo de mantenerlo y desarrollarlo.
3.3. Objetivos
La nalidad de MPI, de manera concisa, es desarrollar un estndar para escribir programas de paso de mensajes que sea ampliamente utilizado. Para ello la interfaz debe establecer un estndar prctico, portable, eciente, escalable, formal y exible.
Objetivos Principales
Portabilidad El principal objetivo de MPI, como ocurre en la mayora de los estndares, es conseguir un alto grado de portabilidad entre diferentes mquinas. Esta portabilidad sera parecida a la que se consigue con lenguajes de programacin como Fortran. De esta manera el mismo cdigo fuente de paso de mensajes debera poder ser ejecutado en una variedad de mquinas tan grande como la soportada por las distintas implementaciones de MPI, aunque pueda ser necesaria una puesta a punto para obtener la mxima ventaja de las caractersticas de cada sistema. A pesar de que el paso de mensajes muchas veces es considerado algo propio de los sistemas paralelos de memoria distribuida, el mismo cdigo podra ser ejecutado en un sistema paralelo de memoria compartida. Puede ejecutarse en clusters o incluso en un conjunto de procesos ejecutndose en una misma mquina. El hecho de saber que existen implementaciones de MPI ecientes para una amplia variedad de sistemas nos da cierto grado de exibilidad en el desarrollo del cdigo, la bsqueda de errores y la eleccin de la plataforma que nalmente utilizaremos. Heterogeneidad Otro tipo de compatibilidad ofrecido por MPI es su capacidad para ejecutarse en sistemas heterogneos de manera transparente. As pues, una implementacin MPI debe ser capaz de extender una coleccin de procesos sobre un conjunto de sistemas con arquitecturas diferentes, de manera que proporcione un modelo de computador virtual que oculte las diferencias en
60
las arquitecturas. De este modo el usuario no se tiene que preocupar de si el cdigo est enviando mensajes entre procesadores de la misma o distinta arquitectura. La implementacin MPI har automticamente cualquier conversin que sea necesaria y utilizar el protocolo de comunicacin adecuado. Sin embargo MPI no prohibe implementaciones destinadas a un nico y homogneo sistema, as como tampoco ordena que distintas implementaciones MPI deban tener la capacidad de interoperar. En denitiva, los usuarios que quieran ejecutar sus programas en sistemas heterogneos debern utilizar implementaciones MPI diseadas para soportar heterogeneidad. Rendimiento La portabilidad es un factor importante, pero el estndar no conseguira una amplia utilizacin si se consiguiera dicha portabilidad a expensas del rendimiento. Por ejemplo, el lenguaje Fortran es comnmente usado por encima de los lenguajes ensambladores porque los compiladores casi siempre ofrecen un rendimiento aceptable comparado con la alternativa no portable que representa el lenguaje ensamblador. Un punto crucial es que MPI fu cuidadosamente diseado de manera que permite implementaciones ecientes. Las elecciones en el diseo parecen haber sido hechas correctamente, dado que las implementaciones MPI estn alcanzando un alto rendimiento en una amplia variedad de plataformas; de hecho el rendimiento alcanzado en dichas implementaciones es comparable al de los sistemas presentados por las compaas, los cuales estn diseados para arquitecturas especcas y tienen menor capacidad de portabilidad. Un objetivo importante de diseo en MPI fu el de permitir implementaciones ecientes para mquinas de diferentes caractersticas. Por ejemplo, MPI evita cuidadosamente especicar la manera en que las operaciones tienen lugar. Slo especica qu hace una operacin lgicamente. Como resultado MPI puede ser fcilmente implementado en sistemas que tienen buffer de mensajes en el proceso emisor, en el receptor, o que no tienen buffers para nada. Las implementaciones pueden beneciarse de las ventajas que ofrecen los subsistemas de comunicacin de varias mquinas a travs de sus caractersticas especcas. En mquinas con coprocesadores de comunicacin inteligentes podemos cargar sobre dichos coprocesadores la mayora del procesamiento relativo al protocolo de paso de mensajes. En otros sistemas la mayora del cdigo de comunicacin ser ejecutada por el procesador principal. Otro ejemplo es el uso de objetos opacos en MPI; por ejemplo los elementos grupo y comunicador son objetos opacos. Desde un punto de vista prctico sto signica que los detalles de su representacin interna dependen de la implementacin MPI particular, y como consecuencia el usuario no puede acceder directamente a ellos. En vez de ello el usuario accede a un manejador que referencia al objeto opaco, de manera que dichos objetos opacos son manipulados por funciones MPI especiales. De esta manera cada implementacin es libre de hacer lo mejor en determinadas circunstancias. Otra eleccin de diseo importante para la eciencia es la manera de evitar el trabajo innecesario. MPI ha sido cuidadosamente diseado de modo que no sea necesaria demasiada informacin extra con cada mensaje, ni complejas codicaciones o decodicaciones sobre las cabeceras de dichos mensajes. MPI tambin evita computaciones extra o tests en funciones crticas que degraden el rendimiento. Otra manera de minimizar el trabajo es reducir la repeticin de computaciones previas. MPI proporciona esta capacidad a travs de construcciones
3.3. OBJETIVOS
61
como peticiones de comunicacin persistente o los atributos de los comunicadores. El diseo de MPI evita la necesidad de operaciones extra de copia o almacenamiento sobre los datos: en la mayora de los casos los datos son llevados directamente de la memoria de usuario a la red, y son recibidos directamente de la red a la memoria receptora. MPI ha sido diseado para reducir la sobrecarga en la comunicacin producida por el procesamiento, utilizando agentes de comunicacin inteligentes y ocultando latencias en la comunicacin. sto se ha logrado usando llamadas no bloqueantes, que separan el inicio de la comunicacin de su nal. Escalabilidad La escalabilidad es otro objetivo importante del procesamiento paralelo. La escalabilidad de un sistema es su capacidad para responder a cargas de trabajo crecientes. De este modo los programas MPI deben mantener su nivel de rendimiento aunque incrementemos el nmero de procesos a ejecutar. MPI permite o soporta la escalabilidad a travs de algunas de sus caractersticas de diseo. Por ejemplo, una aplicacin puede crear subgrupos de procesos que, en turnos, puedan ejecutar operaciones de comunicacin colectiva para limitar el nmero de procesos involucrados. Formalidad MPI, como todos los buenos estndares, es valioso debido a que dene el comportamiento de las implementaciones de manera concisa. Esta caracterstica libera al programador de tener que preocuparse de aquellos problemas que puedan aparecer. Un ejemplo de ello es la garanta de seguridad en la transmisin de mensajes que ofrece MPI. Gracias a esta caracterstica el usuario no necesita comprobar si los mensajes son recibidos correctamente.
Resumen de Objetivos
Disear una interfaz para la programacin de aplicaciones. La interfaz debe ser diseada para que pueda ser implementada en la mayora de las plataformas, sin necesidad de cambios importantes en la comunicacin o el software del sistema. Permitir implementaciones que puedan ser utilizadas en entornos heterogneos. Permitir una comunicacin eciente. Asumir una interfaz de comunicacin able: el usuario no debe preocuparse por los fallos en la comunicacin. La semntica de la interfaz debe ser independiente del lenguaje. La interfaz debe permitir la utilizacin de hilos. Proporcionar extensiones que aadan ms exibilidad.
62
3.4. Usuarios
El estndar MPI est pensado para ser utilizado por todo aquel que pretenda desarrollar programas de paso de mensajes codicados en Fortran 77 y C. sto incluye programadores de aplicaciones individuales, desarrolladores de software para mquinas paralelas y creadores de entornos y herramientas. Para que esta amplia audiencia lo considere atractivo, el estndar debe proporcionar al usuario bsico una interfaz simple y fcil de manejar, que no impida el uso de las operaciones de alto rendimiento disponibles en mquinas avanzadas.
3.5. Plataformas
El atractivo del paradigma de paso de mensajes proviene al menos en parte de su portabilidad. Los programas expresados de esta manera podran ser ejecutados en multicomputadores, multiprocesadores o combinaciones de ambos. Adems es posible realizar implementaciones basadas en memoria compartida. El paradigma no queda obsoleto al combinar arquitecturas de memoria distribuida con arquitecturas de memoria compartida, o al incrementar la velocidad de la red. Debe ser a la vez posible y til implementar dicho estndar en una gran variedad de mquinas, incluyendo dichas mquinas que se componen de colecciones de otras mquinas, paralelas o no, conectadas por una red de comunicaciones. La interfaz es apropiada para su uso en programas MIMD y SPMD. Aunque no proporciona un soporte explcito para la ejecucin de hilos la interfaz ha sido diseada de manera que no perjudique su uso. MPI proporciona muchas caractersticas encaminadas a mejorar el rendimiento en computadores paralelos con hardware de comunicacin especializado entre procesadores. De este modo es posible realizar implementaciones nativas MPI de alto rendimiento para este tipo de mquinas. Al mismo tiempo existen implementaciones MPI que utilizan los protocolos estndares de comunicacin entre procesadores de Unix, las cuales proporcionan portabilidad a los clusters y redes heterogneas.
3.6. Versiones
El estndar MPI se divide bsicamente en dos especicaciones, MPI-1 y MPI-2. La siguiente clasicacin muestra el nivel de compatibilidad con MPI que posee una implementacin dada:
En todo caso la compatibilidad hacia atrs est preservada. De esta manera un programa MPI1.1 vlido ser un programa MPI-1.2 vlido y un programa MPI-2 vlido; un programa MPI1.2 vlido ser un programa MPI-2 vlido.
Mantener compatibilidad con la especicacin MPI-1 signica ser compatible con la versin 1.2 de MPI. Mantener compatibilidad con la especicacin MPI-2 signica proporcionar toda la funcionalidad denida por la especicacin MPI-2.
3.6. VERSIONES
63
3.6.1. MPI-1
Las versiones 1.0, 1.1 y 1.2 del estndar MPI se engloban en la especicacin MPI-1. Dicha especicacin centra su atencin en el modelo de paso de mensajes. A continuacin mostramos una lista con los elementos contenidos en dicha especicacin, y aquellos que quedan fuera de ella. Elementos Incluidos
Elementos No Incluidos
Como vemos MPI-1 est diseado para aprovechar todas las facilidades ofrecidas por el sistema que vayamos a usar, tanto aquellas pertenecientes al sistema de comunicacin (operaciones de memoria compartida, comunicacin va sockets, etc.) como las relativas al entorno de programacin (herramientas para la construccin de programas, facilidades para la depuracin de errores, etc). Como resultado MPI es implementado normalmente como interfaz de comunicaciones, utilizando dichas facilidades ofrecidas por el sistema. Existen muchas caractersticas que fueron consideradas y no se incluyeron en MPI-1. sto ocurri por algunas razones: las restricciones de tiempo que se propuso el Foro MPI en acabar la especicacin; el sentimiento de no tener suciente experiencia en algunos de los
Comunicaciones punto a punto Operaciones colectivas Grupos de procesos Contextos de comunicacin Topologas de procesos Administracin del entorno Enlaces con Fortran 77 y C Interfaz para la creacin de perles de ejecucin
Operaciones de memoria compartida Operaciones ya soportadas por el sistema operativo de manera estandarizada durante la adopcin de MPI; por ejemplo, manejadores de interrupcin o ejecucin remota Herramientas para la construccin de programas Facilidades para la depuracin de errores Soporte especco para hilos Soporte para planicacin y creacin de procesos Funciones de E/S paralela
64
campos; y la preocupacin de que el aadir ms caractersticas podra retrasar la aparicin de implementaciones. De todas maneras las caractersticas no incluidas siempre pueden ser aadidas como extensiones en implementaciones especcas, como es el caso de la extensin MPE dentro de la implementacin MPICH (seccin A.7).
3.6.2. MPI-2
La especicacin MPI-2 es bsicamente una extensin a MPI-1 que aade nuevos elementos al estndar. La versin 2.0 de MPI pertenece a la especicacin MPI-2. Entre las nuevas funcionalidades que se aaden destacan las siguientes:
La razn por la cual se cre la especicacin MPI-2 fu la demanda por parte de los usuarios y desarrolladores de nuevas caractersticas en el estndar. De todos modos MPI-2 slo aade nuevos elementos a MPI-1, pero no lo modica.
3.7. Implementaciones
Desde que se complet la primera versin del estndar en 1994 un gran nmero de implementaciones MPI han sido puestas a disposicin de los usuarios. Esto incluye tanto algunas implementaciones portables e independientes como aquellas que han sido desarrolladas y optimizadas por las principales compaas de computadores paralelos. La alta calidad de dichas implementaciones ha sido un punto clave en el xito de MPI. A continuacin destacamos las tres implementaciones de dominio pblico ms importantes que pueden ser utilizadas en clusters de sistemas Linux:
Administracin y Creacin de Procesos Comunicaciones Unilaterales E/S Paralela Operaciones Colectivas Extendidas Enlaces con Fortran 90 y C++
MPICH (URL [9]) es sin duda la implementacin ms importante de MPI. Muchas implementaciones comerciales desarrolladas por las grandes compaas de computadores paralelos se basan en ella. La primera versin de MPICH fu escrita durante el proceso de estandarizacin de MPI, siendo nalmente presentada al mismo tiempo que la versin 1.0 de MPI. De hecho las experiencias de los autores de MPICH se convirtieron en una gran ayuda para el Foro MPI en el proceso de desarrollo del estndar. Su portabilidad es enorme y su rendimiento elevado. Posee compatibilidad total con MPI-1 e implementa muchos elementos de MPI-2. En el apndice A se analizan de manera detenida sus caractersticas y se informa sobre su instalacin, conguracin y manejo. LAM (URL [6]) fu desarrollada originalmente en el Centro de Supercmputo de Ohio antes de que el estndar MPI fuera presentado. Cuando MPI apareci, LAM adopt
3.7. IMPLEMENTACIONES
65
el estndar. LAM no slo consiste en la librera MPI, si no que adems contiene herramientas de depuracin y monitorizacin. Ha sido optimizada para funcionar con clusters heterogneos de sistemas Unix; sin embargo es muy portable, siendo utilizada en una amplia variedad de plataformas Unix, desde estaciones de trabajo a supercomputadores. LAM posee compatibilidad total con MPI-1 e implementa muchos elementos de MPI-2.
CHIMP (URL [1]) fu desarrollada en el Centro de Cmputo Paralelo de Edimburgo. Como LAM, CHIMP comenz como una infraestructura independiente de paso de mensajes que luego evolucion hacia una implementacin MPI. CHIMP es conocida principalmente por haber sido utilizada como versin optimizada de MPI para los CRAY T3D y T3E. CHIMP es portable, pudiendo ser utilizada en estaciones de trabajo de Sun, SGI, DEC, IBM y HP, en plataformas Meiko y en el Fujitsu AP 1000.
66
Captulo 4
Conceptos Bsicos
Todos los programas MPI comparten una serie de caractersticas. La inicializacin y nalizacin del entorno de ejecucin se llevan a cabo mediante funciones que explicaremos en este captulo. Tambin analizaremos los mtodos para identicar los procesos en ejecucin. Por otro lado estudiaremos funciones para informarnos de dnde est ubicado cada proceso y el momento temporal en que nos encontramos, y explicaremos el problema de la E/S en procesadores paralelos. Para ejemplicar todo sto implementaremos un sencillo programa que enva un mensaje de saludo e indica el nmero de procesos en ejecucin.
I G gi q q q i I i srdfffAXph
Aunque los detalles de qu ocurre cuando el programa es ejecutado varan de una mquina a otra, lo esencial es lo mismo en todos los sistemas, a condicin de que ejecutemos un proceso en cada procesador. 1. 2. 3. El usuario manda una directiva al sistema operativo que crea una copia del programa ejecutable en cada procesador. Cada procesador comienza la ejecucin de su copia del ejecutable. Diferentes procesos pueden ejecutar diferentes instrucciones bifurcando el programa a travs de condicionantes. Dichos condicionantes suelen basarse, como veremos, en el identicador del proceso.
69
int MPI_Comm_rank(MPI_Comm comunicador, int* identificador) El primer argumento es el comunicador. Esencialmente un comunicador es una coleccin de procesos que pueden enviarse mensajes entre s. Normalmente para disear programas bsicos el nico comunicador que necesitaremos ser MPI_COMM_WORLD. Est predenido en MPI y consiste en todos los procesos que se ejecutan cuando el programa comienza. Muchas de las construcciones que empleamos en nuestros programas dependen tambin del nmero de procesos que se ejecutan. MPI ofrece la funcin MPI_Comm_size() para determinar dicho nmero de procesos. Su primer argumento es el comunicador. En el segundo argumento retorna el nmero de procesos pertenecientes a dicho comunicador. Su sintaxis es: int MPI_Comm_size(MPI_Comm comunicador, int* numprocs)
u t
70
mostrarn los datos de los distintos procesos todos mezclados (una lnea del proceso 0, dos caracteres del proceso 1, 3 caracteres del 0, 2 lneas del 2, etc.)? Las operaciones estndar de E/S en C no proporcionan soluciones simples a dicho problema; as, la E/S sigue siendo objeto de investigacin por parte de la comunidad de procesamiento paralelo. Por todo ello asumiremos que el proceso 0 puede al menos escribir en la salida estndar. Tambin asumiremos que puede leer de la entrada estndar. En todos los casos asumiremos que slo el proceso 0 puede interactuar con la E/S. sto podra parecer una debilidad, ya que como mencionamos antes la mayora de las mquinas paralelas permiten que mltiples procesos interactuen con la E/S. Sin embargo es un mtodo muy slido que nos permitir realizar un manejo limpio de la E/S en nuestros programas.
int MPI_Get_processor_name(char* nombre, int* longnombre) El parmetro nombre es una cadena (vector de caracteres) cuyo tamao debe ser al menos igual a la constante MPI_MAX_PROCESSOR_NAME. En dicho vector quedar almacenado el nombre del procesador. El parmetro longnombre es otro parmetro de salida que nos informa de la longitud de la cadena obtenida.
71
MPI_Wtime() debido a que dicha funcin forma parte del entorno MPI, el cual debe ser nalizado antes de que el programa termine. Por lo tanto el tiempo que arrojara es incorrecto, siempre menor al que debera; en su lugar usaremos las herramientas de monitorizacin para determinar el tiempo de ejecucin. Por otro lado llamamos tiempo de procesamiento al tiempo que emplea el computador en calcular el resultado, eliminando el tiempo de inicializacin y nalizacin de los procesos, y la comunicacin con el usuario. De esta manera si el usuario tarda diez segundos en introducir los datos para un problema, ese tiempo no ser aadido al tiempo de procesamiento pero s al tiempo de ejecucin. La funcin MPI_Wtime() nos ayudar a calcular el tiempo de procesamiento de un programa para despus mostrarlo al usuario por la salida estndar. En el caso del algoritmo Hola Mundo! el tiempo de procesamiento no es indicativo. Sin embargo es muy til en programas donde un proceso (normalmente el proceso 0) desencadena la ejecucin de los dems (normalmente al distribuir entre todos los procesos los datos que el usuario introduce por la entrada estndar). ste ser el caso ms comn entre los algoritmos expuestos en el presente documento.
/********************************************************/ /*Hola Mundo: CODIGO PROGRAMA QUE SALUDA */ /********************************************************/ # define TAMCADENA 100 # include " mpi . h " # include < s t d i o . h> /**************/ /*FUNCION MAIN*/ /**************/ i n t main ( i n t argc , char argv ) { int id ; /*IDENTIFICADOR DEL PROCESO*/ i n t numprocs ; /*NUMERO DE PROCESOS*/ char nombreproc [MPI_MAX_PROCESSOR_NAME] ; /*NOMBRE PROCESADOR*/ i n t lnombreproc ; /*LONGITUD NOMBRE PROCESADOR*/ double t m p i n i c = 0 . 0 ; /*TIEMPO INICIO DE LA EJECUCION*/ double t m p f i n ; /*TIEMPO FINAL DE LA EJECUCION*/
v wv
72
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
/*INICIALIZAMOS EL ENTRORNO DE EJECUCION MPI*/ M P I _ I n i t (& argc ,& argv ) ; /*ALMACENAMOS EL IDENTIFICADOR DEL PROCESO*/ MPI_Comm_rank (MPI_COMM_WORLD,& i d ) ; /*ALMACENAMOS EL NUMERO DE PROCESOS*/ MPI_Comm_size (MPI_COMM_WORLD, & numprocs ) ; /*E/S:NOMBRE DEL PROCESADOR,PROCESO 0*/ MPI_Get_processor_name ( nombreproc,& lnombreproc ) ; i f ( i d ==0){ f p r i n t f ( s t d o u t , " \ n P r o c e s o %d en %s E n c a r g a d o de l a E / S \ n \ n " , i d , nombreproc ) ; } /*TIEMPO INICIAL DE LA EJECUCION */ t m p i n i c=MPI_Wtime ( ) ; /*E/S:PROCESAMIENTO*/ i f ( i d ==0){ f p r i n t f ( s t d o u t , " H o l a Mundo ! \ n \ n " ) ; } /*TIEMPO FINAL DE LA EJECUCION*/ t m p f i n =MPI_Wtime ( ) ; /*E/S:INFORMACION SOBRE LA EJECUCION*/ i f ( i d ==0){ f p r i n t f ( s t d o u t , " Numero P r o c e s o s : %d \ n " , numprocs ) ; f p r i n t f ( s t d o u t , " Tiempo P r o c e s a m i e n t o : % f \ n \ n " , t m p f i n t m p i n i c ) ; } /*FINALIZAMOS EL ENTRORNO DE EJECUCION MPI*/ MPI_Finalize ( ) ; return 0 ; }
Captulo 5
Paso de Mensajes
El paso de mensajes es quizs la funcin ms importante y caracterstica del estndar MPI. Se utiliza bsicamente para el intercambio de datos entre los procesos en ejecucin. En este captulo estudiaremos las caractersticas ms importantes de los mensajes bloqueantes y no bloqueantes, aplicando dicha teora a la implementacin de un algoritmo diseado para el clculo de reas circulares.
Utilizando dicha aproximacin de y sabiendo el radio del crculo aproximaremos fcilmente su rea mediante . Lgicamente cuantas ms muestras tomemos, o lo que es lo mismo, cuantos ms puntos generemos, mejor ser la aproximacin de . Tambin interviene mucho la aleatoriedad de las muestras; cuanto ms aleatorias sean, mejor. La cuestin ahora es determinar los puntos que caen dentro del crculo y los que caen podremos saber si ha fuera. Para explicarlo observemos la gura 5.2. Dado un punto cado dentro del crculo mediante la regla de Pitgoras: 73
Q i E9FD
QwydD T @ ) y
T ) B
Qy@ wdD
y
y d@
y
74
Si la hipotenusa es mayor que el radio del crculo querr decir que el punto est fuera de dicho crculo. Si la hipotenusa es menor que el radio, consideraremos que est dentro. Como podemos observar en la gura, tambin podemos generar puntos en slo una cuarta parte del cuadrado y el crculo, de manera que la proporcin no queda alterada. As lo hacemos en la implementacin del algoritmo Clculo de reas mediante Montecarlo (seccin 5.6).
Estos datos pueden ser usados por el proceso receptor para distinguir entre los mensajes entrantes. El origen puede ser usado para distinguir mensajes recibidos por distintos procesos.
75
(x,y)
h y
La etiqueta es un int especicado por el usuario que puede ser usado para distinguir mensajes recibidos por un nico proceso. Por ejemplo, supongamos que el proceso est enviando dos mensajes al proceso ; ambos mensajes contienen un nmero otante. Uno de los otantes se emplea en un clculo, mientras que otro debe ser impreso. Para determinar cul es cul, puede usar etiquetas diferentes para cada mensaje. Si usa las mismas etiquetas que en las recepciones correspondientes, sabr qu hacer con ellas. MPI garantiza que los enteros dentro del intervalo 0-32767 pueden ser usados como etiquetas. La mayora de las implementaciones permiten valores mucho mayores. Como dijimos antes un comunicador es bsicamente una coleccin de procesos que pueden mandarse mensajes entre s. La importancia de los comunicadores se acenta cuando los mdulos de un programa han sido escritos independientemente de los dems. Por ejemplo, supongamos que queremos resolver un sistema de ecuaciones diferenciales y, en el transcurso de resolverlo, tenemos que resolver un sistema de ecuaciones lineales. Mejor que escribir la resolucin del sistema de ecuaciones lineales desde el principio, podramos usar una librera de funciones escrita por otra persona y optimizada para el sistema que estamos usando. Cmo evitamos que se confundan los mensajes que nosotros enviamos entre los procesos y con los mensajes enviados en la librera de funciones? Sin la ventaja de los comunicadores probablemente haramos una particin del rango de las posibles etiquetas, haciendo que parte de ellas slo puedan ser usadas por la librera de funciones. sto es tedioso y puede causarnos problemas si ejecutamos el programa en otro sistema: puede que la librera del otro sistema no haga uso del mismo rango de etiquetas. Con la ventaja de los comunicadores, simplemente creamos un comunicador para uso exclusivo en la resolucin del sistema de ecuaciones lineales, y se lo pasamos a la librera encargada de hacerlo como argumento en la llamada. Comentaremos los detalles ms adelante. Por ahora continuaremos utilizando el comunicador MPI_COMM_WORLD, el cual consiste en todos los procesos que se ejecutan cuando el programa comienza.
76 Tipo de Datos MPI MPI_CHAR MPI_SHORT MPI_INT MPI_LONG MPI_UNSIGNED_CHAR MPI_UNSIGNED_SHORT MPI_UNSIGNED MPI_UNSIGNED_LONG MPI_FLOAT MPI_DOUBLE MPI_LONG_DOUBLE MPI_BYTE MPI_PACKED
Al igual que la mayora de las funciones de la biblioteca estndar de C, la mayora de las funciones MPI retornan un entero como cdigo de error. Sin embargo, como la mayora de los programadores de C, ignoraremos esos valores de retorno en casi todos los casos. Los contenidos del mensaje son almacenados en un bloque de memoria referenciado por el argumento mensaje. Los siguientes dos argumentos, contador y tipo_datos, permiten al sistema identicar el nal del mensaje: ste contiene una secuencia de contador valores, cada uno del tipo MPI datatype. Este tipo no es un tipo de C, aunque la mayora de los tipos predenidos corresponden a tipos de C. En el cuadro 5.1 se listan los tipos predenidos de MPI con sus correspondientes tipos de C, si stos existen. Los ltimos dos tipos, MPI_BYTE y MPI_PACKED, no corresponden con tipos estndar de C. El tipo MPI_BYTE puede ser usado si queremos forzar que el sistema no realice conversin alguna entre las distintas representaciones de los datos (por ejemplo, en una red heterognea de estaciones de trabajo que utilicen una representacin de datos distinta).
77
Notar que la cantidad de espacio reservado para el buffer de entrada no tiene porqu coincidir con la cantidad exacta de espacio que ocupa el mensaje que estemos recibiendo. Por ejemplo, podra darse el caso de que el tamao del mensaje que el proceso 1 enva al proceso 0 sea de 28 caracteres (strlen(mensaje)+1), aunque el proceso 0 reciba el mensaje en un buffer que tiene capacidad para 100 caracteres. sto tiene sentido. En general el proceso receptor no conoce el tamao exacto del mensaje que se le est enviando. MPI permite recibir mensajes tan largos como capacidad reservada tengamos. Si no tenemos suciente capacidad, tendremos un error de desbordamiento. Los argumentos destino y origen son los identicadores del proceso receptor y del proceso emisor, respectivamente. MPI permite que el argumento origen sea un comodn. Existe una constante predenida llamada MPI_ANY_SOURCE que puede ser usada si un proceso est preparado para recibir un mensaje procedente de cualquier proceso. No existe comodn para destino. Como dijimos anteriormente MPI contiene dos mecanismos diseados especcamente para particionar el espacio de los mensajes: las etiquetas y los comunicadores. Los argumentos etiqueta y comunicador son, respectivamente, la etiqueta y el comunicador. El argumento etiqueta es un int y, por ahora, nuestro nico comunicador es MPI_COMM_WORLD, el cual, como comentamos antes, est predenido en todos los sistemas MPI y consiste en todos los procesos que se ejecutan cuando el programa comienza. Existe un comodn, MPI_ANY_TAG, que puede ser usado en MPI_Recv() para la etiqueta. No existe un comodn para el comunicador. En otras palabras, para que el proceso mande un mensaje al proceso el argumento comunicador que usa en MPI_Send() debe ser idntico al argumento que usa en MPI_Recv(). El ltimo argumento de MPI_Recv(), status, retorna informacin acerca de los datos que hemos recibido. Referencia a un registro con dos campos, uno para el origen y otro para la etiqueta. Por ejemplo, si el origen era MPI_ANY_SOURCE en la llamada a MPI_Recv(), el argumento status contendr el identicador del proceso que envi el mensaje.
78
A simple vista la diferencia entre estas funciones y sus versiones bloqueantes es la existencia del argumento peticion en sus llamadas. Este argumento es utilizado por las funciones de nalizacin de transmisiones bloqueantes para su ejecucin. Las funciones de nalizacin de transmisiones bloqueantes son: int MPI_Wait(MPI_Request* peticion, MPI_Status* status) int MPI_Waitany(int contador, MPI_Request* vector_peticiones, int* indice, MPI_Status* status) int MPI_Waitall(int contador, MPI_Request* vector_peticiones, MPI_Status* status) La funcin MPI_Wait() espera a que se complete un envo o una recepcin de un mensaje. Para ello le pasamos como argumento de entrada el argumento de salida que nos proporciona la funcin de paso de mensajes no bloqueantes en el momento de la llamada. El argumento de salida status nos proporciona informacin acerca de los datos que hemos recibido. Por su parte MPI_Waitany() espera a que se complete cualquiera de las peticiones que le pasamos en vector_peticiones, devolviendo en el argumento indice la posicin de la peticin satisfecha. MPI_Waitall() espera a que se completen todas las peticiones que le pasamos en vector_peticiones.
79
debido a que las variables que contienen el radio y el nmero de muestras no tienen porqu estar alojadas en direcciones de memoria contiguas. Tampoco debemos almacenar estos datos en un vector debido a que ello restara claridad y elegancia al cdigo. Para lograr nuestro objetivo utilizaremos una facilidad de MPI para la agrupacin de los datos.
e intentar utilizar el tipo de datos de la estructura como argumento tipo_datos en las funciones de paso de mensajes. El problema aqu es que el tipo de datos de la estructura no es un tipo de datos MPI; necesitamos construir un tipo de datos MPI a partir del tipo de datos de C. MPI propone una solucin a sto permitiendo al usuario construir tipos de datos MPI en tiempo de ejecucin. Para construir un tipo de datos MPI bsicamente se especica la distribucin de los datos en el tipo (los tipos de los miembros y sus direcciones relativas de memoria). Un tipo de datos MPI construido de este modo se denomina tipo de datos derivado. Para ver cmo funciona sto expondremos la funcin que construye dicho tipo de datos.
void construir_tipo_derivado(Tipo_Datos_Entrada* pdatos, MPI_Datatype* pMPI_Tipo_Datos){ MPI_Datatype tipos[2]; int longitudes[2]; MPI_Aint direcc[3]; MPI_Aint desplaz[2];
/*PRIMERO ESPECIFICAMOS LOS TIPOS*/ tipos[0]=MPI_LONG_DOUBLE; tipos[1]=MPI_LONG; /*ESPECIFICAMOS EL NUMERO DE ELEMENTOS DE CADA TIPO*/ longitudes[0]=1; longitudes[1]=1; /*CALCULAMOS LOS DESPLAZAMIENTOS DE LOS MIEMBROS DE LA ESTRUCTURA RELATIVOS AL COMIENZO DE DICHA ESTRUCTURA*/ MPI_Address(pdatos,&direcc[0]); MPI_Address(&(pdatos->radio),&direcc[1]); MPI_Address(&(pdatos->nmuestras_local),&direcc[2]); desplaz[0]=direcc[1]-direcc[0];
80
desplaz[1]=direcc[2]-direcc[0];
/*CREACION TIPO DATOS DERIVADO*/ MPI_Type_struct(2,longitudes,desplaz,tipos,pMPI_Tipo_Datos); /*CERTIFICARLO DE MANERA QUE PUEDA SER USADO*/ MPI_Type_commit(pMPI_Tipo_Datos); }/*construir_tipo_derivado*/
Las primeras dos sentencias especican los tipos de los miembros del tipo de datos derivado, y las dos siguientes especican el nmero de elementos de cada tipo. La funcin MPI_Address() nos ayuda a calcular los desplazamientos de cada uno de los miembros con respecto a la direccin inicial del primero. Con esta informacin ya sabemos los tipos, los tamaos y las direcciones relativas de memoria de cada uno de los miembros del tipo de datos de C, y por lo tanto ya podemos denir el tipo de datos MPI derivado del tipo de datos de C. sto se hace llamando a las funciones MPI_Type_struct() y MPI_Type_Commit(). El tipo de datos MPI creado puede ser usado en cualquiera de las funciones de comunicacin de MPI. Para usarlo simplemente usaremos como primer argumento de las funciones la direccin inicial de la estructura a enviar, y el tipo de datos MPI creado en el argumento tipo_datos.
5.5.2. Vectores
La funcin MPI_Type_vector() crea un tipo derivado consistente en contador elementos. int MPI_Type_vector(int contador, int longitud_bloque, int salto, MPI_Datatype tipo_datos_elem, MPI_Datatype* nuevo_tipo) Cada elemento contiene longitud_bloque elementos de tipo tipo_datos_elem. El argumento salto es el nmero de elementos de tipo tipo_datos_elem que hay entre los sucesivos elementos de nuevo_tipo.
81
/***************************************************/ /*Calculo de Areas: CODIGO APROXIMACION DE AREAS */ /*CIRCULARES MEDIANTE MONTECARLO (BLOQUEANTE) */ /***************************************************/ # # # # include < s t d i o . h> include < s t d l i b . h> include < math . h> include " mpi . h "
/*DECLARACION ESTRUCTURA DATOS ENTRADA*/ typedef s t r u c t { long double r a d i o ; long n m u e s t r a s _ l o c a l ; } Tipo_Datos_Entrada ; /*DECLARACION DE LA FUNCIONES QUE VAMOS A UTILIZAR*/ long double MonteCarlo ( i n t i d , long double r a d i o , long l o c a l _ n ) ; void o b t e n e r _dat os ( long double p r a d i o , long pnmuestras_global ) ; void d i s t r i b u i r _ d a t o s ( i n t i d , i n t numprocs , long double p r a d i o , long p n m u e s t r a s _ l oc a l ) ; void r e c o l e c t a r _ d a t o s ( i n t i d , i n t numprocs , long double p a p r o x _ l o c a l , long double p a p r o x _ g l o b a l ) ; void c o n s t r u i r _ t i p o _ d e r i v a d o ( Tipo_Datos_Entrada pdatos , MPI_Datatype pMPI_Tipo_Datos ) ; /**************/ /*FUNCION MAIN*/ /**************/ i n t main ( i n t argc , char
argv ) {
long double PI25DIGITOS=3.141592653589793238462643; /*VALOR PI PARA CALCULAR EL ERROR*/ int id ; /*IDENTIFICADOR DEL PROCESO*/ i n t numprocs ; /*NUMERO DE PROCESOS*/ char nombreproc [MPI_MAX_PROCESSOR_NAME] ; /*NOMBRE PROCESADOR*/ i n t lnombreproc ; /*LONGITUD NOMBRE PROCESADOR*/ long double r a d i o ; /*RADIO CIRCUNFERENCIA*/ long n m u e s t r a s _global ; /*NUMERO DE MUESTRAS*/ long n m u e s t r a s _ l o c a l ; /*NUMERO DE MUESTRAS DE CADA PROCESO*/ long double a p r o x _ l o c a l ; /*APROX LOCAL DE CADA PROCESO*/ long double a p r o x _ g l o b a l ; /*APROX GENERAL (MEDIA DE TODAS LAS LOCALES)*/ int raiz =0; /*PROCESO QUE RECIBE LAS LOCALES Y LAS SUMA*/ double t m p i n i c = 0 . 0 ; /*TIEMPO INICIO DE LA EJECUCION*/ double t m p f i n ; /*TIEMPO FINAL DE LA EJECUCION */ int etiqueta =50; MPI_Status s t a t u s ; int origen ; /*ETIQUETA MENSAJES DE PRUEBA*/ /*STATUS RECEPCION MENSAJES DE PRUEBA*/ /*PROCESO ORIGEN MENSAJES DE PRUEBA*/
v v
v wv
82
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
83
f p r i n t f ( s t d o u t , " Con n= %d m u e s t r a s , l a e s t i m a c i o n d e l a r e a de l a \ n " , n m u e s t r a s _global ) ; f p r i n t f ( s t d o u t , " de l a c i r c u n f e r e n c i a con r a d i o %Lf e s \ n " , r a d i o ) ; f p r i n t f ( s t d o u t , " %.60 Lf \ n " , a p r o x _ g l o b a l ) ; f p r i n t f ( s t d o u t , " E r r o r < %f \ n \ n " , f a b s ( PI25DIGITOS r a d i o r a d i o a p r o x _ g l o b a l ) ) ; f p r i n t f ( s t d o u t , " Numero P r o c e s o s : %d \ n " , numprocs ) ; f p r i n t f ( s t d o u t , " Tiempo P r o c e s a m i e n t o : % f \ n \ n " , t m p f i n t m p i n i c ) ; } /*FINALIZAMOS EL ENTRORNO DE EJECUCION MPI*/ MPI_Finalize ( ) ; } /*main*/
/***************************************************************/ /*FUNCION obtener_datos:PROCESO 0 CONSULTA AL USUARIO EL RADIO */ /*DE LA CIRCUNFERENCIA Y EL NUMERO DE MUESTRAS GLOBAL */ /***************************************************************/ void o b t e n e r _dat os ( long double p r a d i o , long pnmuestras_global ) { /*E/S:PETICION DE DATOS*/ f p r i n t f ( s t d o u t , " I n t r o d u z c a r a d i o de l a c i r c u n f e r e n c i a \ n " ) ; scanf ( " % " , pradio ) ; Lf f p r i n t f ( s t d o u t , " I n t r o d u z c a numero de m u e s t r a s \ n " ) ; s c a n f ( " % d " , pnmuestras_global ) ; l
/**********************************************************************/ /*FUNCION distribuir_datos:PROCESO 0 DISTIBUYE RADIO DE LA */ /*CIRCUNFERENCIA Y EL NUMERO DE MUESTRAS (n) ENTRE LOS DEMAS PROCESOS */ /**********************************************************************/ void d i s t r i b u i r _ d a t o s ( i n t i d , i n t numprocs , long double p r a d i o , long p n m u e s t r a s _ l oc a l ) { MPI_Datatype MPI_Tipo_Datos_Entrada ; Tipo_Datos_Entrada d a t o s _ e n tr ada ; int origen =0; /*PROCESO ORIGEN MENSAJES*/ int destino ; /*PROCESO DESTINO DATOS*/ int etiqueta ; /*ETIQUETA MENSAJES*/ MPI_Status s t a t u s ; /*STATUS RECEPCION MENSAJES*/
84
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
} else { /*RECEPCION DE LOS DATOS*/ e t i q u e t a =30; MPI_Recv(& d a t o s _ e n tra da , 1 , MPI_Tipo_Datos_Entrada , o r i g e n , e t i q u e t a ,MPI_COMM_WORLD,& s t a t u s ) ; p r a d i o= d a t o s _ e ntr ada . r a d i o ; p n m u e s t r a s _ l o c al= d a t o s _ e nt rada . n m u e s t r a s _ l o c a l ; } } /*distribuir_datos*/
/************************************************************************/ /*FUNCION MonteCarlo: RETORNA EL AREA DE LA CIRCUNFERENCIA CON RADIO */ /*radio UTILIZANDO EL NUM.MUESTRAS nummuestras MEDIANTE MONTECARLO */ /************************************************************************/ long double MonteCarlo ( i n t i d , long double r a d i o , long nummuestras ) { long long long long long long long long double p i ; double area ; double x ; double y ; double h i p ; aciertos =0; fallos =1; i ; /*VBLE QUE ALMACENA NUMERO PI*/ /*AREA CIRCUNFERENCIA*/ /*EJE ORDENADAS MUESTRA ACTUAL*/ /*EJE COORDENADAS MUESTRA ACTUAL*/ /*HIPOTENUSA MUESTRA ACTUAL*/ /*NUM.MUESTRAS QUE CAEN DENTRO DE LA CIRCUNFERENCIA*/ /*NUM.MUESTRAS QUE CAEN FUERA DE LA CIRCUNFERENCIA*/ /*CONTADOR*/
/*UTILIZAMOS COMO SEMILLA EL IDENTIFICADOR DEL PROCESO*/ srand ( i d ) ; /*ESTIMACION DE PI*/ f o r ( i =0; i ! = nummuestras ; i + + ) { x =( long double ) rand ( ) / RAND_MAX; y =( long double ) rand ( ) / RAND_MAX; h i p = s q r t ( pow ( x , 2 ) +pow ( y , 2 ) ) ; i f ( hip >1){ f a l l o s ++;} else { a c i e r t o s + + ; } } p i = 4 . 0 ( ( long double ) a c i e r t o s / nummuestras ) ; /*CALCULAMOS AREA*/ area=pow ( r a d i o , 2 ) p i ; r e t u r n area ; } /*MonteCarlo*/
v v
85
/*********************************************************************/ /*FUNCION recolectar_datos:PROCESO 0 HACE LA MEDIA DE LAS */ /*APROXIMACIONES LOCALES */ /*********************************************************************/ void r e c o l e c t a r _ d a t o s ( i n t i d , i n t numprocs , long double p a p r o x _ l o c a l , long double p a p r o x _ g l o b a l ) { int origen ; int destino =0; int etiqueta ; MPI_Status s t a t u s ; long double b u f f e r ; /*PROCESO ORIGEN MENSAJES*/ /*PROCESO DESTINO DATOS*/ /*ETIQUETA MENSAJES*/ /*STATUS RECEPCION MENSAJES*/ /*BUFFER RECEPCION APROXIMACIONES LOCALES*/
i f ( i d ==0){ /*RECOLECTAMOS LOS CALCULOS LOCALES Y HACEMOS LA MEDIA*/ p a p r o x _ g l o b a l= p a p r o x _ l o c a l ; f o r ( o r i g e n =1; o r i g e n<numprocs ; o r i g e n + + ) { e t i q u e t a =30+ o r i g e n ; MPI_Recv(& b u f f e r , 1 , MPI_LONG_DOUBLE, o r i g e n , e t i q u e t a , MPI_COMM_WORLD,& s t a t u s ) ; p a p r o x _ g l o b a l =( p a p r o x _ g l o b a l+ b u f f e r ) / 2 . 0 ; } } else { /*ENVIO DE LOS DATOS*/ e t i q u e t a =30+ i d ; MPI_Send ( p a p r o x _ l o c a l , 1 , MPI_LONG_DOUBLE, d e s t i n o , e t i q u e t a , MPI_COMM_WORLD ) ; } } /*distribuir_datos*/
/*********************************************************************/ /*FUNCION construir_tipo_derivado: CONSTRUYE EL TIPO DE DATOS MPI */ /*NECESARIO PARA DISTRIBUIR LOS DATOS DE ENTRADA EMPAQUETADOS */ /*********************************************************************/ void c o n s t r u i r _ t i p o _ d e r i v a d o ( Tipo_Datos_Entrada pdatos , MPI_Datatype pMPI_Tipo_Datos ) { MPI_Datatype t i p o s [ 2 ] ; int longitudes [ 2 ] ; MPI_Aint d i r e c c [ 3 ] ; MPI_Aint desplaz [ 2 ] ;
/*PRIMERO ESPECIFICAMOS LOS TIPOS*/ t i p o s [ 0 ] =MPI_LONG_DOUBLE; t i p o s [ 1 ] =MPI_LONG; /*ESPECIFICAMOS EL NUMERO DE ELEMENTOS DE CADA TIPO*/ longitudes [0]=1; longitudes [1]=1; /*CALCULAMOS LOS DESPLAZAMIENTOS DE LOS MIEMBROS DE LA ESTRUCTURA
86
275 276 277 278 279 280 281 282 283 284 285 286 287 288
} /*construir_tipo_derivado*/
/***************************************************/ /*Calculo de Areas: CODIGO APROXIMACION DE AREAS */ /*CIRCULARES MEDIANTE MONTECARLO (NO BLOQUEANTE) */ /***************************************************/ /*NUMERO MAXIMO DE PROCESOS EN EJECUCION */ # define MAX_NUM_PROCS 128 # # # # include < s t d i o . h> include < s t d l i b . h> include < math . h> include " mpi . h "
/*DECLARACION ESTRUCTURA DATOS ENTRADA*/ typedef s t r u c t { long double r a d i o ; long n m u e s t r a s _ l o c a l ; } Tipo_Datos_Entrada ; /*DECLARACION DE LA FUNCIONES QUE VAMOS A UTILIZAR*/ long double MonteCarlo ( i n t i d , long double r a d i o , long l o c a l _ n ) ; void o b t e n e r _dat os ( long double p r a d i o , long pnmuestras_global ) ; void d i s t r i b u i r _ d a t o s ( i n t i d , i n t numprocs , long double p r a d i o , long p n m u e s t r a s _ l oc a l ) ; void r e c o l e c t a r _ d a t o s ( i n t i d , i n t numprocs , long double p a p r o x _ l o c a l , long double p a p r o x _ g l o b a l ) ; void c o n s t r u i r _ t i p o _ d e r i v a d o ( Tipo_Datos_Entrada pdatos , MPI_Datatype pMPI_Tipo_Datos ) ; /**************/ /*FUNCION MAIN*/ /**************/ i n t main ( i n t argc , char
argv ) {
v Vv
x x
x x
87
long double PI25DIGITOS=3.141592653589793238462643; /*VALOR PI PARA CALCULAR EL ERROR*/ int id ; /*IDENTIFICADOR DEL PROCESO*/ i n t numprocs ; /*NUMERO DE PROCESOS*/ char nombreproc [MPI_MAX_PROCESSOR_NAME] ; /*NOMBRE PROCESADOR*/ i n t lnombreproc ; /*LONGITUD NOMBRE PROCESADOR*/ long double r a d i o ; /*RADIO CIRCUNFERENCIA*/ long n m u e s t r a s _global ; /*NUMERO DE MUESTRAS*/ long n m u e s t r a s _ l o c a l ; /*NUMERO DE MUESTRAS DE CADA PROCESO*/ long double a p r o x _ l o c a l ; /*APROX LOCAL DE CADA PROCESO*/ long double a p r o x _ g l o b a l ; /*APROX GENERAL (MEDIA DE TODAS LAS LOCALES)*/ int raiz =0; /*PROCESO QUE RECIBE LAS LOCALES Y LAS SUMA*/ double t m p i n i c = 0 . 0 ; /*TIEMPO INICIO DE LA EJECUCION*/ double t m p f i n ; /*TIEMPO FINAL DE LA EJECUCION */ int etiqueta =50; MPI_Status s t a t u s ; int origen ; /*ETIQUETA MENSAJES DE PRUEBA*/ /*STATUS RECEPCION MENSAJES DE PRUEBA*/ /*PROCESO ORIGEN MENSAJES DE PRUEBA*/
/*INICIALIZAMOS EL ENTRORNO DE EJECUCION MPI*/ M P I _ I n i t (& argc ,& argv ) ; /*ALMACENAMOS EL IDENTIFICADOR DEL PROCESO*/ MPI_Comm_rank (MPI_COMM_WORLD,& i d ) ; /*ALMACENAMOS EL NUMERO DE PROCESOS*/ MPI_Comm_size (MPI_COMM_WORLD,& numprocs ) ; /*E/S:NOMBRE DEL PROCESADOR,PROCESADOR 0*/ MPI_Get_processor_name ( nombreproc,& lnombreproc ) ; i f ( i d ==0){ f p r i n t f ( s t d o u t , " \ n P r o c e s o %d en %s E n c a r g a d o de l a E / S \ n " , i d , nombreproc ) ; } /*E/S:NOMBRE DEL PROCESADOR,TODOS LOS PROCESOS (PRUEBAS)*/ /*if(id==0){ * for (origen=1;origen<numprocs;origen++){ * MPI_Recv(nombreproc,MPI_MAX_PROCESSOR_NAME,MPI_CHAR,origen, * etiqueta,MPI_COMM_WORLD,&status); * fprintf(stdout,"Proceso %d en %s\n",origen,nombreproc); * } *} *else{ * MPI_Send(nombreproc,MPI_MAX_PROCESSOR_NAME,MPI_CHAR,0, * etiqueta,MPI_COMM_WORLD); *} */ /*OBTENEMOS DATOS INTRODUCIDOS POR EL USUARIO*/ i f ( i d ==0){ o b t e n e r _dato s(& r a d i o ,& n m u e s t r a s _ global ) ; /*NUMERO DE MUESTRAS PARA CADA PROCESO*/
88
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
/*TIEMPO INICIAL DE PROCESAMIENTO*/ i f ( i d ==0){ f p r i n t f ( stdout , " \ nProcesando . . . \ n \ n " ) ; } t m p i n i c=MPI_Wtime ( ) ; /*DISTRIBUIMOS DATOS INTRODUCIDOS POR EL USUARIO*/ d i s t r i b u i r _ d a t o s ( i d , numprocs ,& r a d i o ,& n m u e s t r a s _ l o c a l ) ; /*CALCULAMOS LA INTEGRAL PARCIAL DEL PROCESO*/ a p r o x _ l o c a l = MonteCarlo ( i d , r a d i o , n m u e s t r a s _ l o c a l ) ; /*RECOLECTAMOS AREAS CALCULADAS POR LOS PROCESOS Y HACEMOS LA MEDIA*/ r e c o l e c t a r _ d a t o s ( i d , numprocs ,& a p r o x _ l o c a l ,& a p r o x _ g l o b a l ) ; /*TIEMPO FINAL DE PROCESAMIENTO*/ t m p f i n =MPI_Wtime ( ) ; /*E/S:IMPRIMIMOS RESULTADO Y TIEMPO DE PROCESAMIENTO*/ i f ( i d ==0){ f p r i n t f ( s t d o u t , " Con n= %d m u e s t r a s , l a e s t i m a c i o n d e l a r e a de l a \ n " , n m u e s t r a s _global ) ; f p r i n t f ( s t d o u t , " de l a c i r c u n f e r e n c i a con r a d i o %Lf e s \ n " , r a d i o ) ; f p r i n t f ( s t d o u t , " %.60 Lf \ n " , a p r o x _ g l o b a l ) ; f p r i n t f ( s t d o u t , " E r r o r < %f \ n \ n " , f a b s ( PI25DIGITOS r a d i o r a d i o a p r o x _ g l o b a l ) ) ; f p r i n t f ( s t d o u t , " Numero P r o c e s o s : %d \ n " , numprocs ) ; f p r i n t f ( s t d o u t , " Tiempo P r o c e s a m i e n t o : % f \ n \ n " , t m p f i n t m p i n i c ) ; } /*FINALIZAMOS EL ENTRORNO DE EJECUCION MPI*/ MPI_Finalize ( ) ; } /*main*/
/***************************************************************/ /*FUNCION obtener_datos:PROCESO 0 CONSULTA AL USUARIO EL RADIO */ /*DE LA CIRCUNFERENCIA Y EL NUMERO DE MUESTRAS GLOBAL */ /***************************************************************/ void o b t e n e r _dat os ( long double p r a d i o , long pnmuestras_global ) { /*E/S:PETICION DE DATOS*/ f p r i n t f ( s t d o u t , " I n t r o d u z c a r a d i o de l a c i r c u n f e r e n c i a \ n " ) ; scanf ( " % " , pradio ) ; Lf f p r i n t f ( s t d o u t , " I n t r o d u z c a numero de m u e s t r a s \ n " ) ; s c a n f ( " % d " , pnmuestras_global ) ; l
89
} /*obtener_datos*/
/**********************************************************************/ /*FUNCION distribuir_datos:PROCESO 0 DISTIBUYE RADIO DE LA */ /*CIRCUNFERENCIA Y EL NUMERO DE MUESTRAS (n) ENTRE LOS DEMAS PROCESOS */ /**********************************************************************/ void d i s t r i b u i r _ d a t o s ( i n t i d , i n t numprocs , long double p r a d i o , long p n m u e s t r a s _ l oc a l ) { MPI_Datatype MPI_Tipo_Datos_Entrada ; Tipo_Datos_Entrada d a t o s _ e n tr ada ; int origen =0; /*PROCESO ORIGEN MENSAJES*/ int destino ; /*PROCESO DESTINO DATOS*/ int etiqueta ; /*ETIQUETA MENSAJES*/ MPI_Request r e q u e s t ; /*PETICION MENSAJES NO BLOQUEANTES*/ MPI_Status s t a t u s ; /*STATUS RECEPCION*/ c o n s t r u i r _ t i p o _ d e r i v a d o (& d a t o s _ e n tr ada,& MPI_Tipo_Datos_Entrada ) ; i f ( i d ==0){ /*ENVIO DE LOS DATOS*/ d a t o s _ e n trada . r a d i o = p r a d i o ; d a t o s _ e n trada . n m u e s t r a s _ l o c a l = p n m u e s t r a s _ l o c al ; f o r ( d e s t i n o =1; d e s t i n o <numprocs ; d e s t i n o + + ) { e t i q u e t a =30; MPI_Isend(& d a t o s _ e ntr ada , 1 , MPI_Tipo_Datos_Entrada , d e s t i n o , e t i q u e t a , MPI_COMM_WORLD,& r e q u e s t ) ; } } else { /*RECEPCION DE LOS DATOS*/ e t i q u e t a =30; MPI_Irecv (& d a t o s _ e n trada , 1 , MPI_Tipo_Datos_Entrada , o r i g e n , e t i q u e t a , MPI_COMM_WORLD,& r e q u e s t ) ; MPI_Wait(& r e q u e s t ,& s t a t u s ) ; p r a d i o= d a t o s _ e ntr ada . r a d i o ; p n m u e s t r a s _ l o c al= d a t o s _ e n trada . n m u e s t r a s _ l o c a l ; } } /*distribuir_datos*/
/************************************************************************/ /*FUNCION MonteCarlo: RETORNA EL AREA DE LA CIRCUNFERENCIA CON RADIO */ /*radio UTILIZANDO EL NUM.MUESTRAS nummuestras MEDIANTE MONTECARLO */ /************************************************************************/ long double MonteCarlo ( i n t i d , long double r a d i o , long nummuestras ) { long long long long long long double p i ; double area ; double x ; double y ; double h i p ; aciertos =0; /*VBLE QUE ALMACENA NUMERO PI*/ /*AREA CIRCUNFERENCIA*/ /*EJE ORDENADAS MUESTRA ACTUAL*/ /*EJE COORDENADAS MUESTRA ACTUAL*/ /*HIPOTENUSA MUESTRA ACTUAL*/ /*NUM.MUESTRAS QUE CAEN DENTRO DE LA CIRCUNFERENCIA*/
v v
90
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
/*UTILIZAMOS COMO SEMILLA EL IDENTIFICADOR DEL PROCESO*/ srand ( i d ) ; /*ESTIMACION DE PI*/ f o r ( i =0; i ! = nummuestras ; i + + ) { x =( long double ) rand ( ) / RAND_MAX; y =( long double ) rand ( ) / RAND_MAX; h i p = s q r t ( pow ( x , 2 ) +pow ( y , 2 ) ) ; i f ( hip >1){ f a l l o s ++;} else { a c i e r t o s + + ; } } p i = 4 . 0 ( ( long double ) a c i e r t o s / nummuestras ) ; /*CALCULAMOS AREA*/ area=pow ( r a d i o , 2 ) p i ; r e t u r n area ; } /*MonteCarlo*/
/*********************************************************************/ /*FUNCION recolectar_datos:PROCESO 0 HACE LA MEDIA DE LAS */ /*APROXIMACIONES LOCALES */ /*********************************************************************/ void r e c o l e c t a r _ d a t o s ( i n t i d , i n t numprocs , long double p a p r o x _ l o c a l , long double p a p r o x _ g l o b a l ) { int origen ; /*PROCESO ORIGEN MENSAJES*/ int destino =0; /*PROCESO DESTINO DATOS*/ int etiqueta ; /*ETIQUETA MENSAJES*/ long double b u f f e r ; /*BUFFER RECEPCION APROXIMACIONES LOCALES*/ int i ; /*CONTADOR*/ MPI_Request r e q u e s t ; MPI_Request r e q u e s t s [MAX_NUM_PROCS ] ; MPI_Status s t a t u s ;
i f ( i d ==0){ paprox_global= paprox_local ; /*MANDAMOS LAS PETICIONES DE DATOS*/ f o r ( o r i g e n =1; o r i g e n<numprocs ; o r i g e n + + ) { e t i q u e t a =30+ o r i g e n ; MPI_Irecv (& b u f f e r , 1 , MPI_LONG_DOUBLE, o r i g e n , e t i q u e t a , MPI_COMM_WORLD,& r e q u e s t s [ o r i g e n ] ) ; } /*RECOLECTAMOS LOS CALCULOS LOCALES Y HACEMOS LA MEDIA*/ f o r ( i =1; i <numprocs ; i + + ) { MPI_Waitany ( numprocs , r e q u e s t s ,& o r i g e n ,& s t a t u s ) ; p a p r o x _ g l o b a l =( p a p r o x _ g l o b a l+ b u f f e r ) / 2 . 0 ; }
91
/*********************************************************************/ /*FUNCION construir_tipo_derivado: CONSTRUYE EL TIPO DE DATOS MPI */ /*NECESARIO PARA DISTRIBUIR LOS DATOS DE ENTRADA EMPAQUETADOS */ /*********************************************************************/ void c o n s t r u i r _ t i p o _ d e r i v a d o ( Tipo_Datos_Entrada pdatos , MPI_Datatype pMPI_Tipo_Datos ) { MPI_Datatype t i p o s [ 2 ] ; int longitudes [ 2 ] ; MPI_Aint d i r e c c [ 3 ] ; MPI_Aint desplaz [ 2 ] ;
/*PRIMERO ESPECIFICAMOS LOS TIPOS*/ t i p o s [ 0 ] =MPI_LONG_DOUBLE; t i p o s [ 1 ] =MPI_LONG; /*ESPECIFICAMOS EL NUMERO DE ELEMENTOS DE CADA TIPO*/ longitudes [0]=1; longitudes [1]=1; /*CALCULAMOS LOS DESPLAZAMIENTOS DE LOS MIEMBROS DE LA ESTRUCTURA RELATIVOS AL COMIENZO DE DICHA ESTRUCTURA*/ MPI_Address ( pdatos ,& d i r e c c [ 0 ] ) ; MPI_Address ( & ( pdatos >r a d i o ) , & d i r e c c [ 1 ] ) ; MPI_Address ( & ( pdatos >n m u e s t r a s _ l o c a l ) , & d i r e c c [ 2 ] ) ; desplaz [ 0 ] = d i r e c c [1] d i r e c c [ 0 ] ; desplaz [ 1 ] = d i r e c c [2] d i r e c c [ 0 ] ; /*CREACION TIPO DATOS DERIVADO*/ MPI_Type_struct ( 2 , l o n g i t u d e s , desplaz , t i p o s , pMPI_Tipo_Datos ) ; /*CERTIFICARLO DE MANERA QUE PUEDA SER USADO*/ MPI_Type_commit ( pMPI_Tipo_Datos ) ; } /*construir_tipo_derivado*/
x x
x x
92
Captulo 6
Comunicacin Colectiva
Las operaciones de comunicacin colectiva son aquellas que se aplican al mismo tiempo a todos los procesos pertenecientes a un comunicador. Tienen una gran importancia en el estndar MPI, debido a la claridad de su sintaxis y a su eciencia. Para analizar su utilidad y conveniencia implementaremos el algoritmo Regla del Trapecio de manera que haga un uso inteligente de dichas operaciones.
Donde ,y , . Una manera de realizar este clculo mediante un algoritmo paralelo es dividir el intervalo entre los procesos haciendo que cada proceso calcule la integral de sobre su subintervalo. Para estimar la integral completa se suman los clculos locales de cada proceso. Supongamos que tenemos procesos y segmentos, y, para simplicar, supongamos que es divisible entre . En este caso es natural que el primer proceso calcule la integral de los primeros segmentos, el segundo proceso calcular el rea de los siguientes segmentos, etc. Siguiendo esta regla el proceso estimar la integral del subintervalo:
dt i
El nmero de procesos
93
mediante la divisin del intervalo La regla del trapecio estima mentos iguales, calculando la siguiente suma:
Q FD
dt i g6 9)
en
seg-
Q SFD
)6 8Q
G t jD
g6 9)
dt i
94
Los dos primeros datos se pueden conseguir llamando a las funciones MPI_Comm_size() y MPI_Comm_rank(). Sin embargo tanto el intervalo como el nmero de segmentos deben ser introducidos por el usuario. Por otro lado sera positivo que el usuario pudiera elegir la funcin a integrar (dentro de un conjunto predenido de funciones). Como explicamos en la seccin 4.4 slo un proceso (normalmente el proceso 0) debe encargarse de obtener los datos de la entrada estndar y distribuirlos entre los dems procesos. sto puede hacerse mediante paso de mensajes o mediante comunicacin colectiva, siendo la segunda opcin ms eciente. En la seccin 6.2 se explica el uso de las operaciones de comunicacin colectiva con dicho propsito. Por otro lado una buena forma de sumar los clculos individuales de los procesos es hacer que cada proceso enve su clculo local al proceso 0, y que el proceso 0 haga la suma nal. De nuevo podemos emplear al menos dos tcnicas: paso de mensajes y operaciones de reduccin. Dado que las operaciones de reduccin son ms ecientes, utilizaremos la segunda opcin. Las funciones que ofreceremos al usuario estarn codicadas en funciones de cdigo C, por lo que tendremos que modicar el cdigo y compilarlo de nuevo para introducir nuevas funciones. Entre las funciones ofrecidas incluiremos al menos las siguientes:
Esta ltima funcin nos permite realizar la bsqueda del nmero nos proporciona un mtodo para computar :
dt i
w Q
I t
I "D
Q FD t
La funcin
a integrar
srn p h Q ! q o FD
s rRn pq o FD Q ! n FD Q FD Q Q d@ FD
Q FD
r n q p
El nmero de segmentos
95
Figura 6.1: Procesos estructurados en rbol 1. 2. Proceso 0 recoge los datos de la entrada estndar Proceso 0 enva un mensaje a cada uno de los restantes procesos comunicndole los datos de entrada
Si utilizamos un bucle para realizar el segundo paso, los procesos con identicador mayor deben continuar esperando mientras el proceso 0 enva los datos de entrada a los procesos con identicador menor. ste no es slo un asunto de E/S y por supuesto no es un comportamiento deseable: el punto principal del procesamiento paralelo es conseguir que mltiples procesos colaboren para resolver un problema. Si uno de los procesos est haciendo la mayora del trabajo, podramos usar mejor una mquina convencional de un solo procesador. Por otro lado observamos que existe una ineciencia similar en el nal del algoritmo al utilizar paso de mensajes en el proceso de recoleccin, donde el proceso 0 hace todo el trabajo de recolectar y sumar las integrales locales. La pregunta que surge es... cmo podemos dividir el trabajo ms equitativamente entre los procesos? Una solucin natural es imaginar que tenemos un rbol de procesos, con el proceso 0 como raz. Durante la primera etapa de la distribucin de los datos pongamos que el proceso 0 enva los datos al 4. Durante la siguiente etapa el 0 enva los datos al 2, mientras que el 4 los enva al 6. Durante la ltima etapa el 0 se los enva al 1, mientras el 2 los enva al 3, el 4 al 5 y el 6 al 7 (mirar la gura 6.1). As reducimos el bucle de distribucin de la entrada de 7 etapas a 3 etapas. De manera ms general, si tenemos procesos este procedimiento permite distribuir los datos de entrada en etapas, mientras que de la anterior manera lo haciamos en etapas. Si es grande esta mejora es una gran ventaja. Si queremos utilizar un esquema de distribucin estructurado en rbol en nuestro algoritetapas. En la implementacin de dicho bucle mo, necesitamos introducir un bucle con cada proceso necesita calcular en cada etapa: Si recibe, y en caso de hacerlo, el origen; y
Q 3 |gD 4i10
Q 3 |gD 4210
QI G R~}|gD
96
Como puede suponerse estos clculos pueden ser algo complicados, especialmente porque no hay un ordenamiento jo. En nuestro ejemplo elegimos: 1. 2. 3. 0 enva al 4 0 enva al 2, 4 al 6 0 enva al 1, 2 al 3, 4 al 5, 6 al 7
De hecho, a menos que sepamos algo acerca de la topologa subyacente de nuestra mquina no podremos decidir realmente qu esquema es mejor. Lo ideal sera usar una funcin diseada especcamente para la mquina que estemos usando de manera que no nos tengamos que preocupar acerca de todos los detalles, y que no tengamos que modicar el cdigo cada vez que cambiamos de mquina. Y como habr podido adivinar MPI proporciona dicha funcin.
97
2.
3.
Por supuesto caemos en la misma cuestin que cuando discutiamos la implementacin de nuestro propio broadcast: Hace un uso ptimo de la topologa de nuestra mquina esta estructura en rbol? Una vez ms debemos responder que ello depende de la mquina. As que, como antes, debemos dejar a MPI hacer dicho trabajo utilizando una funcin optimizada. La suma global que queremos calcular es un ejemplo de una clase general de operaciones de comunicacin colectiva llamadas operationes de reduccin. Las operaciones de reduccin forman un subconjunto de las operaciones de comunicacin colectiva. En una operacin de reduccin global todos los procesos (pertenecientes a un comunicador) aportan datos, los cuales se combinan usando una operacin binaria. Las operaciones binarias tpicas son la suma, el mximo, el mnimo, AND lgico, etc. La funcin MPI que implementa una operacin de reduccin es: int MPI_Reduce(void* operando, void* resultado, int contador, MPI_Datatype tipo_datos, MPI_Op operacion, int raiz, MPI_Comm comunicador); La funcin MPI_Reduce combina los operandos referenciados por operando usando la operacin sealada por operacion y almacena el resultado en la variable resultado perteneciente al proceso raiz. Tanto operando como resultado referencian contador posiciones de memoria del tipo tipo_datos. MPI_Reduce() debe ser llamado por todos los procesos pertenecientes a comunicador; adems contador, tipo_datos y operacion deben ser iguales para todos los procesos. El argumento operacion puede adquirir uno de los valores predenidos mostrados en el cuadro 6.1. Tambin es posible denir operaciones adicionales.
dt i FD Q
98
/********************************************************/ /*Regla del Trapecio: CODIGO APROXIMACION DE INTEGRALES */ /*MEDIANTE LA REGLA DEL TRAPECIO */ /********************************************************/ # include < s t d i o . h> # include " mpi . h " /*DECLARACION ESTRUCTURA DATOS ENTRADA*/ typedef s t r u c t { long double a ; long double b ; long nsegmentos ; i n t nfuncion ; } Tipo_Datos_Entrada ; /*DECLARACION DE LA FUNCIONES QUE VAMOS A UTILIZAR*/ long double T r a p e c i o ( long double l o c a l _ a , long double l o c a l _ b , long l o c a l _ n , long double h , i n t numfuncion ) ; long double F1 ( long double x ) ; long double F2 ( long double x ) ; long double F3 ( long double x ) ;
99
long double F4 ( long double x ) ; void o b t e n e r _dat os ( i n t i d , long double pa , long double pb , long pn , i n t pnumfuncion ) ; void d i s t r i b u i r _ d a t o s ( i n t i d , long double pa , long double pb , long pn , i n t pnumfuncion ) ; void r e c o l e c t a r _ d a t o s ( i n t i d , i n t numprocs , long double p p a r c i a l , long double pcompleta ) ; void c o n s t r u i r _ t i p o _ d e r i v a d o ( Tipo_Datos_Entrada pdatos , MPI_Datatype pMPI_Tipo_Datos ) ; /**************/ /*FUNCION MAIN*/ /**************/ i n t main ( i n t argc , char long double a ; long double b ; long n ;
argv ) { /*COMIENZO DEL INTERVALO GENERAL*/ /*FINAL DEL INTERVALO GENERAL*/ /*NUMERO DE SEGMENTOS EN TOTAL*/
int id ; /*IDENTIFICADOR DEL PROCESO*/ i n t numprocs ; /*NUMERO DE PROCESOS*/ char nombreproc [MPI_MAX_PROCESSOR_NAME] ; /*NOMBRE PROCESADOR*/ i n t lnombreproc ; /*LONGITUD NOMBRE PROCESADOR*/ long double h ; /*ANCHO DE CADA SEGMENTO*/ long double l o c a l _ a ; /*COMIENZO DEL SUBINTERVALO DE CADA PROCESO*/ long double l o c a l _ b ; /*FINAL DEL SUBINTERVALO DE CADA PROCESO*/ long l o c a l _ n ; /*NUMERO DE SEGMENTOS PARA CADA PROCESO*/ long double p a r c i a l ; /*INTEGRAL PARCIAL DE CADA PROCESO*/ long double completa ; /*INTEGRAL COMPLETA (SUMA DE TODAS LAS PARCIALES)*/ double t m p i n i c = 0 . 0 ; /*TIEMPO INICIO DE LA EJECUCION*/ double t m p f i n ; /*TIEMPO FINAL DE LA EJECUCION*/ i n t numfuncion ; /*NUMERO DE FUNCION A UTILIZAR*/ i n t e t i q u e t a =50; MPI_Status s t a t u s ; int origen ;
/*INICIALIZAMOS EL ENTORNO DE EJECUCION MPI*/ M P I _ I n i t (& argc ,& argv ) ; /*ALMACENAMOS EL IDENTIFICADOR DEL PROCESO*/ MPI_Comm_rank (MPI_COMM_WORLD,& i d ) ; /*ALMACENAMOS EL NUMERO DE PROCESOS*/ MPI_Comm_size (MPI_COMM_WORLD,& numprocs ) ; /*E/S:NOMBRE DEL PROCESADOR,PROCESADOR 0*/ MPI_Get_processor_name ( nombreproc,& lnombreproc ) ; i f ( i d ==0){ f p r i n t f ( s t d o u t , " \ n P r o c e s o %d en %s E n c a r g a d o de l a E / S \ n " , i d , nombreproc ) ; } /*E/S:NOMBRE DEL PROCESADOR,TODOS LOS PROCESOS (PARA PRUEBAS)*/ /*if(id==0){
v v
v v
v wv
100
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
} /*main*/
101
/***********************************************************************/ /*FUNCION obtener_datos:PROCESO 0 CONSULTA AL USUARIO COMIENZO Y FINAL */ /*DEL INTERVALO [a,b] Y EL NUMERO DE SEGMENTOS (n) */ /***********************************************************************/ void o b t e n e r _dat os ( i n t i d , long double pa , long double pb , long pn , i n t pnumfuncion ) { /*E/S:PETICION DE DATOS*/ i f ( i d ==0){ f p r i n t f ( s t d o u t , " \ n I n t r o d u z c a num . de l a f u n c i o n a i n t e g r a r \ n " ) ; f p r i n t f ( s t d o u t , " \ nF1 =2 x F2=x^2 F3 = 1 / x F4 = 4 / ( 1 + x ^ 2 ) \ nF " ) ; s c a n f ( " % " , pnumfuncion ) ; d i f ( pnumfuncion < 1 | | pnumfuncion > 4 ) { f p r i n t f ( s t d o u t , " E r r o r en l a e n t r a d a , u t i l i z a n d o f u n c i o n F1=2 x \ n " ) ; pnumfuncion =1; } f p r i n t f ( s t d o u t , " I n t r o d u z c a un v a l o r p a r a a ( i n i c i o d e l i n t e r v a l o ) \ n " ) ; s c a n f ( " % " , pa ) ; Lf f p r i n t f ( s t d o u t , " I n t r o d u z c a un v a l o r p a r a b ( f i n a l d e l i n t e r v a l o ) \ n " ) ; s c a n f ( " % " , pb ) ; Lf f p r i n t f ( s t d o u t , " I n t r o d u z c a numero de s e g m e n t o s \ n " ) ; s c a n f ( " % d " , pn ) ; l }
/**************************************************************************/ /*FUNCION distribuir_datos:PROCESO 0 DISTIBUYE COMIENZO Y FINAL DEL */ /*INTERVALO [a,b] Y EL NUMERO DE SEGMENTOS (n) ENTRE LOS DEMAS PROCESOS */ /**************************************************************************/ void d i s t r i b u i r _ d a t o s ( i n t i d , long double pa , long double pb , long pn , i n t pnumfuncion ) { MPI_Datatype MPI_Tipo_Datos_Entrada ; Tipo_Datos_Entrada d a t o s _ e n tr ada ; int raiz =0; /*PROCESO QUE ENVIA LOS DATOS A LOS DEMAS PROCESOS*/
/*CONSTRUIMOS EL TIPO MPI PARA EMPAQUETAR LOS DATOS DE ENTRADA*/ c o n s t r u i r _ t i p o _ d e r i v a d o (& d a t o s _ e n tr ada,& MPI_Tipo_Datos_Entrada ) ; i f ( i d ==0){ /*EMPAQUETADO DE DATOS*/ d a t o s _ e n trada . a= pa ; d a t o s _ e n trada . b= pb ; d a t o s _ e n trada . nsegmentos= pn ; d a t o s _ e n trada . n f u n c i o n = pnumfuncion ; }
102
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
MPI_Bcast (& d a t o s _ e ntr ada , 1 , MPI_Tipo_Datos_Entrada , r a i z ,MPI_COMM_WORLD ) ; if ( id !=0){ /*RECOGIDA DE DATOS*/ pa=d a t o s _ e n tra da . a ; pb=d a t o s _ e n tra da . b ; pn=d a t o s _ e n tra da . nsegmentos ; pnumfuncion= d a t o s _ e nt rada . n f u n c i o n ; } } /*distribuir_datos*/
/************************************************************************/ /*FUNCION Trapecio:FUNCION QUE APLICA LA REGLA DEL TRAPECIO AL */ /*SUBINTERVALO COMPRENDIDO ENTRE local_a Y local_b, CON UN NUMERO DE */ /*SEGMENTOS local_n Y UN TAMAO DE SEGMENTO h */ /************************************************************************/ long double T r a p e c i o ( long double l o c a l _ a , long double l o c a l _ b , long l o c a l _ n , long double h , i n t numfuncion ) { long double ( f ) ( long double ) ; long double i n t e g r a l ; long double x ; int i ;
switch ( numfuncion ) { case 1 : f =F1 ; break ; case 2 : f =F2 ; break ; case 3 : f =F3 ; break ; case 4 : f =F4 ; break ; } i n t e g r a l =( f ( l o c a l _ a )+ f ( l o c a l _ b ) ) / 2 . 0 ; x= l o c a l _ a ; f o r ( i =1; i <= l o c a l _ n 1; i + + ) { x+=h ; i n t e g r a l += f ( x ) ; } i n t e g r a l =h ; return i n t e g r a l ; } /*Trapecio*/
/*******************************************************************/ /*FUNCION recolectar_datos:PROCESO 0 SUMA LAS INTEGRALES PARCIALES */ /*CALCULADAS POR LOS DEMAS PROCESOS. */ /*******************************************************************/ void r e c o l e c t a r _ d a t o s ( i n t i d , i n t numprocs , long double p p a r c i a l , long double pcompleta ) { int raiz =0; /*PROCESO QUE RECIBE LAS PARCIALES Y LAS SUMA*/
v v v v
/*VBLE QUE ALMACENA FUNCION A INTEGRAR*/ /*VBLE QUE ALMACENA EL RESULTADO*/ /*POSICION EN EL EJE X*/ /*CONTADOR*/
103
/********************************/ /*FUNCION F1(x):FUNCION f(x)=2x */ /********************************/ long double F1 ( long double x ) { long double v a l o r _ r e t o r n o ; v a l o r _ r e t o r n o =2 x ; return valor_retorno ; }
/*********************************/ /*FUNCION F2(x):FUNCION f(x)=x^2 */ /*********************************/ long double F2 ( long double x ) { long double v a l o r _ r e t o r n o ; v a l o r _ r e t o r n o =x x ; return valor_retorno ; }
/*********************************/ /*FUNCION F3(x):FUNCION f(x)=1/x */ /*********************************/ long double F3 ( long double x ) { long double v a l o r _ r e t o r n o ; v a l o r _ r e t o r n o =1/ x ; return valor_retorno ; } /***************************************/ /*FUNCION F4(x):FUNCION f(x)=4/(1+x^2) */ /***************************************/ long double F4 ( long double x ) { long double v a l o r _ r e t o r n o ; valor_retorno =4/(1+x x ) ; return valor_retorno ; }
/*********************************************************************/ /*FUNCION construir_tipo_derivado: CONSTRUYE EL TIPO DE DATOS MPI */ /*NECESARIO PARA DISTRIBUIR LOS DATOS DE ENTRADA EMPAQUETADOS */ /*********************************************************************/ void c o n s t r u i r _ t i p o _ d e r i v a d o ( Tipo_Datos_Entrada pdatos , MPI_Datatype pMPI_Tipo_Datos ) { MPI_Datatype t i p o s [ 4 ] ;
104
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
/*PRIMERO ESPECIFICAMOS LOS TIPOS*/ t i p o s [ 0 ] =MPI_LONG_DOUBLE; t i p o s [ 1 ] =MPI_LONG_DOUBLE; t i p o s [ 2 ] =MPI_LONG ; t i p o s [ 3 ] = MPI_INT ; /*ESPECIFICAMOS EL NUMERO DE ELEMENTOS DE CADA TIPO*/ longitudes [0]=1; longitudes [1]=1; longitudes [2]=1; longitudes [3]=1; /*CALCULAMOS LOS DESPLAZAMIENTOS DE LOS MIEMBROS DE LA ESTRUCTURA RELATIVOS AL COMIENZO DE DICHA ESTRUCTURA*/ MPI_Address ( pdatos ,& d i r e c c [ 0 ] ) ; MPI_Address ( & ( pdatos >a ) , & d i r e c c [ 1 ] ) ; MPI_Address ( & ( pdatos >b ) , & d i r e c c [ 2 ] ) ; MPI_Address ( & ( pdatos >nsegmentos ) , & d i r e c c [ 3 ] ) ; MPI_Address ( & ( pdatos >n f u n c i o n ) , & d i r e c c [ 4 ] ) ; desplaz [ 0 ] = d i r e c c [1] d i r e c c [ 0 ] ; desplaz [ 1 ] = d i r e c c [2] d i r e c c [ 0 ] ; desplaz [ 2 ] = d i r e c c [3] d i r e c c [ 0 ] ; desplaz [ 3 ] = d i r e c c [4] d i r e c c [ 0 ] ; /*CREACION TIPO DATOS DERIVADO*/ MPI_Type_struct ( 4 , l o n g i t u d e s , desplaz , t i p o s , pMPI_Tipo_Datos ) ; /*CERTIFICARLO DE MANERA QUE PUEDA SER USADO*/ MPI_Type_commit ( pMPI_Tipo_Datos ) ; } /*construir_tipo_derivado*/
x x x x
x x x x
Captulo 7
Comunicadores y Topologas
El uso de comunicadores y topologas hace a MPI diferente de la mayora de los dems sistemas de paso de mensajes. En pocas palabras, un comunicador es una coleccin de procesos que pueden mandarse mensajes entre ellos. Una topologa es una estructura impuesta en los procesos de un comunicador que permite a los procesos ser direccionados de diferentes maneras. Para ilustrar estas ideas desarrollaremos el cdigo que implementa el algoritmo de Fox para multiplicar dos matrices cuadradas.
La siguiente armacin dene nuestra tabla de procesos: el proceso pertenece a la la y la columna dadas por . Adems diremos que el proceso con direccin tiene asignadas las submatrices: . . . . . .
. . .
. . .
105
Qi a 'SD e
e e e pU s o U s p o ff U s 9p o U 9p 9 ' U VU e ff U U q
eU s e U e U ff U s o s p o t 9p o t 9p 9 U U e ff U U s 9q o t p q t
G G g qiIi dI r2i2q2qfAXph
E ) ) Q D k
m6 d9)
106
Cuadro 7.1: Particin Matriz 6*6 en 9 Procesos Por ejemplo, si , particionada como se indica en el cuadro 7.1. En el algoritmo de Fox las submatrices acumuladas por el proceso . Algoritmo bsico
Desde paso=0 hasta paso=q-1(aumentar paso en cada iteracin):
entonces la matriz
son multiplicadas y
1.
Elegir una submatriz de A de cada una de las las de procesos. La submatriz elegida en la la ser , donde
2. 3.
En cada una de las las de procesos hacer un broadcast de la submatriz elegida hacia los dems procesos en dicha la. En cada proceso multiplicar la submatriz recibida de A por la matriz de B que reside en dicho proceso, sin modicar ninguna de estas matrices. Sumar el resultado de la multiplicacin al valor que contiene el proceso en la matriz resultado C. En cada proceso enviar la submatriz de B al proceso que est encima de l (los procesos de la primera la enviarn la submatriz a la ltima la).
4.
7.2. Comunicadores
Si intentamos implementar el algoritmo de Fox, parece claro que nuestro trabajo se facilitara si pudiramos tratar ciertos subconjuntos de procesos como el universo de la comunicacin, al menos temporalmente. Por ejemplo, en el pseudocdigo
2. En cada una de las las de procesos hacer un broadcast de la submatriz elegida hacia los dems procesos en dicha la.
# # ! "# # '! ! !
8X4V
# # (! '!
Proceso 6
Proceso 7
&
% q
Proceso 3
Proceso 4
# ! $ # " !
Proceso 5
Proceso 0
Proceso 1
Proceso 2
107
sera til tratar cada columna de procesos como el universo de la comunicacin. El mecanismo que MPI proporciona para tratar a un subconjunto de procesos como el universo de la comunicacin son los comunicadores. Hasta ahora hemos denido al comunicador como una coleccin de procesos que pueden mandarse mensajes entre ellos. Ahora que queremos construir nuestros propios comunicadores necesitaremos una discusin ms profunda. En MPI existen dos tipos de comunicadores: intracomunicadores e intercomunicadores. Los intracomunicadores son esencialmente una coleccin de procesos que pueden mandarse mensajes entre ellos y utilizar operaciones de comunicacin colectivas. Por ejemplo, MPI_COMM_WORLD es un intracomunicador, y queremos formar para cada la y cada columna del algoritmo de Fox otro intracomunicador. Los intercomunicadores, como su propio nombre indica, son utilizados para mandar mensajes entre los procesos pertenecientes a intracomunicadores disjuntos. Por ejemplo, un intercomunicador podra ser til en un entorno que nos permitiera crear procesos dinmicamente: un nuevo conjunto de procesos que formen un intracomunicador podra ser enlazado al conjunto de procesos original (por ejemplo MPI_COMM_WORLD) mediante un intercomunicador. Nosotros slo utilizaremos intracomunicadores. Un intracomunicador mnimo est compuesto de:
Un grupo es una coleccin ordenada de procesos. Si un grupo consiste en procesos, a cada proceso en el grupo se le asigna un nico identicador, que no es ms que un entero no negativo en el rango . Un contexto puede ser entendido como una etiqueta denida por el sistema que es atribuida al grupo. De este modo dos procesos que pertenecen al mismo grupo y usan el mismo contexto pueden comunicarse. Esta paridad grupo-contexto es la forma ms bsica de comunicador. Otros datos pueden ser asociados al comunicador. En particular, se le puede asociar una estructura o topologa al comunicador, permitiendo un esquema de direccionamiento de los procesos ms natural. Abordaremos las topologas en la seccin 7.5.
Q FD
g m
I G gi q q q i I i rdfffAXph
Un Grupo, y Un Contexto.
108
Este cdigo construye de una manera muy estricta el nuevo comunicador. Primero crea una lista de los procesos que debern ser asignados al nuevo comunicador. Luego crea un grupo con dichos procesos. sto requiere dos llamadas; primero se obtiene el grupo asociado a MPI_COMM_WORLD, dado que ste es el grupo del cual se extraen los procesos para el nuevo grupo; luego se crea el grupo con MPI_Group_incl(). Finalmente el nuevo comunicador es creado con una llamada a MPI_Comm_create(). La llamada a MPI_Comm_create() asocia implcitamente un contexto al nuevo grupo. El resultado es el comunicador com_primera_la. Ahora los procesos pertenecientes a com_primera_la pueden ejecutar operaciones de comunicacin colectivas. Por ejemplo, el proceso 0 (en grupo_primera_la) a los otros procesos del grupo grupo_primera_la: puede hacer un broadcast de su matriz int mi_id_en_primera_fila; float* A_00; /* mi_id ES EL IDENT. DEL PROCESO EN MPI_GROUP_WORLD */ if(mi_id<q){ MPI_Comm_rank(com_primera_fila,&mi_id_en_primera_fila); /* ASIGNAMOS ESPACIO A A_00, ORDEN=n */ A_00=(float*) malloc(n*n*sizeof(float)); if(mi_id_en_primera_fila==0){ /*INICIALIZAMOS A_00 */ . . . }
109
Los grupos y los comunicadores son objetos opacos. Desde un punto de vista prctico sto signica que los detalles de su representacin interna dependen de la implementacin MPI particular, y como consecuencia el usuario no puede acceder directamente a ellos. En vez de esto el usuario accede a un manejador que referencia al objeto opaco, de manera que dichos objetos opacos son manipulados por funciones MPI especiales, como por ejemplo MPI_Comm_create(), MPI_Group_incl() y MPI_Comm_group(). Los contextos no son explcitamente usados en ninguna funcin MPI. En vez de ello, son implcitamente asociados a los grupos cuando los comunicadores son creados. La sintaxis de los comandos que hemos usado para crear com_primera_la es bastante sencilla. El primer comando int MPI_Comm_group(MPI_Comm com, MPI_Group* grupo) simplemente retorna el grupo perteneciente al comunicador com. El segundo comando int MPI_Group_incl(MPI_Group antiguo_grupo, int tamano_nuevo_grupo, int* ids_antiguo_grupo, MPI_Group* nuevo_grupo) crea un nuevo grupo a partir de una lista de procesos pertenecientes al grupo existente antiguo_grupo. El nmero de procesos en el nuevo grupo es tamano_nuevo_grupo, y los procesos que sern incluidos son listados en ids_antiguo_grupo. El proceso 0 en nuevo_grupo tiene el identicador ids_antiguo_grupo[0] en antiguo_grupo, el proceso 1 en nuevo_grupo es el ids_antiguo_grupo[1] en antiguo_grupo, y as sucesivamente. El comando nal int MPI_Comm_create(MPI_Comm antiguo_com, MPI_Group nuevo_grupo, MPI_Comm* nuevo_com) asocia el contexto al grupo nuevo_grupo, y crea el comunicador nuevo_com. Todos los procesos en nuevo_grupo pertenecen al grupo subyacente antiguo_com. Existe una diferencia extremadamente importante entre las primeras dos funciones y la tercera. MPI_Comm_group() y MPI_Group_incl() son ambas operaciones locales. Ello quiere decir que no hay comunicacin entre los procesos implicados en dicha ejecucin. Sin embargo MPI_Comm_create() es una operacin colectiva. Todos los procesos en antiguo_grupo deben llamar a MPI_Comm_create() con los mismos argumentos. El estndar MPI da tres razones para ello:
Permite a la implementacin colocar a MPI_Comm_create() como la primera de las comunicaciones colectivas regulares.
110
Notemos que como MPI_Comm_create() es colectiva tendr un comportamiento sincronizador. En particular, si varios comunicadores estn siendo creados, todos deben ser creados en el mismo orden en todos los procesos.
Una nica llamada a MPI_Comm_split() crea nuevos comunicadores, todos ellos con el mismo nombre com_la. Por ejemplo, si el grupo com_la consistir en los procesos 0, 1 y 2 para los procesos 0, 1 y 2. En los procesos 3, 4 y 5 el grupo subyacente a nuevo_com ser el formado por los procesos 3, 4 y 5; y lo mismo ocurrir con los procesos 6, 7 y 8. La sintaxis de MPI_Comm_split() es: int MPI_Comm_split(MPI_Comm antiguo_com, int clave_particion, int clave_id, MPI_Comm* nuevo_com) La llamada crea un comunicador para cada valor de clave_particion. Los procesos con el mismo valor en clave_particion forman un nuevo grupo. El identicador de los procesos en el nuevo grupo estar determinado por su valor en clave_id. Si los procesos y llaman ambos a la funcin MPI_Comm_split() con el mismo valor en clave_particion, y el argumento clave_id pasado por el proceso es menor que el pasado por el proceso , entonces el identicador de en el grupo nuevo_com ser menor que el identicador del proceso . Si llaman a la funcin con el mismo valor en clave_id el sistema asignar arbitrariamente a uno de los procesos un identicador menor.
g m
Proporciona mayor seguridad. Permite que las implementaciones eviten comunicaciones relativas a la creacin del contexto.
7.5. TOPOLOGAS
111
MPI_Comm_split() es una operacin colectiva y debe ser llamada por todos los procesos pertenecientes a antiguo_com. La funcin puede ser utilizada incluso si no deseamos asignarle un comunicador a todos los procesos. sto puede ser realizado pasando la constante predenida MPI_UNDEFINED en el argumento clave_particion. Los procesos que hagan sto obtendrn como valor de retorno en nuevo_com el valor MPI_COMM_NULL.
7.5. Topologas
Recordemos que es posible asociar informacin adicional (ms all del grupo y del contexto) a un comunicador. Una de las piezas de informacin ms importantes que se pueden adjuntar al comunicador es la topologa. En MPI una topologa no es ms que un mecanismo para asociar diferentes esquemas de direccionamiento a los procesos pertenecientes a un grupo. Notar que las topologas en MPI son topologas virtuales, lo que quiere decir que podra no haber una relacin simple entre la estructura de procesos de una topologa virtual y la estructura fsica real de la mquina paralela. Esencialmente existen dos tipos de topologas virtuales que se pueden crear en MPI: la topologa cartesiana o rejilla, y la topologa grca. Conceptualmente sta ltima engloba a la primera. De todos modos, y debido a la importancia de las rejillas en las aplicaciones, existe una coleccin separada de funciones en MPI cuyo propsito es la manipulacin de rejillas virtuales. En el algoritmo de Fox queremos identicar los procesos en MPI_COMM_WORLD mediante las coordenadas de una rejilla, y cada la y cada columna de la rejilla necesita formar su propio comunicador. Observemos un mtodo para construir dicha estructura. Comenzamos asociando una estructura de rejilla a MPI_COMM_WORLD. Para hacer esto necesitamos especicar la siguiente informacin: 1. 2. 3. El nmero de dimensiones de la rejilla. Tenemos 2. El tamao de cada dimensin. En nuestro caso, no es ms que el nmero de las y el nmero de columnas. Tenemos las y columnas. La periodicidad de cada dimensin. En nuestro caso esta informacin especica si la primera entrada de cada la o columna es adyacente a la ltima entrada de dicha la o columna, respectivamente. Dado que nosotros queremos un paso circular de las matrices en cada columna, sera provechoso que la segunda dimensin fuera peridica. No es importante si la primera dimensin es peridica o no. Finalmente MPI ofrece al usuario la posibilidad de permitir al sistema optimizar el direccionamiento de la rejilla, posiblemente reordenando los procesos pertenecientes al comunicador asociado, para as aprovechar mejor la estructura fsica de dichos procesos. Dado que no necesitamos preservar el orden de los procesos en MPI_COMM_WORLD, deberamos permitir al sistema el reordenamiento.
4.
Para implementar estas decisiones simplemente ejecutaremos el siguiente cdigo: MPI_Comm com_rejilla;
112
Tras ejecutar este cdigo el comunicador com_rejilla contendr los procesos pertenecientes a MPI_COMM_WORLD (posiblemente reordenados) y tendr asociado un sistema de coordenadas cartesianas de dos dimensiones. Para determinar las coordenadas de un proceso simplemente llamaremos a la funcin MPI_Cart_coords(): int coordenadas[2]; int id_rejilla; MPI_Comm_rank(com_rejilla, &id_rejilla); MPI_Cart_coords(com_rejilla, id_rejilla, 2, coordenadas); Observemos que necesitamos llamar a MPI_Comm_rank() para obtener el identicador del proceso en com_rejilla. Esto es necesario porque en nuestra llamada a MPI_Cart_create() establecimos la variable reordenamiento a 1, y por lo tanto el identicador original de un proceso en MPI_COMM_WORLD puede cambiar en com_rejilla. La inversa a MPI_Cart_coords() es MPI_Cart_rank():
int MPI_Cart_rank(com_rejilla, coordenadas, &id_rejilla) Dadas las coordenadas de un proceso, MPI_Cart_rank() retorna el identicador del proceso en su tercer parmetro id_proceso. La sintaxis de MPI_Cart_create() es: int MPI_Cart_create(MPI_Comm antiguo_com, int numero_dimensiones, int* tam_dimensiones, int* periodicidades, int reordenamiento, MPI_Comm* com_cartesiano) MPI_Cart_create() crea un nuevo comunicador, com_cartesiano, aplicando una topologa cartesiana a antiguo_com. La informacin sobre la estructura de la topologa cartesiana est contenida en los parmetros numero_dimensiones, tam_dimensiones y periodicidades. El primero de ellos, numero_dimensiones, contiene el nmero de dimensiones que forman el sistema de coordenadas cartesianas. Los dos siguientes, tam_dimensiones y periodicidades, son
113
Cuadro 7.2: Topologa Fsica 3*3 vectores que tienen el mismo orden que numero_dimensiones. El vector tam_dimensiones especica el orden de cada dimensin, mientras que el vector periodicidades especica para cada dimensin si es circular o linear. Los procesos pertenecientes a com_cartesiano son ordenados de la en la. De este modo _ , la segunda la conla primera la contiene los procesos tendr _ _ _ , y as sucesivamente. En este sentido podra ser ventajoso cambiar el orden relativo de los procesos en com_antiguo. Por ejemplo, supongamos que la topologa fsica es una tabla y que los procesos pertenecientes com_antiguo, representados por sus identicadores, estn asociados a los procesadores como se expone en el cuadro 7.2. Claramente la eciencia del algoritmo de Fox se mejorara si reordenramos los procesos. Sin embargo, y dado que el usuario no conoce cmo se asocian los procesos a los procesadores, deberamos dejar al sistema hacerlo estableciendo el parmetro reordenamiento a 1. Dado que MPI_Cart_create() construye un nuevo comunicador, se trata de una operacin colectiva. La sintaxis de las funciones que nos informan sobre el direccionamiento de los procesos es:
int MPI_Cart_rank(MPI_Comm cart_com, int* coordenadas, int* id) int MPI_Cart_coords(MPI_Comm cart_com, int id, int numero_dimensiones, int* coordenadas) La funcin MPI_Cart_rank() retorna el identicador en cart_com del proceso que tiene las coordenadas cartesianas representadas en el vector coordenadas. As, coordenadas es un vector de orden igual al nmero de dimensiones de la topologa cartesiana asociada a cart_com. MPI_Cart_coords() es la inversa a MPI_Cart_rank(): retorna las coordenadas del proceso que tiene como identicador id en el comunicador cartesiano cart_com. Notar que ambas funciones son locales.
IGRd h d B @iqqqi d { 21 7{ 7 98fffAI d h i q q21 q AI i7 'z $d h { 21 7{ 7 'z u id u I G d d h 'u z { 21 { i7 'u z 8{fff7{ Xph i i B
La llamada a MPI_Cart_sub() crea nuevos comunicadores. El argumento var_coords es un vector de booleanos. Especica para cada dimensin si pertenece al nuevo comunicador. Dado que estamos creando comunicadores para las las de la rejilla, cada nuevo comunicador consiste en los procesos obtenidos al jar la coordenada de la la, permitiendo que la coordenada de la columna vare. Con este propsito le asignamos a var_coords[0] el valor 0 (la primera coordenada no vara) y le asignamos a var_coords[1] el valor 1 (la segunda coordenada vara). En cada proceso retornamos el nuevo comunicador en com_la. Si queremos crear comunicadores para las columnas, simplemente invertimos los valores en los elementos de var_coords. MPI_Com com_columna; var_coords[0]=1; var_coords[1]=0; MPI_Cart_sub(cart_com,var_coords,&com_columna); Notar la similaridad entre MPI_Cart_sub() y MPI_Comm_split(). Ambas llevan a cabo funciones similares (las dos dividen un comunicador en una coleccin de nuevos comunicadores). Sin embargo MPI_Cart_sub() slo puede ser usada en comunicadores que tengan asociada una topologa cartesiana, y el nuevo comunicador slo puede ser creado jando (o variando) una o ms dimensiones del antiguo comunicador. Notar tambin que MPI_Cart_sub() es, como MPI_Comm_split(), una operacin colectiva.
115
/*TAMAO MAXIMO DE LA MATRIZ DE CADA PROCESO*/ # define MAX_ORDEN_LOCAL 700 # # # # include < s t d i o . h> include < s t d l i b . h> include < math . h> include " mpi . h "
/*ESTRUCTURA QUE CONTIENE PARA CADA PROCESO LA INFORMACION RELEVANTE A LA TOPOLOGIA CARTESIANA QUE COMPONEMOS*/ typedef s t r u c t { i n t numprocs ; /*NUM DE PROCESOS PERTENECIENTES*/ i n t orden_cart ; /*sqrt(p)--->ORDEN DE LA TOPOLOGIA*/ MPI_Comm comm_global ; /*COMM GLOBAL DE LA TOPOLOGIA COMPLETA*/ MPI_Comm comm_fila ; /*COMM FORMADO POR LOS PROCS DE LA FILA*/ MPI_Comm comm_columna ; /*COMM FORMADO POR LOS PROCS DE LA COLUMNA*/ int f i l a ; /*NUMERO DE FILA*/ i n t columna ; /*NUMERO DE COLUMNA*/ int id ; /*IDENTIFICADOR DENTRO DE LA TOPOLOGIA CREADA*/ } Info_cart ; /*TIPO MATRIZ DE CADA PROCESO*/ typedef i n t M a t r i z L o c a l [MAX_ORDEN_LOCAL] [ MAX_ORDEN_LOCAL] ; /*TIPO DE DATOS MPI UTILIZADO PARA EL ENVIO DE MATRICES ENTRE LOS PROCESOS*/ MPI_Datatype T i p o _ e n v i o _ m a t r i z ; /*DECLARACION DE LAS FUNCIONES UTILIZADAS*/ int Config_cart ( Info_cart pcart ) ; void o b t e n e r _dat os ( i n t minimo , i n t maximo , i n t o r d e n _ g l o b a l ) ; void d i s t r i b u i r _ d a t o s ( i n t tamano_local ) ; void i n i c i a l i z a c i o n _ m a t r i c e s ( M a t r i z L o c a l l o c a l A , MatrizLocal localB , MatrizLocal localC , int orden_local , int id ) ; void Fox ( I n f o _ c a r t p c a r t , MatrizLocal matriz1 , MatrizLocal matriz2 , MatrizLocal r e s u l t , int orden_local ) ; i n t i m p r e s i o n _ m a t r i c e s ( i n t i d , i n t numprocs , MatrizLocal matriz1 , MatrizLocal matriz2 , MatrizLocal r e s u l t , i n t tamano , int f i l a , i n t columna ) ; void m u l t _ m a t r i c e s ( M a t r i z L o c a l m a t r i z 1 , MatrizLocal matriz2 , MatrizLocal r e s u l t , int orden_local ) ; void i m p _ m a t r i z ( M a t r i z L o c a l m a t r i z , i n t o r d e n _ l o c a l , FILE s a l i d a ) ;
v v
116
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
/*********************************************************************/ /*FUNCION MAIN: NORMALMENTE UTILIZAMOS COMUNICADOR MPI_COMM_WORLD EN */ /*LAS COMUNICACIONES.EMPLEAMOS COMUNICADOR TOPOLOGIA CARTESIANA SOLO */ /*PARA LA MULTIPLICACION DE LAS MATRICES */ /*********************************************************************/ i n t main ( i n t argc , char argv ) { Info_cart top_cart ; /*ESTRUCTURA CON INFO SOBRE LA TOP.CARTESIANA*/ MatrizLocal localA ; /*MATRIZ LOCAL*/ MatrizLocal localB ; /*MATRIZ LOCAL*/ MatrizLocal localC ; /*MATRIZ LOCAL (SOLUCION)*/ int orden_local ; /*ORDEN MATRIZ LOCAL DE CADA PROCESO*/ i n t orden_global ; /*ORDEN MATRIZ GLOBAL*/ i n t minimo ; /*MINIMO ORDEN GLOBAL*/ i n t maximo ; /*MAXIMO ORDEN GLOBAL*/ i n t id_comm_world ; /*ID PROCESO EN MPI_COMM_WORLD*/ i n t numprocs_comm_world ; /*NUMERO PROCESOS EN MPI_COMM_WORLD*/ i n t raiz_numprocs ; /*RAIZ DE NUMERO PROCESOS*/ char nombreproc [MPI_MAX_PROCESSOR_NAME] ; /*NOMBRE PROCESADOR*/ i n t lnombreproc ; /*LONGITUD NOMBRE PROCESADOR*/ double t m p i n i c = 0 . 0 ; /*TIEMPO INICIO DE LA EJECUCION*/ double t m p f i n ; /*TIEMPO FINAL DE LA EJECUCION */ int etiqueta =50; /*ETIQUETA MENSAJES DE PRUEBA*/ MPI_Status s t a t u s ; /*STATUS MENSAJES DE PRUEBA*/ int origen ; /*ORIGEN MENSAJES DE PRUEBA*/
/*INICIALIZAMOS EL ENTORNO DE EJECUCION MPI*/ M P I _ I n i t (& argc ,& argv ) ; /*ALMACENAMOS EL IDENTIFICADOR DEL PROCESO EN MPI_COMM_WORLD*/ MPI_Comm_rank (MPI_COMM_WORLD,& id_comm_world ) ; /*ALMACENAMOS EL NUMERO DE PROCESOS*/ MPI_Comm_size (MPI_COMM_WORLD,& numprocs_comm_world ) ; /*FINALIZAMOS SI NUMERO DE PROCESOS NO TIENE RAIZ ENTERA*/ raiz_numprocs= s q r t ( numprocs_comm_world ) ; i f ( pow ( raiz_numprocs , 2 ) ! = numprocs_comm_world ) { i f ( id_comm_world = = 0 ) { f p r i n t f ( s t d o u t , " \ n E r r o r . Numero de p r o c e s o s u t i l i z a d o " ) ; f p r i n t f ( stdout , " debe t e n e r r a i z e n t e r a \ n \ n " ) ; } MPI_Finalize ( ) ; return 0 ; } /*E/S:NOMBRE DEL PROCESADOR,PROCESADOR 0*/ MPI_Get_processor_name ( nombreproc,& lnombreproc ) ; i f ( id_comm_world = = 0 ) { f p r i n t f ( s t d o u t , " \ n P r o c e s o %d (MPI_COMM_WORLD) en %s " , id_comm_world , nombreproc ) ; f p r i n t f ( s t d o u t , " E n c a r g a d o de l a E / S \ n " ) ; }
v Vv
v v v
117
/*E/S:NOMBRE DEL PROCESADOR,TODOS LOS PROCESOS (PRUEBAS)*/ /*if(id_comm_world==0){ * for (origen=1;origen<numprocs_comm_world;origen++){ * MPI_Recv(nombreproc,MPI_MAX_PROCESSOR_NAME,MPI_CHAR,origen, * etiqueta,MPI_COMM_WORLD,&status); * fprintf(stdout,"PROC %d (MPI_COMM_WORLD) en %s\n", * origen,nombreproc); * } *} *else{ * MPI_Send(nombreproc,MPI_MAX_PROCESSOR_NAME,MPI_CHAR,0, * etiqueta,MPI_COMM_WORLD); *} * */ /*RESERVAMOS ESPACIO PARA MATRICES LOCALES*/ l o c a l A =( M a t r i z L o c a l ) m a l l o c ( s i z e o f ( M a t r i z L o c a l ) ) ; l o c a l B =( M a t r i z L o c a l ) m a l l o c ( s i z e o f ( M a t r i z L o c a l ) ) ; l o c a l C =( M a t r i z L o c a l ) m a l l o c ( s i z e o f ( M a t r i z L o c a l ) ) ; /*OBTENEMOS DATOS INTRODUCIDOS POR EL USUARIO*/ i f ( id_comm_world = = 0 ) { minimo=raiz_numprocs ; /*MINIMO ORDEN GLOBAL*/ maximo=raiz_numprocs MAX_ORDEN_LOCAL; /*MAXIMO ORDEN GLOBAL*/ o b t e n e r _dato s ( minimo , maximo,& o r d e n _ g l o b a l ) ; /*OBTENEMOS DATOS DEL USUARIO*/ o r d e n _ l o c a l= o r d e n _ g l o b a l / raiz_numprocs ; /*CALCULAMOS ORDEN MATRIZ LOCAL*/ o r d e n _ g l o b a l= o r d e n _ l o c a l raiz_numprocs ; /*TRUNCAMOS ORDEN MATRIZ GLOBAL*/ } /*TIEMPO INICIAL DE PROCESAMIENTO*/ i f ( id_comm_world = = 0 ) { f p r i n t f ( s t d o u t , " \ n U t i l i z a n d o %d m a t r i c e s de o r d e n %d c a d a una . \ n " , numprocs_comm_world , o r d e n _ l o c a l ) ; f p r i n t f ( s t d o u t , " Orden M a t r i z G l o b a l : %d \ n " , o r d e n _ g l o b a l ) ; f p r i n t f ( stdout , " Procesando . . . \ n \ n" ) ; } t m p i n i c=MPI_Wtime ( ) ; /*DISTRIBUIMOS DATOS INTRODUCIDOS POR EL USUARIO*/ d i s t r i b u i r _ d a t o s (& o r d e n _ l o c a l ) ; /*INICIALIZACION MATRICES*/ i n i c i a l i z a c i o n _ m a t r i c e s ( l o c a l A , l o c a l B , l o c a l C , o r d e n _ l o c a l , id_comm_world ) ;
/*----------------[UTILIZACION TOPOLOGIA CARTESIANA]------------------*/ /*DEFINICION TIPO DE DATOS MPI UTILIZADO PARA EL ENVIO DE MATRICES*/ MPI_Type_vector ( o r d e n _ l o c a l , o r d e n _ l o c a l ,MAX_ORDEN_LOCAL, MPI_INT , &T i p o _ e n v i o _ m a t r i z ) ; MPI_Type_commit (& T i p o _ e n v i o _ m a t r i z ) ; /*CREACION Y CONFIGURACION DE LA TOPOLOGIA CARTESIANA SI LA SALIDA DE Config_cart ES ERRONEA,FINALIZAMOS EL PROCESO*/
v v v
118
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
/*IMPRIMIMOS RESULTADO.UTILIZAMOS FILA Y COLUMNA DE LA TOP.CARTESIANA*/ i m p r e s i o n _ m a t r i c e s ( id_comm_world , numprocs_comm_world , localA , localB , localC , orden_local , t o p _ c a r t . f i l a , t o p _ c a r t . columna ) ; /*IMPRIMIMOS TIEMPO FINAL DE PROCESAMIENTO*/ t m p f i n =MPI_Wtime ( ) ; i f ( id_comm_world = = 0 ) { f p r i n t f ( s t d o u t , " \ nNumero P r o c e s o s : %d \ n " , numprocs_comm_world ) ; f p r i n t f ( s t d o u t , " Tiempo P r o c e s a m i e n t o : % f \ n \ n " , t m p f i n t m p i n i c ) ; } /*FINALIZAMOS EL ENTORNO DE EJECUCION MPI*/ MPI_Finalize ( ) ; return 0 ; } /*main*/
/*************************************************************/ /*FUNCION obtener_datos: PROCESO 0 EN MPI_COMM_WORLD OBTIENE */ /*LOS DATOS DE ENTRADA */ /*************************************************************/ void o b t e n e r _dat os ( i n t minimo , i n t maximo , i n t o r d e n _ g l o b a l ) { i n t ok = 0 ; /*SEMAFORO PETICION DATOS*/
/*E/S:PETICION DE DATOS*/ while ( ok = = 0 ) { f p r i n t f ( s t d o u t , " I n t r o d u z c a o r d e n de l a m a t r i z g l o b a l a c a l c u l a r " ) ; f p r i n t f ( s t d o u t , " ( minimo= %d , maximo= %d ) \ n " , minimo , maximo ) ; scanf ( " % " , orden_global ) ; d i f ( minimo <=( o r d e n _ g l o b a l ) & & ( o r d e n _ g l o b a l )<=maximo ) { ok = 1 ; } else { f p r i n t f ( s t d o u t , " Orden e r r o n e o . \ n " ) ; } }
119
/*********************************************************************/ /*FUNCION distribuir_datos: UTILIZAMOS EL COMUNICACOR MPI_COMM_WORLD */ /*PARA DISTRIBUIR EL DATO DE ENTRADA */ /*********************************************************************/ void d i s t r i b u i r _ d a t o s ( i n t o r d e n _ l o c a l ) { MPI_Bcast ( o r d e n _ l o c a l , 1 , MPI_INT , 0 ,MPI_COMM_WORLD ) ; } /***********************************************************/ /*FUNCION inicializacion_matrices:INICIALIZA LAS MATRICES */ /*ALEATORIAMENTE.LA MATRIZ RESULTADO SE DEJA A 0 */ /***********************************************************/ void i n i c i a l i z a c i o n _ m a t r i c e s ( M a t r i z L o c a l l o c a l A , MatrizLocal localB , MatrizLocal localC , int orden_local , int id ){ int i , j ; /*CONTADORES*/
/*UTILIZAMOS COMO SEMILLA EL IDENTIFICADOR DEL PROCESO*/ srand ( i d ) ; f o r ( i =0; i < o r d e n _ l o c a l ; i + + ) { f o r ( j =0; j < o r d e n _ l o c a l ; j + + ) { /*MATRICES LOCALES,ELEMENTOS PSEUDOALEATORIOS*/ l o c a l A [ i ] [ j ] = ( i n t ) ( 1 0 0 . 0 rand ( ) / ( RAND_MAX) ) ; l o c a l B [ i ] [ j ] = ( i n t ) ( 1 0 0 . 0 rand ( ) / ( RAND_MAX) ) ; /*RESULTADO,ELEMENTOS=0*/ localC [ i ] [ j ]=0; } } } /*inicializacion_matrices*/
/************************************************************************/ /*FUNCION Config_cart:CREA Y CONFIGURA UN COMUNICADOR CUYA TOPOLOGIA ES */ /*CARTESIANA. ALMACENA EN LA ESTRUCTURA Info_cart LOS DATOS NECESARIOS */ /************************************************************************/ int Config_cart ( Info_cart pcart ) { int antigua_id ; /*ID DENTRO DEL COMUNICADOR INICIAL MPI_COMM_WORLD*/ i n t dims [ 2 ] ; /*VECTOR QUE CONTIENE LA EXTENSION DE CADA DIMENSION*/ int periods [ 2 ] ; /*VECTOR BOOLEANO.CONTIENE PERIODICIDAD DE CADA DIMENSION*/ i n t coords [ 2 ] ; /*VECTOR QUE CONTIENE LAS COORDENADAS DE CADA PROCESO*/ i n t var_coords [ 2 ] ; /*VECTOR PARA GENERAR COMUNICADORES DE FILA Y COLUMNA*/ /*ALMACENAMOS EL NUM DE PROCESOS PERTENECIENTES A MPI_COMM_WORLD*/ MPI_Comm_size (MPI_COMM_WORLD, & ( p c a r t >numprocs ) ) ; /*IDENTIFICADOR DE CADA PROCESO DENTRO DE MPI_COMM_WORLD*/ MPI_Comm_rank (MPI_COMM_WORLD,& a n t i g u a _ i d ) ; /*ORDEN DE LA TOPOLOGIA CARTESIANA,QUE ES LA RAIZ DEL NUM DE PROCESOS*/ /*SI DICHA RAIZ NO ES ENTERA,DEBEMOS DESHACERNOS DE LOS PROCESOS SOBRANTES*/
v v
120
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
} /*Config_cart*/
/**************************************************************************/ /*FUNCION Fox:MULTIPLICACION DE MATRICES MEDIANTE EL ALGORITMO DE FOX */ /**************************************************************************/ void Fox ( I n f o _ c a r t p c a r t , MatrizLocal matriz1 , MatrizLocal matriz2 , MatrizLocal r e s u l t , int orden_local ) { int i ; int bcast_raiz ; int origen , destino ; int etiqueta =50; MPI_Status s t a t u s ; M a t r i z L o c a l temp1 ;
/*CONTADOR*/ /*PROCESO ORIGEN QUE ENVIA MATRIZ LOCAL 1 HACIA LOS PROCESOS DE LA MISMA FILA*/ /*ORIGEN Y DESTINO DE MATRIZ LOCAL 2 ENTRE LOS PROCESOS DE LA MISMA COLUMNA*/ /*ETIQUETA*/ /*STATUS RECEPCION*/ /*VBLE DONDE ALMACENAMOS LA MATRIZ ENVIADA POR bcast_raiz*/
x x
x x x
121
/*ESTABLECEMOS EL NUMERO DE FILA DE LOS PROCESOS ORIGEN Y DESTINO DE LA MATRIZ LOCAL 2*/ o r i g e n =( p c a r t > f i l a + 1 ) % p c a r t >o r d e n _ c a r t ; d e s t i n o =( p c a r t > f i l a + p c a r t >o r d e n _ c a r t 1 ) % p c a r t >o r d e n _ c a r t ; /*MIENTRAS QUEDEN PROCESOS EN LA FILA...*/ f o r ( i =0; i <( p c a r t >o r d e n _ c a r t ) ; i + + ) { /*SE ELIGE EL PROCESO RAIZ*/ b c a s t _ r a i z =( p c a r t > f i l a + i ) %( p c a r t >o r d e n _ c a r t ) ; /*SI ES EL TURNO DEL PROPIO PROCESO EN EJECUCION ,SE ENVIA MATRIZ LOCAL 1 HACIA LOS PROCESOS DE LA MISMA FILA Y SE MULTIPLICA LOCALMENTE*/ i f ( b c a s t _ r a i z = = p c a r t >columna ) { MPI_Bcast ( m a t r i z 1 , 1 , T i p o _ e n v i o _ m a t r i z , b c a s t _ r a i z , p c a r t >comm_fila ) ; mult_matrices ( matriz1 , matriz2 , r e s u l t , orden_local ) ; } /*SI NO TOCA EL TURNO,SE RECIBE LA MATRIZ Y SE MULTIPLICA LOCALMENTE*/ else { MPI_Bcast ( temp1 , 1 , T i p o _ e n v i o _ m a t r i z , b c a s t _ r a i z , p c a r t >comm_fila ) ; m u l t _ m a t r i c e s ( temp1 , m a t r i z 2 , r e s u l t , o r d e n _ l o c a l ) ; } /*POR ULTIMO SE ENVIA HACIA ARRIBA EN LA COLUMNA LA MATRIZ LOCAL 2*/ MPI_Sendrecv_replace ( m a t r i z 2 , 1 , T i p o _ e n v i o _ m a t r i z , destino , etiqueta , origen , etiqueta , p c a r t >comm_columna,& s t a t u s ) ; } } /*Fox*/
/******************************************************************/ /*FUNCION impresion_matrices:PROCESO 0 RECIBE LAS MATRICES DE LOS */ /*DEMAS PROCESOS ORDENADAMENTE Y LAS IMPRIME */ /******************************************************************/ i n t i m p r e s i o n _ m a t r i c e s ( i n t i d , i n t numprocs , MatrizLocal matrizA , MatrizLocal matrizB , MatrizLocal matrizResult , int orden_local , int f i l a , i n t columna ) { int BufferFila ; /*BUFFER RECEPCION FILA*/ i n t BufferColumna ; /*BUFFER RECEPCION COLUMNA*/ M a t r i z L o c a l B u f f e r M a t r i z ; /*BUFFER RECEPCION MATRIZ*/ int origen ; /*ORIGEN DE LOS DATOS*/ MPI_Request r e q u e s t s [ 5 ] ; /*VECTOR DE PETICIONES*/ MPI_Status s t a t u s [ 5 ] ; /*VECTOR DE STATUS*/ int etiqueta =10; /*ETIQUETA DE LOS MENSAJES*/ FILE s a l i d a ; /*FICHERO SALIDA*/
122
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
i f ( i d ==0){ /*APERTURA FICHERO SALIDA*/ /*UTILIZAR PREFERIBLEMENTE UN FICHERO LOCAL (EN LINUX PODRIAMOS USAR ALGO COMO "/tmp/Result.txt")*/ i f ( ( s a l i d a=fopen ( " / tmp / R e s u l t . t x t " , "w" ) ) = =NULL ) { f p r i n t f ( s t d e r r , " F a l l o de a p e r t u r a f i c h e r o s a l i d a . \ n " ) ; return 1 ; } else { f p r i n t f ( s t d o u t , " E s c r i b i e n d o r e s u l t a d o en f i c h e r o de s a l i d a . \ n " ) ; } /*IMPRESION MATRICES PROPIAS*/ f p r i n t f ( s a l i d a , "PROC % : C o o r d e n a d a s( %d, %d ) . M a t r i z A\ n " , i d , d f i l a , columna ) ; imp_matriz ( matrizA , orden_local , s a l i d a ) ; f p r i n t f ( s a l i d a , "PROC % : C o o r d e n a d a s( %d, %d ) . M a t r i z B \ n " , i d , d f i l a , columna ) ; imp_matriz ( matrizB , orden_local , s a l i d a ) ; f p r i n t f ( s a l i d a , "PROC % : C o o r d e n a d a s( %d, %d ) . M a t r i z R e s u l t a d o \ n " , i d , d f i l a , columna ) ; imp_matriz ( matrizResult , orden_local , s a l i d a ) ; /*IMPRESION OTRAS MATRICES*/ f o r ( o r i g e n =1; o r i g e n<numprocs ; o r i g e n + + ) { /*MATRIZ A*/ MPI_Irecv (& B u f f e r F i l a , 1 , MPI_INT , o r i g e n , e t i q u e t a o r i g e n +1, MPI_COMM_WORLD,& r e q u e s t s [ 0 ] ) ; MPI_Irecv (& BufferColumna , 1 , MPI_INT , o r i g e n , e t i q u e t a o r i g e n +2, MPI_COMM_WORLD,& r e q u e s t s [ 1 ] ) ; MPI_Irecv ( B u f f e r M a t r i z , 1 , T i p o _ e n v i o _ m a t r i z , o r i g e n , e t i q u e t a o r i g e n +3, MPI_COMM_WORLD,& r e q u e s t s [ 2 ] ) ; MPI_Waitall ( 3 , requests , status ) ; f p r i n t f ( s a l i d a , "PROC % : C o o r d e n a d a s( %d, %d ) . M a t r i z A \ n " , o r i g e n , d B u f f e r F i l a , BufferColumna ) ; i m p _ m a t r iz ( B u f f e r M a t r i z , o r d e n _ l o c a l , s a l i d a ) ; /*MATRIZ B*/ MPI_Irecv ( B u f f e r M a t r i z , 1 , T i p o _ e n v i o _ m a t r i z , o r i g e n , e t i q u e t a o r i g e n +4, MPI_COMM_WORLD,& r e q u e s t s [ 0 ] ) ; MPI_Wait(& r e q u e s t s [ 0 ] , & s t a t u s [ 0 ] ) ; f p r i n t f ( s a l i d a , "PROC % : C o o r d e n a d a s( %d, %d ) . M a t r i z B \ n " , o r i g e n , d B u f f e r F i l a , BufferColumna ) ; i m p _ m a t r iz ( B u f f e r M a t r i z , o r d e n _ l o c a l , s a l i d a ) ; /*MATRIZ Result*/ MPI_Irecv ( B u f f e r M a t r i z , 1 , T i p o _ e n v i o _ m a t r i z , o r i g e n , e t i q u e t a o r i g e n +5, MPI_COMM_WORLD,& r e q u e s t s [ 0 ] ) ; MPI_Wait(& r e q u e s t s [ 0 ] , & s t a t u s [ 0 ] ) ; f p r i n t f ( s a l i d a , "PROC % : C o o r d e n a d a s( %d, %d ) . M a t r i z R e s u l t \ n " , o r i g e n , d B u f f e r F i l a , BufferColumna ) ; i m p _ m a t r iz ( B u f f e r M a t r i z , o r d e n _ l o c a l , s a l i d a ) ; } /*CIERRE FICHERO SALIDA*/ fclose ( salida ) ; } else { /*ENVIO DE DATOS*/
v v v
v v v
123
MPI_Isend(& f i l a , 1 , MPI_INT , 0 , e t i q u e t a i d +1, MPI_COMM_WORLD,& r e q u e s t s [ 0 ] ) ; MPI_Isend(& columna , 1 , MPI_INT , 0 , e t i q u e t a i d +2, MPI_COMM_WORLD,& r e q u e s t s [ 1 ] ) ; MPI_Isend ( m a t r i z A , 1 , T i p o _ e n v i o _ m a t r i z , 0 , e t i q u e t a i d +3, MPI_COMM_WORLD,& r e q u e s t s [ 2 ] ) ; MPI_Isend ( m a t r i z B , 1 , T i p o _ e n v i o _ m a t r i z , 0 , e t i q u e t a i d +4, MPI_COMM_WORLD,& r e q u e s t s [ 2 ] ) ; MPI_Isend ( m a t r i z R e s u l t , 1 , T i p o _ e n v i o _ m a t r i z , 0 , e t i q u e t a i d +5, MPI_COMM_WORLD,& r e q u e s t s [ 2 ] ) ; } } /*impresion_matrices*/
/**************************************************************/ /*FUNCION mult_matrices:MULTIPLICACION DE MATRICES LOCALMENTE */ /**************************************************************/ void m u l t _ m a t r i c e s ( M a t r i z L o c a l m a t r i z 1 , MatrizLocal matriz2 , MatrizLocal r e s u l t , int orden_local ) { int i , j , k ; /*CONTADORES*/
f o r ( i =0; i < o r d e n _ l o c a l ; i + + ) { f o r ( j =0; j < o r d e n _ l o c a l ; j + + ) { /*CALCULAMOS EL ELEMENTO i,j DE LA MATRIZ result*/ f o r ( k =0; k< o r d e n _ l o c a l ; k + + ) { ( r e s u l t ) [ i ] [ j ] + = ( matriz1 ) [ i ] [ k ] ( matriz2 ) [ k ] [ j ] ; } } } } /*Mult_Matrices*/
int i , j ;
/*CONTADORES*/
f o r ( i =0; i < o r d e n _ l o c a l ; i + + ) { f o r ( j =0; j < o r d e n _ l o c a l ; j ++) f p r i n t f ( salida , " % " , matriz [ i ] [ j ] ) ; d f p r i n t f ( salida , " \ n" ) ; } }
salida ){
v v
124
Parte III
125
Captulo 8
Normalmente la medicin del rendimiento se realiza a travs de herramientas especializadas en el anlisis, de modo que podemos saber fcilmente y con seguridad cunto de apropiado es el sistema para la ejecucin de determinados algoritmos paralelos.
Los desarrolladores de aplicaciones necesitan conocer el rendimiento de las implementaciones MPI sobre el sistema que van a emplear. De esta manera podrn elegir de manera acertada el tipo de operaciones a implementar en sus algoritmos y, si hay varias disponibles, la implementacin MPI a utilizar. Los evaluadores encuentran la informacin sobre el rendimiento crtica a la hora de decidir qu mquina adquirir para ejecutar sus aplicaciones y, si hay varias disponibles, qu implementacin MPI utilizar. Los implementadores necesitan entender el comportamiento de sus propias implementaciones MPI para poder plantear modicaciones y medir los efectos de dichas modicaciones.
128
cualquier implementacin MPI. Las versiones ms actuales incluyen junto a mpptest una serie de programas (stress y goptest entre otros) que estn adaptados especcamente a cierto tipo de mediciones del rendimiento del sistema.
129
Tambin podemos utilizar la opcin -fname. Con la siguiente orden guardaremos en el chero nombre.mpl los comandos que sern ledos por gnuplot, agregando los datos del test al chero nombre.gpl: $ mpirun -np 2 mpptest -gnuplot -fname nombre.mpl
8.1.3. Visualizacin
En la visualizacin del contenido de los tests utilizaremos el programa gnuplot. Lo primero que debemos hacer, como se explica en el apartado anterior, es generar el chero de comandos .mpl y el chero de datos .gpl asociado. Una vez hecho sto, para ejecutar los comandos del chero out.mpl (analizando as los datos almacenados en el chero .gpl asociado) utilizaremos: $ gnuplot out.mpl o bien escribiremos el comando > load out.mpl dentro del programa gnuplot.
8.1.4. Grcos
Para generar grcos en formato Encapsulated Postscript tenemos dos opciones. La primera es utilizar la opcin -gnuploteps en vez de -gnuplot para generar el chero de comandos .mpl. La siguiente secuencia de rdenes genera el grco out.eps en monocromo: $ mpirun -np 2 mpptest -gnuploteps -fname out.mpl $ gnuplot out.mpl > out.eps Otra posibilidad sera generar el chero de comandos .mpl con la opcin -gnuplot (como hacamos antes): $ mpirun -np 2 mpptest -gnuplot -fname out.mpl Para luego escribir una serie de comandos dentro del programa gnuplot. De esta manera podremos elegir de una manera ms precisa el formato del grco de salida. Con la siguiente serie de comandos conseguiremos obtener el grco en color: > set term postscript eps color > set output out.eps > load out.mpl
130
8.1.5. Operaciones
Mpptest proporciona una amplia variedad de tests. Los distintos tipos de tests son seleccionados normalmente a travs de los argumentos asociados a la ejecucin del programa en la lnea de comandos, aunque tambin puede ser necesario el empleo de otros programas para ejecutarlos. La siguiente lista resume las opciones disponibles ms interesantes: Comunicacin No Bloqueante. La comunicacin no bloqueante es importante; en muchas aplicaciones usar funciones de comunicacin no bloqueante es la manera ms fcil de asegurar la abilidad evitando problemas relacionados con la capacidad nita del buffer. El rendimiento de las funciones no bloqueantes puede ser diferente al de las funciones bloqueantes. Para utilizar este tipo de comunicacin emplearemos la opcin -async. Nmero de Procesos. Cualquier nmero de procesos puede ser empleado. Por defecto slo dos de los procesos se comunican. Utilizando la opcin -bisect todos los procesos participan en la comunicacin. Solapamiento entre comunicacin y procesamiento. La opcin -overlap realiza un simple test que mide el solapamiento entre comunicacin y procesamiento del sistema enviando mensajes con una longitud determinada y generando una carga variable de procesamiento. Patrones de Comunicacin. Existen una gran variedad de patrones de comunicacin. De este modo, no slo existe el modelo punto a punto; un modelo muy importante es el de comunicacin colectiva, entre otros. La comunicacin colectiva se mide con el programa goptest. Dicho programa utiliza muchas opciones similares a mpptest, y se maneja de manera muy similar. Para conocer su funcionamiento ejecutaremos : $ goptest -help Como ocurre con mpptest, tambin existe un script que facilita el manejo del programa goptest. Dicho script se denomina rungoptest. Podemos conocer sus opciones ejecutando: $ rungoptest -help Fiabilidad. La abilidad se comprueba mediante el programa stress. Este programa enva conjuntos de bits en mensajes de varios tamaos, y luego chequea cada bit del mensaje recibido en el proceso receptor. Para conocer sus opciones ejecutaremos: $ stress -help
131
Informtica de Gestin de la Universidad de Cdiz. Dicho sistema se encuentra en el Aula de Informtica II de la Escuela Superior de Ingeniera. Las mquinas en las cuales ejecutaremos los algoritmos tienen las siguientes caractersticas:
Todas las mquinas estn conectadas a una red Ethernet (mediante una tarjeta Davicom Ethernet 100/10 Mbit) y comparten el sistema de cheros /home mediante NFS (Network File System, Sistema de Ficheros en Red). El servidor de cheros es un computador Compaq DEC 3000/800S Alpha, con el sistema operativo Tru64 UNIX (Digital UNIX) V4.0E . La implementacin MPI utilizada es MPICH Versin 1.2.4 . A continuacin analizaremos el rendimiento y la abilidad de nuestro sistema al ejecutar distintos tipos de comunicacin.
set terminal postscript eps color set xlabel "Tamano (bytes)" set ylabel "Tiempo (micro-seg)" set title "Comunicacion Bloqueante" plot [] [:1200] ComBloq.gpl using 4:5 title "Com.Bloqueante" \ with lines lt 1 lw 3 exit
Procesador AMD Duron a 1,2 Ghz 256 Mb RAM Distribucin SUSE Linux 8.0
132
1000
600
400
200
Figura 8.1: Grco Comunicacin Bloqueante $ gnuplot ComBloq.mpl > ComBloq.eps El grco que obtenemos como resultado lo tenemos en la gura 8.1. El eje mide el tamao de los mensajes, mientras que el eje mide el tiempo necesario para transmitirlos. La lnea roja representa el rendimiento de la comunicacin bloqueante.
A NLISIS
DE LOS
R ESULTADOS
Como caba esperar a medida que aumenta el tamao del mensaje tambin lo hace el tiempo requerido para transmitirlo. Debemos observar que el retardo mnimo en la comunicacin bloqueante es de 200 , tiempo requerido para transmitir un mensaje sin contenido (0 bytes).
eca (db`
133
La opcin -async provoca la utilizacin de mensajes no bloqueantes en la comunicacin. Con esta orden el chero ComNoBloq.gpl almacenar los datos para el grco, mientras que ComNoBloq.mpl contendr los comandos gnuplot para visualizarlos. Modicaremos ste ltimo para comparar el rendimiento de la comunicacin bloqueante y el de la no bloqueante, relacionndolos en el mismo grco:
set terminal postscript eps color set xlabel "Tamano (bytes)" set ylabel "Tiempo (micro-seg)" set title "Comparacion Comunicacion Bloqueante-No Bloqueante" plot [] [:1200] ComNoBloq.gpl using 4:5 title "Com.No Bloqueante" \ with lines lt 1 lw 3, \ ComBloq.gpl using 4:5 title "Com.Bloqueante" \ with lines lt 3 lw 3 exit
A continuacin daremos la siguiente orden para generar el grco ComBloq.eps: $ gnuplot ComNoBloq.mpl > ComNoBloq.eps El grco que obtenemos como resultado lo tenemos en la gura 8.2. El eje mide el tamao de los mensajes, mientras que el eje mide el tiempo necesario para transmitirlo. La lnea roja representa el rendimiento de la comunicacin no bloqueante y la azul el rendimiento de la comunicacin bloqueante. A NLISIS
DE LOS
R ESULTADOS
En el grco observamos que los resultados son muy parecidos a los del test anterior. La pequea sobrecarga que genera el proceso de sincronizacin en este tipo de mensajes no afecta casi nada al rendimiento de la comunicacin.
134
600
400
200
$ mpirun -np 16 mpptest -bisect -gnuplot -fname Bisect.mpl La opcin -bisect provoca la participacin de todos los procesos en la comunicacin. Con esta orden el chero Bisect.gpl almacenar los datos para el grco, mientras que Bisect.mpl contendr los comandos gnuplot para visualizarlos. Modicaremos ste ltimo para comparar el rendimiento de la comunicacin participativa y el de la no participativa, relacionndolos en el mismo grco:
set terminal postscript eps color set xlabel "Tamano (bytes)" set ylabel "Tiempo (micro-seg)" set title "Comparacion Com.Participativa-No Participativa" plot [] [:1600]Bisect.gpl using 4:5 title "Com.Participativa" \ with lines lt 1 lw 3, \ ComBloq.gpl using 4:5 title "Com.No Participativa" \ with lines lt 3 lw 3 exit
A continuacin daremos la siguiente orden para generar el grco ComBloq.eps: $ gnuplot Bisect.mpl > Bisect.eps
135
1200
Tiempo (micro-seg)
1000
800
600
400
200
Figura 8.3: Comparacin Com. Participativa - No Participativa El grco que obtenemos como resultado lo tenemos en la gura 8.3. El eje mide el tamao de los mensajes, mientras que el eje mide el tiempo necesario para transmitirlos. La lnea roja representa el rendimiento de la comunicacin participativa y la azul el rendimiento de la comunicacin no participativa. A NLISIS
DE LOS
R ESULTADOS
En el grco observamos que los resultados son algo distintos a los obtenidos en la comunicacin bloqueante convencional. La sobrecarga en la comunicacin que genera la participacin de todos los procesos queda reejada en un aumento del tiempo requerido para transmitir los mensajes. El retardo en la comunicacin aumenta conforme crece el tamao de la informacin a transmitir.
136
0 bytes (mensajes sin contenido). Para realizarlo daremos la orden: $ mpirun -np 16 mpptest -overlap -gnuplot -fname Overlap.mpl La opcin -overlap realiza un simple test que mide el impacto que produce el solapamiento entre comunicacin y procesamiento en el rendimiento del sistema. Este test se lleva a cabo enviando mensajes no bloqueantes sin contenido a la vez que se genera una carga variable de procesamiento. Con esta orden el chero Overlap.gpl almacenar los datos para el grco, mientras que Overlap.mpl contendr los comandos gnuplot para visualizarlos. Modicaremos ste ltimo para comparar el rendimiento de la comunicacin solapada y el de la no solapada, relacionndolos en el mismo grco:
set terminal postscript eps color set xlabel "Carga de Procesamiento (bytes)" set ylabel "Tiempo (micro-seg)" set title "Impacto Solapamiento Comunicacion-Procesamiento" plot [] [182:194] Overlap.gpl using 4:5 title "Com.Solapada" \ with lines lt 1 lw 3 exit
A continuacin daremos la siguiente orden para generar el grco ComBloq.eps: $ gnuplot Overlap.mpl > Overlap.eps El grco que obtenemos como resultado lo tenemos en la gura 8.4. El eje representa la carga de procesamiento medida en bytes, mientras que el eje mide el tiempo necesario para transmitir un mensaje con dicha carga. La lnea roja representa el rendimiento de la comunicacin solapada. A NLISIS
DE LOS
R ESULTADOS
Como observamos en el grco la presencia de procesamiento no provoca una cada del rendimiento de la comunicacin en nuestro sistema. sto es lgico debido a que contamos con equipos relativamente potentes. De este modo el tiempo requerido para transmitir un mensaje de 0 bytes es prcticamente el mismo independientemente de la carga de trabajo del procesador. Por otro lado observamos muchos picos en la lnea de la comunicacin solapada; ello se debe a que la carga de procesamiento que genera este test es variable, por lo que la incidencia sobre el rendimiento tambin ser variable.
137
192
188
186
184
182 0 200 400 600 800 1000 1200 Carga de Procesamiento (bytes)
Figura 8.4: Comparacin Com. Solapada - No Solapada E JECUCIN En el caso de las operaciones colectivas las mediciones no se deben basar slo en el tamao de los mensajes, ya que no es la nica variable determinante; tambin debemos analizar el nmero de procesos que intervienen en su ejecucin. Goptest es el programa encargado de generar datos para grcos basndose en el nmero de procesos. La dicultad que entraa este tipo de mediciones es que no pueden ser realizadas en un solo paso; ello es debido a que el programa de arranque mpirun slo puede seleccionar un nmero de procesos en la ejecucin cada vez. Por lo tanto debemos realizar una ejecucin del test para cada nmero de procesos que queramos incluir en el test. As pues realizaremos cuatro ejecuciones consecutivas para medir el comportamiento del sistema en una comunicacin colectiva de 2, 4, 8 y 16 procesos. La operacin se comunicacin colectiva que realizaremos ser una operacin de reduccin que sumar los valores de todos los procesos. Dichos valores sern de tipo entero: $ mpirun -np 2 goptest -isum -sizelist 32,256,512,1024 -gnuplot -fname Goptest.mpl $ mpirun -np 4 goptest -isum -sizelist 32,256,512,1024 -gnuplot -fname Goptest.mpl $ mpirun -np 8 goptest -isum -sizelist 32,256,512,1024 -gnuplot -fname Goptest.mpl $ mpirun -np 16 goptest -isum -sizelist 32,256,512,1024
138
Como podemos observar el tipo de operacin colectiva se determina mediante una opcin. La opcin isum indica la realizacin de una operacin de reduccin donde se suman los valores de todos los procesos, siendo dichos valores de tipo entero. La opcin -sizelist indica los tamaos de mensajes a utilizar en las pruebas. En todo caso vemos que la ejecucin de goptest es muy similar a la de mpptest, coincidiendo en la mayora de las opciones disponibles. Lo siguiente ser preparar el chero de datos. Dado que realizamos cuatro ejecuciones, en cada una de ellas agregamos de manera dispersa informacin al chero Goptest.gpl. Tendremos que preparar dicho chero para que pueda ser utilizado por el programa gnuplot. Con esta nalidad debemos agrupar la informacin para que el chero quede sin lneas vacas, dejndolo de la siguiente manera:
#np time (us) for various sizes 2 579.500000 2037.400000 3946.940000 7333.680000 4 1606.820000 5923.540000 11683.560000 22859.700000 8 4418.800000 14938.040000 30276.300000 60126.700000 16 10821.880000 37237.340000 73761.080000 137344.780000
Ahora tenemos el chero Goptest.gpl, que almacena los datos para el grco, y el chero Goptest.mpl, que contiene los comandos gnuplot para visualizarlos. Modicaremos ste ltimo de manera que gnuplot genere un grco Encapsulated Postscript manteniendo un buen aspecto:
set term postscript eps color set xlabel "Num.Procesos" set ylabel "Tiempo (micro-seg)" set title "Comunicacion Colectiva Op.Reduccion-Entero" plot [] [:160000] Goptest.gpl using 1:2 title 32 \ with lines lt 1 lw 3,\ Goptest.gpl using 1:3 title 256 with lines lt 3 lw 3,\ Goptest.gpl using 1:4 title 512 with line lt 4 lw 3,\ Goptest.gpl using 1:5 title 1024 with lines lt 7 lw 3 exit
A continuacin daremos la siguiente orden para generar el grco Goptest.eps: $ gnuplot Goptest.mpl > Goptest.eps El grco que obtenemos como resultado lo tenemos en la gura 8.5. El eje representa el nmero de procesos utilizados, mientras que el eje mide el tiempo necesario realizar la comunicacin colectiva. La lnea roja representa el rendimiento de la comunicacin colectiva utilizando los mensajes de 32 bytes, la azul los de 256 bytes, la morada los de 512 y la negra los de 1024 bytes.
139
140000
120000
Tiempo (micro-seg)
100000
80000
60000
40000
20000
0 0 2 4 6 8 Num.Procesos 10 12 14 16
A NLISIS
DE LOS
R ESULTADOS
En el grco podemos observar la incidencia que tienen sobre el rendimiento de la comunicacin tanto el nmero de procesos que toman parte en ella como el tamao de los mensajes que se transmiten . sto lo vemos claramente analizando dos datos:
Una comunicacin colectiva de 16 procesos utilizando mensajes de 1024 bytes tarda , mientras que utilizando mensajes de 256 bytes (una cuarta parte) el uno 140.000 tiempo total es de 35.000 aproximadamente. En este ejemplo slo observamos una reduccin del 75 %.
Con estos datos vemos que el nmero de procesos es una variable algo ms determinante que el tamao de los mensajes, aunque esta ltima tambin reviste mucha importancia. Por lo dems vemos que el crecimiento de las funciones es similar en todos los tamaos de mensajes, y que este tipo de comunicacin en general consume ms tiempo que la comunicacin punto a punto.
eca (db`
eca f8b`
Una comunicacin colectiva entre 16 procesos utilizando mensajes de 1024 bytes tarda unos 140.000 , mientras que con 4 procesos (una cuarta parte) tarda aproximanda. Observamos una reduccin del 85 %. mente 22.000
140
8.2.6. Fiabilidad
Este test comprueba la abilidad de la comunicacin en el sistema utilizando el programa stress. E JECUCIN El programa stress realiza un test de abilidad sobre un determinado sistema. Este programa enva conjuntos de bits en mensajes de varios tamaos, y luego chequea cada bit del mensaje recibido en el proceso receptor. Podemos utilizar el nmero de procesos que creamos conveniente. Con la siguiente orden realizaremos un test con 4 procesos: $ mpirun -np 4 stress Por defecto el tamao de los mensajes que utiliza est comprendido entre 0 y 1024 bytes, con un salto de 32 bytes entre un tamao y el siguiente. La comunicacin es de tipo bloqueante, aunque sto lo podemos cambiar con la opcin -async. A continuacin exponemos la salida que genera este programa:
Each to All ................................+ ................................+ ................................+ ................................+ ................................+ ................................+ ................................+ ................................+ ................................+ ................................+ ................................+ ................................+ ................................+ stress runs to Tue Jul 1 12:15:19 2003 (1) [0.641943 MB/s aggregate] Stress completed 1 tests 2.108621e+08 bytes sent
La primera lnea , Each to All, indica que cada proceso enviar mensajes a todos los dems. Cada una de las lneas de puntos representa una serie de mensajes que enviamos de un proceso a otro. Al utilizar la opcin -verbose la lnea de puntos es sustituida por una informacin para cada mensaje, que indica su tamao y el patrn utilizado para generar el conjunto de bits que forma dicho mensaje; de esta manera cada lnea de puntos representa lo siguiente:
141
A NLISIS
DE LOS
R ESULTADOS
El hecho de no obtener un mensaje de error quiere decir que el test ha sido satisfactorio y que disponemos de un sistema able para la ejecucin de programas MPI.
142
Captulo 9
Los programas de utilidad incluidos en MPE son bsicamente utilidades para el manejo y tratamiento de cheros de recorrido, y las herramientas grcas se utilizan en su visualizacin. Todo ello se analiza con ms detalle en la siguiente seccin. 143
Librera de generacin de cheros de recorrido de la ejecucin Librera de representacin del trazado de la ejecucin Librera de animacin en tiempo real
144
Generalmente el mtodo ms sencillo y seguro para la utilizacin de las libreras MPE es mediante el enlace del cdigo MPI con las libreras MPE adecuadas. Para ello slo debemos proporcionar un argumento (-mpilog) al comando de compilacin que usemos normalmente (seccin A.5). En realidad sto slo debe hacerse en el momento de enlazar el cdigo. Por ejemplo, para crear una versin del programa RTrap (algoritmo Regla del Trapecio) que genere un chero de recorrido, compilaremos y enlazaremos dando las siguientes rdenes: $ mpicc -c RTrap.c $ mpicc -o RTrap -mpilog RTrap.o Aunque tambin podemos compilar directamente: $ mpicc -o RTrap -mpilog RTrap.c Dado que el formato por defecto de salida es CLOG, el chero de recorrido que obtendremos al ejecutar RTrap se llamar RTrap.clog. Si queremos que el chero tenga otro formato de salida debemos utilizar la variable de entorno MPE_LOG_FORMAT. Dicha variable determina el formato de salida de los cheros de recorrido. Los valores permitidos para MPE_LOG_FORMAT son CLOG, SLOG y ALOG. Cuando la variable MPE_LOG_FORMAT no est establecida se asume CLOG. As pues, para generar el chero de recorrido de RTrap en formato SLOG ejecutaremos lo siguiente: $ $ $ $ MPE_LOG_FORMAT=SLOG export MPE_LOG_FORMAT mpicc -c RTrap.c mpicc -o RTrap -mpilog RTrap.o
De esta manera el chero de recorrido que obtendremos al ejecutar RTrap ser RTrap.slog.
145
Para visualizar el contenido de los cheros de recorrido, lo ms recomendable es ejecutar el programa logviewer. Este script emplea el visualizador adecuado para tratar el chero basndose en su extensin. Dependiendo del formato que tenga el chero, logviewer emplear un visualizador u otro. Si queremos informacin acerca de sus opciones ejecutaremos: $ logviewer -help Si lo que queremos es visualizar un chero de recorrido ejecutaremos: $ logviewer nombrefichero.extension El programa logviewer utiliza los siguientes visualizadores para mostrar el contenido de los cheros de recorrido: upshot Utilizado para visualizar cheros con el formato ALOG. Analiza eventos asociados a etiquetas temporales que representan el momento en que se produjeron, almacenados en formato de texto ASCII. jumpshot-2 Utilizado para visualizar cheros con el formato CLOG. Este visualizador es una evolucin de nupshot, el cual a su vez es una versin ms rpida de upshot. Analiza los cheros en formato binario y est escrito en Java. Su inconveniente radica en el impacto que tiene sobre su rendimiento el tamao del chero a analizar. Cuando el chero CLOG sobrepasa los 4MB su rendimiento se deteriora de manera signicativa. jumpshot-3 Utilizado para visualizar cheros con el formato SLOG. Es la evolucin natural de jumpshot-2 y tambin est escrito en Java. Este visualizador es fruto del esfuerzo de investigacin desarrollado para solucionar los problemas de rendimiento de su antecesor. De este modo visualiza programas de una manera ms escalable. Debido al formato de los cheros que trata, este visualizador no analiza eventos convencionales si no estados (esencialmente eventos con una duracin) en un formato binario especial, diseado para permitir el tratamiento de cheros de recorrido muy grandes (del tamao de varios Gigas). 9.1.1.3. Conversin
Para convertir los cheros de recorrido de un formato a otro, tenemos las siguientes herramientas: clog2slog Conversor de cheros CLOG a SLOG. Es muy til en aquellos casos en los que la generacin directa del chero SLOG no funciona debido mal comportamiento del programa MPI. Adems este conversor nos permite ajustar ciertos parmetros del chero de recorrido, como el segmento del chero a mostrar, etc. Para obtener ms informacin ejecutaremos: $ clog2slog -h clog2alog Coversor de cheros CLOG a ALOG. Se proporciona por motivos de compatibilidad hacia atrs.
146 9.1.1.4.
Para imprimir los cheros de recorrido en modo texto, tenemos los siguientes programas: slog_print Programa que imprime cheros SLOG en modo texto por la salida estndar. Sirve para chequear el contenido del chero de recorrido. Si el chero SLOG es demasiado grande, puede no ser til usar slog_print. Adems cuando el chero SLOG no est completo slog_print no funcionar. Por lo tanto servir como un simple test para saber si el chero SLOG est generado completamente. clog_print Programa que imprime cheros CLOG en modo texto por la salida estndar.
Starting MPI_Init... Starting MPI_Init... [0] Ending MPI_Init [0] Starting MPI_Comm_rank...
147
Proceso 0 en linux.local Encargado de la E/S Hola Mundo! Numero Procesos: 2 Tiempo Procesamiento: 0.000087 [0] [1] [1] [1] [1] [1] [1] [1] [1] [1] [0] Starting MPI_Finalize... Ending MPI_Init Starting MPI_Comm_rank... Ending MPI_Comm_rank Starting MPI_Comm_size... Ending MPI_Comm_size Starting MPI_Get_processor_name... Ending MPI_Get_processor_name Starting MPI_Finalize... Ending MPI_Finalize Ending MPI_Finalize
148
Figura 9.1: Animacin en Tiempo Real Aunque tambin podemos compilar directamente: $ mpicc -o RTrap -L/usr/X11R6/lib -lX11 -lm -mpianim RTrap.c Debido a que dicha librera utiliza operaciones del sistema XWindow, puede que tengamos problemas con los permisos de acceso al servidor X. En ese caso utilizaremos la orden xhost para permitir el acceso al servidor X. Si tiene problemas con la conguracin de seguridad consulte al administrador del sistema. Al ejecutar la siguiente orden: $ mpirun -np 4 RTrap obtendremos una salida como que se muestra en la gura 9.1.
149
9.2.3. Coste
El coste de un algoritmo se obtiene de la multiplicacin de las dos medidas anteriores; de esta manera Coste = Tiempo de ejecucin * Nmero de procesadores sta es la medida ms indicativa del rendimiento de un algoritmo paralelo. De hecho ser la que utilicemos en la evaluacin de nuestros algoritmos. Su precisin radica en que relaciona el nmero de procesadores empleados con el tiempo de ejecucin obtenido; por lo tanto, nos ser til para conocer en qu proporcin aumenta el rendimiento del sistema al incrementar el nmero de procesadores.
150
151
Cuadro 9.1: Evaluacin Clculo de reas Bloqueante El cuadro 9.1 contiene para cada nmero de procesadores empleado el tiempo de ejecucin medido en segundos y el coste obtenido. En el grco de la gura 9.3 exponemos la relacin entre tiempo de ejecucin y nmero de procesadores. La gura 9.4 contiene la curva de crecimiento del coste con respecto al nmero de procesadores. A NLISIS
DE LOS
R ESULTADOS
El modelo de ejecucin de este algoritmo puede ser interpretado fcilmente. En un principio el proceso 0 distribuye los datos de entrada a los dems procesos enviando a cada uno un mensaje bloqueante. Si hubiramos introducido los datos a travs del terminal en vez de haber jado variables en estas pruebas, este paso hubiera sido ms largo debido a que el resto de procesos tendran que esperar a que el proceso 0 terminara de consultar los datos al usuario. Una vez realizado este paso se produce el procesamiento interno en cada uno de los procesos durante el cual no existe comunicacin entre los procesos. Cuando los procesos culminan el tiempo de procesamiento envan su resultado local al proceso 0 mediante un mensaje bloqueante. El proceso 0 recoge dichos resultados locales, calcula la media de todos ellos e imprime el resultado global. Una vez hecho sto el programa termina. Como podamos esperar, cuantos ms procesadores intervienen en la ejecucin menor es el tiempo de ejecucin. Sin embargo el coste aumenta gradualmente con respecto al nmero de procesadores. Por lo tanto deberamos emplear ms o menos procesadores dependiendo de la necesidad que tengamos de acelerar el procesamiento y de los recursos que podamos utilizar, intentando llegar a un compromiso entre rendimiento y coste que sea ptimo para nuestras necesidades.
152
120
80
60
40
20
0 0 2 4 6 8 10 12 14 16 Numero de Procesadores
Coste
154
Cuadro 9.2: Evaluacin Clculo de reas No Bloqueante En la gura 9.5 observamos el modelo de ejecucin del algoritmo regla del trapecio con 8 procesos. El cuadro 9.2 contiene para cada nmero de procesadores empleado el tiempo de ejecucin medido en segundos y el coste obtenido. En el grco de la gura 9.6 exponemos la relacin entre tiempo de ejecucin y nmero de procesadores. La gura 9.7 contiene la curva de crecimiento del coste con respecto al nmero de procesadores. A NLISIS
DE LOS
R ESULTADOS
El modelo de ejecucin de este algoritmo puede ser interpretado fcilmente. En un principio el proceso 0 distribuye los datos de entrada a los dems procesos enviando a cada uno un mensaje no bloqueante. Si hubiramos introducido los datos a travs del terminal en vez de haber jado variables en estas pruebas, este paso hubiera sido ms largo debido a que el resto de procesos tendran que esperar a que el proceso 0 terminara de consultar los datos al usuario. Una vez realizado este paso se produce el procesamiento interno en cada uno de los procesos durante el cual no existe comunicacin entre los procesos. Cuando los procesos culminan el tiempo de procesamiento envan su resultado local al proceso 0 mediante un mensaje no bloqueante. El proceso 0 recoge dichos resultados locales, calcula la media de todos ellos e imprime el resultado global. Una vez hecho sto el programa termina. Podemos observar que la versin no bloqueante de este algoritmo es un poco ms eciente que la versin bloqueante. Los tiempos de ejecucin son algo menores, y por lo tanto el coste tambin. De este modo nos percatamos de la mejora en el rendimiento que proporciona la comunicacin no bloqueante.
155
100
Tiempo (seg)
80
60
40
20
0 0 2 4 6 8 10 12 14 16 Numero de Procesadores
165
160 Coste
155
150
145
140
156
157
El segundo asunto es que necesitamos realizar bajo las mismas condiciones todas las ejecuciones. Los datos de entrada deben ser jados siempre a los mismos valores. De este modo intentaremos buscar el nmero PI a travs de la regla del trapecio. Para este propsito, y como y el intervalo . ya explicamos en la seccin 6.1, utilizaremos la funcin Para computarlo utilizaremos el nmero de segmentos 1.000.000.000 . En la gura 9.8 observamos el modelo de ejecucin del algoritmo regla del trapecio con 8 procesos. El cuadro 9.3 contiene para cada nmero de procesadores empleado el tiempo de ejecucin medido en segundos y el coste obtenido. En el grco de la gura 9.9 exponemos la relacin entre tiempo de ejecucin y nmero de procesadores. La gura 9.10 contiene la curva de crecimiento del coste con respecto al nmero de procesadores.
A NLISIS
DE LOS
R ESULTADOS
El modelo de ejecucin de este algoritmo puede ser interpretado fcilmente. En un principio se produce una operacin broadcast, con la cual distribuimos los datos de entrada desde el proceso 0 hacia los dems procesos. Si hubiramos introducido los datos a travs del terminal en vez de haber jado variables en estas pruebas, este paso hubiera sido ms largo debido a que el resto de procesos tendran que esperar a que el proceso 0 terminara de consultar los datos al usuario. Una vez realizado este paso se produce el procesamiento interno en cada uno de los procesos durante el cual no existe comunicacin entre los procesos. Cuando cada proceso ha culminado su propio procesamiento el proceso 0 recoge los resultados de cada proceso a travs de una operacin reduce. Luego el proceso 0 imprime los resultados y el programa termina. Como podamos esperar, cuantos ms procesadores intervienen en la ejecucin menor es el tiempo de ejecucin. Sin embargo el coste aumenta gradualmente a partir de la utilizacin de 4 procesadores. Por lo tanto deberamos emplear ms o menos procesadores dependiendo de la necesidad que tengamos de acelerar el procesamiento y de los recursos que podamos utilizar, intentando llegar a un compromiso entre rendimiento y coste que sea ptimo para nuestras necesidades.
dIi Xp h
) sr p Rn q o FD Q
158
100
Tiempo (seg)
80
60
40
20
0 0 2 4 6 8 10 12 14 16 Numero de Procesadores
134
132 Coste
130
128
126
124
159 16 19,1 / 23,2 57,3 / 78,9 134,0 / 183,3 261,1 / 344,8 458,5 / 599,9 726,7 / 930,2 1016,4 / 1291,9
C B
T 6
160
Tiempo (seg)
1500
1000
500
0 500
1000
1500
2000
2500
3000
3500
4000
4500
5000
Orden Matriz
1000
1500
2000
2500
3000
3500
4000
4500
5000
Orden Matriz
162 A NLISIS
DE LOS
El modelo de ejecucin de este algoritmo con 9 procesos demuestra la sobrecarga en la comunicacin que genera. Cada uno de los procesos en ejecucin realiza 3 operaciones de bradcast y 6 de paso de mensajes bloqueantes (en realidad la funcin MPI_Sendrecv_replace() realiza un envo y una recepcin por cada llamada). Cada una de los mensajes transmitidos tendr al menos el mismo tamao que las matrices locales de los procesos. Una vez que los procesos culminan el procesamiento de sus matrices locales, envan los resultados al proceso 0 para generar la salida. Como podemos observar en la gura 9.11 el crecimiento del tiempo de ejecucin es exponencial para todas las cantidades de procesos utilizadas; sin embargo dicho crecimiento es ms paulatino cuanto mayor es la cantidad de procesos empleados. En la gura 9.12 observamos que el coste depende tanto del nmero de procesos empleados como del tamao de las matrices a multiplicar. De hecho vemos que para matrices de orden mayor a 2000 la utilizacin de 1 slo procesador es la ms costosa. Con este planteamiento podemos prever que para tamaos de matrices superiores a los empleados en las pruebas la utilizacin de 16 procesadores ser la ms rentable.
Apndice A
Compatibilidad total con MPI-1.2, incluyendo cancelaciones de envos. Soporte para clusters heterogneos. Los enlaces con C++ incluidos en la especicacin MPI-2 estn disponibles para las funciones MPI-1. Enlaces con Fortran 77 y Fortran 90. Una versin de cdigo abierto est disponible para Windows NT. La instalacin, conguracin y manejo de esta versin son diferentes a las explicadas en este apndice, el cual cubre slo la versin Unix de MPICH. Soporte para una amplia variedad de entornos, incluyendo MPPs y clusters de SMPs. Sigue la mayora de las recomendaciones GNU acerca de la instalacin y compilacin, incluyendo VPATH. Compatibilidad con algunas partes de la especicacin MPI-2, de modo que incluye: La mayora de las funcionalidades de E/S paralela (MPI-IO) a travs de la implementacin ROMIO. Algunas funcionalidades de administracin de hilos (MPI_INIT_THREAD). Nuevas funciones MPI_Info() y MPI_Datatype(). 163
164
A.1.
Dispositivos
La portabilidad de MPICH proviene de su diseo en dos capas. La mayor parte del cdigo de MPICH es independiente del hardware y est implementado por encima de una ADI (Abstract Device Interface, Interfaz de Dispositivo Abstracto). La interfaz ADI, llamada tambin dispositivo, oculta la mayora de los detalles especcos del hardware permitiendo que MPICH sea portado fcilmente a nuevas arquitecturas. La interfaz ADI (o dispositivo) se encarga de facilitar el acceso al hardware de una manera eciente, mientras que el resto del cdigo por encima de la ADI se encarga de la sintaxis y la semntica de MPI. A continuacin mostramos una lista con los dispositivos (ADIs) disponibles en MPICH. Clusters, Beowulf y Estaciones de Trabajo Individuales. Los dispositivos ms importantes son ch_p4 y ch_p4mpd. El dispositivo ch_p4 es el ms general y soporta nodos SMP, programas MPMD y sistemas heterogneos. El dispositivo ch_p4mpd (ms rpido) soporta slo clusters homogneos de uniprocesadores, pero proporciona un arranque ms rpido y escalable. Topologas de tipo Rejilla. El dispositivo globus2 utiliza Globus (URL 19) para proporcionar una implementacin diseada para topologas de tipo rejilla. Este dispositivo es apropiado para sistemas en los que est instalado Globus. Multiprocesadores Simtricos. El dispositivo ch_shmem es apropiado para sistemas basados en memoria compartida. Utiliza la memoria compartida para pasar mensajes entre los procesadores, y hace uso de las facilidades proporcionadas por el sistema operativo. El dispositivo ch_lfshmem es una versin de ch_shmem que no utiliza bloqueos, desarrollada para el NEC-SX4. Procesadores Paralelos Masivos (MPPs). MPICH fue desarrollado originalmente para proporcionar una implementacin MPI a la mayora de los MPPs existentes, cada uno de los cuales tiene su propio sistema de paso de mensajes. De este modo se incluyen los dispositivos ch_meiko, ch_nx y ch_mpl en las distribuciones de MPICH. Otros. MPICH ha sido diseado para permitir que otros grupos lo usen cuando desarrollen sus propias implementaciones MPI. Tanto las compaas privadas como los grupos de investigacin han usado MPICH como base para sus implementaciones. Una implementacin importante desarrollada de esta manera es MPICH-GM, la cual se emplea en clusters Myrinet conectados mediante hubs dedicados.
Y Y Y Y
Incluye componentes pertenecientes al entorno de programacin paralela, como son: Herramientas de monitorizacin. Herramientas para la visualizacin de los anlisis del rendimiento (upshot y jumpshot). Amplios tests de abilidad y rendimiento. Ejemplos de aplicaciones tanto simples como complejos.
A.2. OBTENCIN
165
A.2. Obtencin
El primer paso para poder utilizar MPICH ser descargarlo e instalar los parches necesarios: 1. Obtener MPICH. El camino ms fcil para hacerlo es usar la seccin de descargas de su pgina web (URL [10]). De esta manera podremos descargar fcilmente el chero mpich.tar.gz. Dicho chero contiene la distribucin MPICH completa. Descomprimir el chero mpich.tar.gz en un directorio de trabajo. Se recomienda usar una particin montada localmente antes que usar una particin NFS (Network File System, Sistema de Ficheros en Red). La mayora de los sistemas tienen el directorio /tmp o /sandbox montado localmente. Asegrese de que existe espacio suciente disponible (100MB debera ser ms que suciente). Para descomprimir el chero mpich.tar.gz (asumiendo que ha sido descargado en /tmp) usaremos: $ cd /tmp $ gunzip mpich.tar.gz $ tar -xvf mpich.tar 3. Aplicar los parches. Visite la seccin de parches de la pgina web de MPICH (URL [11]) para vericar la existencia de parches que pueda necesitar. Normalmente las versiones disponibles de MPICH tienen ya aplicados dichos parches; sto queda indicado por cuatro nmeros en el nombre de la versin (p.ej. 1.2.2.3). En otros casos el parche aislado se pone a disposicin antes que la versin parcheada. Para aplicar estos parches siga las instrucciones expuestas en la pgina indicada y en la documentacin.
2.
2.
166
$ ./configure -prefix=$HOME/mpich-1.2.4 | tee c.log Este comando hace que MPICH utilice el dispositivo ch_p4 por defecto ; sta es normalmente la eleccin adecuada. La salida de congure es encauzada hacia tee; este programa escribe la salida tanto en el chero especicado en su argumento (aqu c.log) como en la salida estndar . Si tenemos problemas en la conguracin o la compilacin el chero c.log nos servir de ayuda para identicar los posibles problemas. En la seccin A.4.3 se explica cmo utilizar el programa ssh en vez de rsh para el arranque de procesos remotos. 3. Compilar MPICH: $ make | tee make.log sto puede llevar un tiempo dependiendo de la carga de nuestro sistema y de nuestro servidor de cheros; puede durar desde algunos minutos hasta una hora o ms. 4. (Opcional) Si queremos instalar MPICH en un lugar pblico de manera que los dems usuarios puedan usarlo, ejecutaremos: $ make install De este modo instalaremos MPICH en el directorio especicado por el argumento prex del comando congure. La instalacin estar formada por los directorios include, lib, bin, sbin, www y man, adems de un pequeo directorio con ejemplos. Si queremos eliminar la instalacin debemos usar el script sbin/mpiuninstall dentro del directorio de MPICH.
A.4.
Conguracin
A.4. CONFIGURACIN
167
#FICHERO MAQUINAS ARQ. LINUX galba neron oton # vitelio vespasiano tito #FINAL FICHERO MAQUINAS
Los nombres deben ser proporcionados con el mismo formato que la salida del comando hostname. Por ejemplo, si el resultado de hostname en galba fuera galba.aulas y lo mismo sucediera para los dems nombres, el chero de mquinas sera entonces:
#FICHERO MAQUINAS ARQ. LINUX galba.aulas neron.aulas oton.aulas # vitelio.aulas vespasiano.aulas tito.aulas #FINAL FICHERO MAQUINAS
En el caso de que tengamos nodos con mltiples procesadores, debemos indicar su nmero de procesadores tras su nombre y dos puntos. Por ejemplo, si en el ejemplo anterior vitelio tuviera dos procesadores el chero de mquinas sera:
#FICHERO MAQUINAS ARQ. LINUX galba neron oton # vitelio:2 vespasiano tito #FINAL FICHERO MAQUINAS
A.4.2. RSH
El programa rsh (Remote SHell, Shell Remoto) es utilizado para iniciar procesos remotos en general. Si pretendemos usar rsh con el dispositivo ch_p4 necesitaremos congurar
168
nuestra mquina para permitir el uso de rsh. Por motivos de seguridad slo debemos hacer sto si somos un administrador del sistema y entendemos lo que estamos haciedo, o en el caso de que utilicemos una red aislada. Por ejemplo, si estamos utilizando una red Linux en nuestra casa o en el trabajo, y estas mquinas no estn conectadas a una red ms grande, debemos seguir las siguientes instrucciones. Si por el contrario alguna de nuestras mquinas est conectada a otra red, debemos preguntarle a nuestro administrador del sistema acerca de la poltica de utilizacin de rsh. Como alternativa podemos usar ssh. Lo siguiente explica cmo congurar una mquina de manera que pueda usar rsh para iniciar un proceso en ella misma. Para ello debemos asegurarnos de que exista un chero /etc/hosts.equiv que contenga al menos las siguientes lneas: localhost nombre_maquina donde nombre_maquina es el nombre que le damos a nuestra mquina en /etc/hosts. Para este propsito tambin podemos utilizar el chero .rhosts en el directorio de casa si queremos aplicarlo slo a una cuenta de usuario. Por otro lado debemos asegurarnos de que los cheros /etc/hosts.allow y /etc/hosts.deny estn vacos.
A.4.3.
SSH
El mecanismo habitual para el arranque de procesos remotos al utilizar el dispositivo ch_p4 en redes es rsh. El uso de rsh requiere ciertos permisos en las mquinas implicadas. Sin embargo en algunas redes no conviene establecer los permisos de esta manera. La alternativa ms simple a rsh es el uso de ssh (Secure Shell, Shell Seguro). ste puede ser utilizado como mecanismo seguro de procesamiento distribuido. Requiere cierta conguracin que describiremos seguidamente, aunque su utilizacin es muy sencilla. Dicha conguracin depende de la versin de ssh que vayamos a utilizar. Exponemos a continuacin el conjunto de pasos necesarios para que ssh funcione correctamente con MPICH. 1. Debemos asegurarnos de que ssh est instalado en nuestra red y, en caso de estarlo, compruebaremos su versin. Si no est instalado podemos obtenerlo nosotros mismos (URL [12]). Crear nuestra clave de autenticacin. a) Si utilizamos SSH Versin 1 ejecutaremos: $ ssh-keygen sto crear el par clave privada/pblica. La clave privada se almacenar en ~/.ssh/identity y la clave pblica se guardar en ~/.ssh/identity.pub b) Si utilizamos SSH Versin 2 ejecutaremos:
2.
A.4. CONFIGURACIN
$ ssh-keygen -t dsa
169
Si no lo hacemos as, generaremos una clave rsa1 que no podr ser usada con SSH Versin 2. Dicha orden crear el par clave privada/pblica. La clave privada se almacenar en ~/.ssh/id_dsa y la clave pblica se guardar en ~/.ssh/id_dsa.pub 3. Autorizar el acceso. Si estamos utilizando SSH Versin 1 aada su clave pblica al chero /.ssh/authorized_keys. Todas las claves de este chero tendrn permitido el acceso: $ cp ~/.ssh/identity.pub ~/.ssh/authorized_keys Si la mquina a la que queremos conectarnos no comparte el sistema de cheros, entonces debemos copiar el chero ~/.ssh/identity.pub sobre el chero ~/.ssh/authorized_keys de la mquina a la que queremos conectarnos. Debemos asegurarnos de que el chero ~/.ssh/authorized_keys no tenga permiso de escritura por parte de los miembros de nuestro grupo, de manera que tendremos que ejecutar: $ chmod go-rwx ~/.ssh/authorized_keys En caso de utilizar SSH Versin 2 copiaremos el chero id_dsa.pub sobre authorized_keys2 en vez de authorized_keys. Por lo dems todo es igual. Una vez hechos estos cuatro pasos ya podremos utilizar ssh en nuestro sistema. Ahora tendremos que indicar a MPICH que haga uso de dicho programa; sto puede hacerse de dos formas:
Ejecutar congure con la opcin -rsh=ssh para que el dispositivo ch_p4 utilice ssh en vez de rsh. De esta manera tambin los scripts sern modicados para hacer uso de ssh. Si MPICH ya haba sido compilado antes debemos recongurar y recompilar utilizando los siguientes comandos: $ configure -rsh=ssh $ make Si no es as utilizaremos las opciones -prex para indicar el directorio de la instalacin, y -rsh=ssh para elegir ssh como programa de arranque de procesos remotos. Luego compilaremos: $ ./configure -rsh=ssh -prefix=$HOME/mpich-1.2.4 | tee c.log $ make
170
Por lo tanto la manera ms cmoda de utilizarlo es empleando rsh como programa de arranque de procesos remotos. Por otro lado tambin podemos usar ssh para ejecutar el servidor de manera remota, y establecer la conguracin adecuada para poder ejecutar procesos mediante el servidor seguro (aunque ni siquiera est instalado rsh). En este caso debemos tener en cuenta que los scripts generados por MPICH utilizan por defecto rsh para su ejecucin; si queremos que dichos scripts hagan uso de ssh, tendremos que modicarlos o congurar MPICH con la opcin -rsh=ssh.
Establecer la variable de entorno P4_RSHCOMMAND de manera que contenga el nombre del programa a utilizar como arranque de procesos remotos. En nuestro caso ejecutaremos: $ P4_RSHCOMMAND=ssh $ export P4_RSHCOMMAND
Asegrese de que las mquinas listadas en nuestro chero de mquinas estn tambin listadas en el chero /etc/ssh_known_hosts de la red o en el chero ~/.ssh/known_hosts en el directorio de casa. Es importante que el directorio /tmp tenga los permisos establecidos a 03777, con root como dueo y grupo 0. Openssh tiene el argumento -v, el cual es muy til para identicar posibles problemas.
171
Debemos aclarar que tanto el chero serv_p4 como chp4_servs se encuentran en directorios pertenecientes a la instalacin de MPICH, generados por la ejecucin del comando make install (seccin A.3). Antes de arrancar el servidor debemos comprobar si el servidor seguro ha sido inicializado en nuestro sistema para uso general; si es as, el mismo servidor puede ser utilizado por todos los usuarios. Para realizarlo de esta manera necesitamos acceder al sistema como root. Si el servidor seguro no ha sido inicializado, entonces podemos inicializarlo para nuestro uso personal sin necesisdad de privilegios especiales con la orden: $ chp4_servs -port=1234 Esta orden inicializa el servidor seguro en todas las mquinas listadas en el chero de mquinas (seccin A.4.1). El nmero de puerto proporcionado por la opcin -port (por defecto 1234) debe ser diferente del resto de puertos utilizados en las estaciones de trabajo. Para hacer uso del servidor seguro con el dispositivo ch_p4 debemos establecer las siguientes variables de entorno: $ $ $ $ MPI_USEP4SSPORT=yes export MPI_USEP4SSPORT MPI_P4SSPORT=1234 export MPI_P4SSPORT
El valor de MPI_P4SSPORT debe ser el nmero de puerto en el cual inicializamos el servidor seguro. Cuando estas variables de entorno estn establecidas, mpirun intenta utilizar el servidor seguro para arrancar programas que usen el dispositivo ch_p4; si sto no da resultado utilizar el programa de arranque de procesos remotos que tengamos por defecto (normalmente rsh o ssh). Tambin podemos hacer que mpirun utilice el servidor seguro empleando la opcin -p4ssport <num>, que indica el nmero de puerto donde el servidor seguro est instalado.
172
Las rdenes para enlazar cdigo pueden requerir la inclusin de libreras adicionales. Por ejemplo, para utilizar la librera de funciones matemticas de C usaramos la siguiente orden: mpicc -o foo foo.o -lm Tambin podemos combinar la compilacin y el enlace en una sola orden, como exponemos a continuacin: mpicc -o foo foo.c mpif77 -o foo foo.f mpiCC -o foo foo.C mpif90 -o foo foo.f Notar que mientras los sujos .c para los programas en C y .f para los programas en Fortran-77 son estndar, no existe concenso para los sujos de los programas escritos en C++ y Fortran90. Los sujos mostrados en los ejemplos expuestos son aceptados por la mayora de los sistemas, aunque no todos. MPICH intenta determinar los sujos aceptados, pero no es capaz siempre. Podemos modicar la eleccin del compilador a utilizar por MPICH especicando las variables de entorno MPICH_CC, MPICH_F77, MPICH_CCC y MPICH_F90. Sin embargo sto slo funcionar si el compilador alternativo es compatible con el compilador por defecto (esto quiere decir que utilice los mismos tamaos para los tipos de datos y sus composiciones, y que genere un cdigo objeto que sea compatible con el utilizado en las libreras MPICH). Si lo que queremos es modicar el enlazador, utilizaremos las variables de entorno MPICH_CLINKER, MPICH_F77LINKER, MPICH_CCLINKER y MPICH_F90LINKER. Si lo que queremos es ver los comandos que utilizara la orden de compilacin sin ejecutarlos realmente emplearemos el argumento -show. Las siguientes opciones nos ayudan a acceder a las libreras de monitorizacin del entorno MPE: -mpilog Compila una versin que genera el chero de recorrido de la ejecucin. -mpitrace Compila una versin que muestra el trazado de la ejecucin. -mpianim Compila una versin que genera animacin en tiempo real.
A.6.
Para ejecutar programas MPI debemos utilizar el programa mpirun, localizado en el directorio bin/ de MPICH. Bajo la mayora de los sistemas podremos usar la orden mpirun -np 4 a.out
173
para ejecutar el programa a.out en 4 procesadores. La orden mpirun -help nos ofrece una lista completa de las opciones que tiene este programa. Como salida mpirun retorna el status de uno de los procesos, usualmente el proceso con identicador 0 en MPI_COMM_WORLD.
Libreras de monitorizacin utilizadas para generar informacin acerca del rendimiento de los programas MPI, y herramientas para el estudio y visualizacin de dicha informacin. Librera grca para la ejecucin de programas paralelos en X Window. Funciones para la secuencializacin del cdigo ejecutado en paralelo. Funciones para la depuracin de errores.
174
Apndice B
Manual de Referencia
Este apndice describe de manera resumida las funciones MPI utilizadas en los algoritmos implementados. Pretendemos que sea una gua til como manual de consulta. Para mayor comodidad las funciones estn expuestas en orden alfabtico. Para cada una de las funciones denimos su funcionalidad y su sintaxis, especicando cules son los parmetros de entrada y los de salida. Por ltimo, en algunos casos haremos un breve comentario acerca de su funcionamiento.
175
176
B.1. MPI_Bcast
F UNCIONALIDAD Enva un mismo mensaje desde un proceso a todos los dems. Es una operacin de comunicacin colectiva. S INTAXIS int MPI_Bcast(void* mensaje, int contador, MPI_Datatype tipo_datos, int raiz, MPI_Comm com); PARMETROS E NTRADA /S ALIDA mensaje Direccin inicial de memoria del mensaje a enviar/recibir contador Nmero de elementos del tipo tipo_datos que componen el mensaje tipo_datos Tipo de datos MPI de cada elemento del mensaje (Cuadro 5.1) raiz Identicador del proceso que enva el mensaje com Comunicador en el cual se produce la comunicacin C OMENTARIOS Si el soporte hardware se hace responsable de la ejecucin de esta funcin, generalmente se implementa mediante un algoritmo que estructura un modelo de comunicacin en rbol entre los procesos. Para ms informacin, lase la seccin ??.
B.2. MPI_CART_COORDS
177
B.2. MPI_Cart_coords
F UNCIONALIDAD Retorna las coordenadas de un proceso en un comunicador de topologa cartesiana, dado su identicador. S INTAXIS int MPI_Cart_coords(MPI_Comm cart_com, int id, int numero_dimensiones, int* coordenadas) PARMETROS E NTRADA cart_com Comunicador de topologa cartesiana id Identicador del proceso dentro del comunicador cart_com numero_dimensiones Nmero de dimensiones del vector coordenadas PARMETROS S ALIDA coordenadas Vector de enteros (de tamao numero_dimensiones) que contiene las coordenadas cartesianas del proceso
178
B.3. MPI_Cart_create
F UNCIONALIDAD Crea un nuevo comunicador de topologa cartesiana (tipo rejilla). S INTAXIS int MPI_Cart_create(MPI_Comm antiguo_com, int numero_dimensiones, int* tam_dimensiones, int* periodicidades, int reordenamiento, MPI_Comm* com_cartesiano) PARMETROS E NTRADA antiguo_com Comunicador original a partir del cual creamos el nuevo comunicador de topologa cartesiana numero_dimensiones Nmero de dimensiones de la rejilla cartesiana que queremos crear tam_dimensiones Vector de enteros de tamao numero_dimensiones que especica el nmero de procesos en cada dimensin periodicidades Vector de booleanos de tamao numero_dimensiones que especica para cada dimensin si es peridica (verdadero) o no (falso) reordenamiento Booleano que especica si pueden ser reordenados los identicadores de los procesos (verdadero) o no (falso). En muchos casos es apropiado para la optimizacin del sistema, en otros no es signicante. PARMETROS S ALIDA com_cartesiano Nuevo comunicador de topologa cartesiana
B.4. MPI_CART_RANK
179
B.4. MPI_Cart_rank
F UNCIONALIDAD Retorna el identicador de un proceso en un comunicador de topologa cartesiana, dadas sus coordenadas. S INTAXIS int MPI_Cart_rank(MPI_Comm cart_com, int* coordenadas, int* id) PARMETROS E NTRADA cart_com Comunicador de topologa cartesiana coordenadas Vector de enteros (de tamao numero_dimensiones, vase funcin B.3) que especica las coordenadas cartesianas del proceso PARMETROS S ALIDA id Identicador del proceso especicado
180
B.5. MPI_Cart_sub
F UNCIONALIDAD Divide un comunicador de tipo rejilla (topologa cartesiana) en rejillas de menores dimensiones. S INTAXIS int MPI_Cart_sub(MPI_Comm cart_com, int* var_coords, MPI_Comm nuevo_com) PARMETROS E NTRADA cart_com Comunicador de topologa cartesiana var_coords Vector de booleanos que especica para cada dimensin de cart_com si pertenece a nuevo_com, dejando que la coordenada vare (verdadero) o no (falso) PARMETROS S ALIDA nuevo_com Nuevo comunicador de topologa cartesiana con igual o menor nmero de dimensiones que cart_com
B.6. MPI_COMM_CREATE
181
B.6. MPI_Comm_create
F UNCIONALIDAD Crea un nuevo comunicador a partir de otro. S INTAXIS int MPI_Comm_create(MPI_Comm antiguo_com, MPI_Group nuevo_grupo, MPI_Comm* nuevo_com) PARMETROS E NTRADA antiguo_com Comunicador original a partir del cual generamos el nuevo comunicador nuevo_com Grupo que contiene los procesos que formarn parte del nuevo comunicador. Debe ser un subconjunto del grupo asociado al comunicador original (antiguo_com). PARMETROS S ALIDA nuevo_com Nuevo comunicador
182
B.7. MPI_Comm_group
F UNCIONALIDAD Retorna el grupo asociado a un comunicador determinado. S INTAXIS int MPI_Comm_group(MPI_Comm com, MPI_Group* grupo) PARMETROS E NTRADA com Comunicador PARMETROS S ALIDA grupo Grupo asociado al comunicador
B.8. MPI_COMM_RANK
183
B.8. MPI_Comm_rank
F UNCIONALIDAD Retorna el identicador de un proceso dentro de un comunicador. S INTAXIS int MPI_Comm_rank(MPI_Comm com, int* id) PARMETROS E NTRADA com Comunicador dentro del cual el proceso tiene asociado el identicador PARMETROS S ALIDA id Identicador del proceso dentro del comunicador com
184
B.9. MPI_Comm_size
F UNCIONALIDAD Determina el nmero de procesos pertenecientes al grupo asociado a un comunicador. S INTAXIS int MPI_Comm_size(MPI_Comm com, int* numprocs) PARMETROS E NTRADA com Comunicador al cual est asociado el grupo cuyo tamao queremos conocer PARMETROS S ALIDA numprocs Nmero de procesos en el grupo del comunicador (entero)
B.10. MPI_COMM_SPLIT
185
B.10. MPI_Comm_split
F UNCIONALIDAD Particiona un comunicador en varios subconjuntos de procesos y crea un nuevo comunicador para cada uno de ellos. S INTAXIS int MPI_Comm_split(MPI_Comm antiguo_com, int clave_particion, int clave_id, MPI_Comm* nuevo_com) PARMETROS E NTRADA antiguo_com Comunicador original a partir del cual creamos los nuevos comunicadores clave_particion Nmero que representa el nuevo comunicador en el cual quedar englobado el proceso clave_id Identicador del proceso dentro del nuevo comunicador PARMETROS S ALIDA nuevo_com Nuevo comunicador (leer comentarios) C OMENTARIOS La llamada crea un comunicador para cada valor de clave_particion. Los procesos con el mismo valor en clave_particion quedan englobados en el mismo comunicador. Sin embargo los comunicadores creados tendrn el mismo nombre para todos los procesos. Imaginemos que dividimos de manera escalonada un comunicador con 9 procesos en tres comunicadores con 3 procesos, llamados todos nuevo_com. De esta manera, el grupo nuevo_com consistir en los procesos 0, 1 y 2 para los procesos 0, 1 y 2. En los procesos 3, 4 y 5 el grupo subyacente a nuevo_com ser el formado por los procesos 3, 4 y 5; y lo mismo ocurrir con los procesos 6, 7 y 8.
186
B.11. MPI_Finalize
F UNCIONALIDAD Finaliza el entorno de ejecucin MPI. Despus de que el programa haya acabado de utilizar la librera MPI, se debe hacer una llamada a MPI_Finalize. Esta funcin limpia todos los trabajos no nalizados dejados por MPI (por ejemplo, envos pendientes que no hayan sido completados, etc.). S INTAXIS int MPI_Finalize() Esta funcin no tiene parmetros.
B.12. MPI_GET_PROCESSOR_NAME
187
B.12. MPI_Get_processor_name
F UNCIONALIDAD Retorna el nombre del procesador donde est ubicado el proceso. S INTAXIS int MPI_Get_processor_name(char* nombre, int* longnombre) PARMETROS S ALIDA nombre Vector de caracteres cuyo tamao debe ser al menos igual a la constante MPI_MAX_PROCESSOR_NAME destinado a contener el nombre del procesador longname Longitud (en caracteres) de la cadena obtenida C OMENTARIOS El nombre retornado debe identicar un elemento hardware especco; el formato exacto estar denido por la implementacin.
188
B.13. MPI_Group_incl
F UNCIONALIDAD Crea un nuevo grupo a partir de una lista de procesos pertenecientes a un grupo existente. S INTAXIS int MPI_Group_incl(MPI_Group antiguo_grupo, int tamano_nuevo_grupo, int* ids_antiguo_grupo, MPI_Group* nuevo_grupo) PARMETROS E NTRADA antiguo_grupo Grupo original a partir del cual generamos el nuevo grupo tamano_nuevo_grupo Nmero de procesos que formarn el nuevo grupo ids_antiguo_grupo Identicadores de los procesos que formarn parte del nuevo grupo (vector de enteros) PARMETROS S ALIDA nuevo_grupo Nuevo grupo derivado del existente, reordenado segn el vector ids_antiguo_grupo.
B.14. MPI_INIT
189
B.14. MPI_Init
F UNCIONALIDAD Inicializa el entorno de ejecucin MPI. Antes de que podamos llamar a cualquier otra funcin MPI, debemos hacer una llamada a MPI_Init; esta funcin slo debe ser llamada una vez. Permite al sistema hacer todas la conguraciones necesarias para que la librera MPI pueda ser usada. S INTAXIS int MPI_Init(int *argc, char ***argv); PARMETROS E NTRADA argc Puntero al nmero de argumentos argv Puntero a los vectores de argumentos
190
B.15. MPI_Irecv
F UNCIONALIDAD Inicializa la recepcin de un mensaje no bloqueante. S INTAXIS int MPI_Recv(void* mensaje, int contador, MPI_Datatype tipo_datos, int origen, int etiqueta, MPI_Comm com, MPI_Request* peticion) PARMETROS E NTRADA contador Nmero de elementos del tipo tipo_datos que componen el mensaje a recibir tipo_datos Tipo de datos MPI de cada elemento del mensaje a recibir (Cuadro 5.1) origen Identicador del proceso origen etiq Etiqueta del mensaje com Comunicador en el cual se produce la comunicacin PARMETROS S ALIDA mensaje Direccin inicial de memoria del mensaje a recibir peticion Manejador de la peticin C OMENTARIOS Esta funcin recibe mensajes de tipo no bloqueante. Ello quiere decir que la ejecucin del programa no se bloquea con la llamada a esta funcin.
B.16. MPI_ISEND
191
B.16. MPI_Isend
F UNCIONALIDAD Inicializa el envo de un mensaje no bloqueante a un proceso determinado. S INTAXIS int MPI_Isend(void* mensaje, int contador, MPI_Datatype tipo_datos, int destino, int etiq, MPI_Comm com, MPI_Request* peticion) PARMETROS E NTRADA mensaje Direccin inicial de memoria del mensaje a enviar contador Nmero de elementos del tipo tipo_datos que componen el mensaje a enviar tipo_datos Tipo de datos MPI de cada elemento del mensaje a enviar (Cuadro 5.1) destino Identicador del proceso destino etiq Etiqueta del mensaje com Comunicador en el que se produce la comunicacin PARMETROS S ALIDA peticion Manejador de la peticin C OMENTARIOS Esta funcin enva mensajes de tipo no bloqueante. Ello quiere decir que la ejecucin del programa no se bloquea con la ejecucin de la llamada.
192
B.17. MPI_Recv
F UNCIONALIDAD Recibe un mensaje bsico de un proceso. S INTAXIS int MPI_Recv(void* mensaje, int contador, MPI_Datatype tipo_datos, int origen, int etiqueta, MPI_Comm com, MPI_Status* status) PARMETROS E NTRADA contador Nmero de elementos del tipo tipo_datos que componen el mensaje a recibir tipo_datos Tipo de datos MPI de cada elemento del mensaje a recibir (Cuadro 5.1) origen Identicador del proceso origen etiq Etiqueta del mensaje com Comunicador en el cual se produce la comunicacin PARMETROS S ALIDA mensaje Direccin inicial de memoria del mensaje a recibir status Objeto que representa el estado de la recepcin C OMENTARIOS Esta funcin recibe mensajes de tipo bloqueante. Ello quiere decir que la ejecucin del programa se bloquea hasta que el mensaje ha sido recibido.
B.18. MPI_REDUCE
193
B.18. MPI_Reduce
F UNCIONALIDAD Reduce valores en todos los procesos a un solo valor. Realiza una operacin de reduccin. S INTAXIS int MPI_Reduce(void* operando, void* resultado, int contador, MPI_Datatype tipo_datos, MPI_Op operacion, int raiz, MPI_Comm com); PARMETROS E NTRADA operando Direccin inicial de memoria de los valores a operar contador Nmero de elementos del tipo tipo_datos que componen cada uno de los operandos y el resultado tipo_datos Tipo de datos MPI de los valores a operar operacion Operacin de reduccin a realizar (Cuadro 6.1) raiz Identicador del proceso que recibe el valor calculado com Comunicador en el cual se produce la comunicacin PARMETROS S ALIDA resultado Direccin inicial de memoria del valor calculado a recibir (signicante slo en el proceso raiz)
194
B.19. MPI_Send
F UNCIONALIDAD Enva un mensaje bsico a un proceso determinado. S INTAXIS int MPI_Send(void* mensaje, int contador, MPI_Datatype tipo_datos, int destino, int etiq, MPI_Comm com) PARMETROS E NTRADA mensaje Direccin inicial de memoria del mensaje a enviar contador Nmero de elementos del tipo tipo_datos que componen el mensaje a enviar tipo_datos Tipo de datos MPI de cada elemento del mensaje a enviar (Cuadro 5.1) destino Identicador del proceso destino etiq Etiqueta del mensaje com Comunicador en el que se produce la comunicacin C OMENTARIOS Esta funcin enva mensajes de tipo bloqueante. Ello quiere decir que la ejecucin del programa se bloquea hasta que el mensaje ha sido enviado.
B.20. MPI_SENDRECV_REPLACE
195
B.20. MPI_Sendrecv_replace
F UNCIONALIDAD Enva y recibe un mensaje bsico utilizando un slo buffer. S INTAXIS int MPI_Sendrecv_replace(void* mensaje, int contador, MPI_Datatype tipo_datos, int destino, int etiqdestino, int origen, int etiqorigen, MPI_Comm com, MPI_Status* status) PARMETROS E NTRADA mensaje Direccin inicial de memoria del mensaje a enviar y en la cual recibiremos el nuevo mensaje contador Nmero de elementos del tipo tipo_datos que componen el mensaje a enviar/recibir tipo_datos Tipo de datos MPI de cada elemento del mensaje a enviar/recibir (Cuadro 5.1) destino Identicador del proceso destino etiqdestino Etiqueta del mensaje a enviar origen Identicador del proceso origen etiqorigen Etiqueta del mensaje a recibir com Comunicador en el que se produce la comunicacin C OMENTARIOS Esta funcin enva/recibe mensajes de tipo bloqueante. Ello quiere decir que la ejecucin del programa se bloquea hasta que el mensaje ha sido enviado/recibido.
196
B.21. MPI_Type_commit
F UNCIONALIDAD Acomete un tipo de datos MPI. S INTAXIS int MPI_Type_commit(MPI_Datatype* tipo_datos_MPI) PARMETROS E NTRADA tipo_datos_MPI Tipo de datos MPI
B.22. MPI_TYPE_STRUCT
197
B.22. MPI_Type_struct
F UNCIONALIDAD Crea un tipo de datos MPI para estructuras. S INTAXIS int MPI_Type_struct(int contador, int longitudes_bloque[], MPI_Aint indices[], MPI_Datatype antiguos_tipos_datos, MPI_Datatype* nuevo_tipo) PARMETROS E NTRADA contador Nmero de bloques longitud_bloque Nmero de elementos de tipo tipo_datos_elem de cada bloque indices Direccin relativa de cada bloque antigus_tipo_datos Tipos de datos de cada bloque PARMETROS S ALIDA nuevo_tipo Nuevo tipo de datos MPI
198
B.23. MPI_Type_vector
F UNCIONALIDAD Crea un tipo de datos MPI para vectores. S INTAXIS int MPI_Type_vector(int contador, int longitud_bloque, int salto, MPI_Datatype tipo_datos_elem, MPI_Datatype* nuevo_tipo) PARMETROS E NTRADA contador Nmero de bloques longitud_bloque Nmero de elementos de tipo tipo_datos_elem en cada bloque salto Nmero de elementos de tipo tipo_datos_elem que hay entre los sucesivos elementos de nuevo_tipo. tipo_datos_elem Antiguo tipo de datos PARMETROS S ALIDA nuevo_tipo Nuevo tipo de datos MPI
B.24. MPI_WAIT
199
B.24. MPI_Wait
F UNCIONALIDAD Espera a que se complete un envo o una recepcin de un mensaje. S INTAXIS int MPI_Wait(MPI_Request* peticion, MPI_Status* status) PARMETROS E NTRADA peticion Manejador de la peticin PARMETROS S ALIDA status Objeto que representa el estado del envo/recepcin del mensaje
200
B.25. MPI_Waitall
F UNCIONALIDAD Espera a que se completen todas las peticiones especicadas en un vector. S INTAXIS int MPI_Waitall(int contador, MPI_Request* vector_peticiones, MPI_Status* status) PARMETROS E NTRADA contador Longitud del vector de peticiones vector_peticiones Vector de peticiones PARMETROS S ALIDA status Objeto que representa el estado del envo/recepcin del mensaje
B.26. MPI_WAITANY
201
B.26. MPI_Waitany
F UNCIONALIDAD Espera a que se complete cualquiera de las peticiones especicadas en un vector. S INTAXIS int MPI_Waitany(int contador, MPI_Request* vector_peticiones, int* indice, MPI_Status* status) PARMETROS E NTRADA contador Longitud del vector de peticiones vector_peticiones Vector de peticiones PARMETROS S ALIDA indice Posicin de la peticin satisfecha en el vector de peticiones status Objeto que representa el estado del envo/recepcin del mensaje
202
B.27. MPI_Wtime
F UNCIONALIDAD Retorna el tiempo transcurrido para un proceso. S INTAXIS double MPI_Wtime() VALOR DE R ETORNO Tiempo en segundos desde que comenz la ejecucin del proceso.
Conclusiones
Para llegar a ciertas conclusiones en el estudio realizado lo primero que debemos hacer es analizar los resultados obtenidos en las ejecuciones de los algoritmos paralelos. Slo de este modo podremos demostrar la utilidad y potencialidad del procesamiento paralelo ejecutado en redes bajo Linux.
Sumario de Resultados
Comenzaremos el anlisis observando algunos grcos ciertamente determinantes. La gura 1 muestra un grco que representa el tiempo de ejecucin del algoritmo Clculo de reas mediante Montecarlo utilizando paso de mensajes no bloqueantes.
Calculo de Areas No Bloqueante: Tiempo Ejecucion 140 Tiempo Ejecucion 120
100
Tiempo (seg)
80
60
40
20
0 0 2 4 6 8 10 12 14 16 Numero de Procesadores
En el grco observamos una notoria reduccin en el tiempo de ejecucin de dicho algoritmo conforme incorporamos procesadores al cmputo. Ello es lgico debido a que se trata de 203
204
CONCLUSIONES
un algoritmo cuyo rendimiento depende bsicamente de la capacidad de cmputo que tenga la mquina en la cual lo ejecutamos. Adems tenemos la gran ventaja de que si dividimos dicho cmputo en varios elementos procesadores, el proceso de converger los resultados parciales de cada uno de los elementos procesadores es bastante sencillo: slo tenemos que hacer la media de todos ellos. As pues este algoritmo se muestra muy apropiado para el procesamiento paralelo. El rendimiento obtenido en la versin bloqueante de dicho algoritmo es slo un poco inferior al obtenido en la versin no bloqueante, aunque su comportamiento es similar. En la misma lnea se encuentra el algoritmo Regla del Trapecio. En la gura 2 tenemos el grco que muestra el rendimiento de dicho algoritmo. De nuevo observamos una importante reduccin del tiempo necesario para su ejecucin. Debemos hacer notar que en este tipo de algoritmos el nivel de detalle es un elemento a tener en cuenta. La calidad de las aproximaciones que hacemos en estos algoritmos depender del nmero de muestras aleatorias recogidas en el algoritmo Clculo de reas mediante Montecarlo, y del nmero de intervalos generados en el algoritmo Regla del Trapecio. Por supuesto el nivel de detalle queda jado de antemano antes de realizar las pruebas de rendimiento con distintas cantidades de procesadores.
Regla del Trapecio: Tiempo Ejecucion 140 Tiempo Ejecucion 120
100
Tiempo (seg)
80
60
40
20
0 0 2 4 6 8 10 12 14 16 Numero de Procesadores
Por otro lado el algoritmo Multiplicacin de Matrices de Fox tiene una serie de caractersticas que lo diferencian del resto. Una de ellas es la exactitud; aqu no tratamos de hacer aproximaciones precisas, a diferencia de los algoritmos anteriormente expuestos. En este algoritmo multiplicamos matrices cuadradas particionndolas en submatrices. Cada proceso en este caso se encargar de calcular una submatriz de la matriz resultado. La principal dicultad en este caso es la sobrecarga en la comunicacin. El hecho de tener que transmitir submatrices enteras entre los procesadores diculta mucho el clculo uido.
205 Sin embargo obtenemos resultados muy interesantes en el cmputo de matrices de un orden elevado. Como podemos observar en la gura 3 el crecimiento del tiempo de ejecucin es exponencial para todas las cantidades de procesos utilizadas; sin embargo dicho crecimiento es ms paulatino cuanto mayor es la cantidad de procesos empleados.
Comparacion Tiempo de distintas Cantidades de Procesos 2500 16 9 4 1 2000
Tiempo (seg)
1500
1000
500
0 500
1000
1500
2000
2500
3000
3500
4000
4500
5000
Orden Matriz
El cuadro 1 muestra los tiempos obtenidos en la ejecucin del algoritmo Multiplicacin de Matrices de Fox. Orden \ Num.Procs. 700 1400 2100 2800 3500 4200 4900 1 19,0 / 19,1 172,0 / 172,2 2237,2 / 2252,8 4 10,3 / 14,9 59,8 / 78,4 190,9 / 232,7 430,1 / 504,3 2074,1 / 2202,5 9 10,0 / 15,37 50,1 / 70,9 135,1 / 183,6 274,9 / 362,3 491,3 / 626,8 833,1 / 1032,6 1257,1 / 1527,3 16 19,1 / 23,2 57,3 / 78,9 134,0 / 183,3 261,1 / 344,8 458,5 / 599,9 726,7 / 930,2 1016,4 / 1291,9
Contiene para cada cantidad de procesadores empleados los tiempos obtenidos en la multiplicacin de matrices de distintos rdenes; los dos tiempos separados por el carcter / representan el tiempo requerido para multiplicar las matrices por un lado, y por otro el tiempo requerido para multiplicarlas y mostrar el resultado. Dichos tiempos se miden en segundos.
206
CONCLUSIONES
Para cada orden de matrices utilizado resaltaremos en negrita el tiempo de multiplicacin ptimo. Pero en el anlisis de los algoritmos no slo se deben medir sus tiempos de ejecucin. Una variable importante a tener en cuesta es el coste. Dicha variable relaciona el nmero de procesadores empleados con el tiempo de ejecucin obtenido; de este modo nos permite saber si es rentable el uso de una cantidad mayor de procesadores en la ejecucin de un algoritmo dado. El coste normalmente aumenta en la mayora de los algoritmos al emplear una cantidad mayor de procesadores en su ejecucin. En la gura 4 mostramos el coste de ejecucin del algoritmo Clculo de reas mediante Montecarlo. La curva de crecimiento del coste prcticamente se repite en la mayora de los algoritmos (gura 5).
Calculo de Areas No Bloqueante: Coste 175 Coste 170
165
160 Coste
155
150
145
140
Sin embargo en la comparacin de costes del algoritmo de Fox (gura 6) observamos que el coste depende tanto del nmero de procesos empleados como del tamao de las matrices a multiplicar. De hecho vemos que para matrices de orden mayor a 2000 la utilizacin de 1 slo procesador es la ms costosa. Con este planteamiento podemos prever que para tamaos de matrices superiores a los empleados en las pruebas la utilizacin de 16 procesadores ser la ms rentable.
207
Regla del Trapecio: Coste 138 Coste 136
134
132 Coste
130
128
126
124
Comparacion Coste de distintas Cantidades de Procesos 18000 16000 14000 12000 Coste 10000 8000 6000 4000 2000 0 500 16 9 4 1
1000
1500
2000
2500
3000
3500
4000
4500
5000
Orden Matriz
208
CONCLUSIONES
Corolario
Las demostraciones de la seccin anterior nos permiten argumentar que el procesamiento paralelo es una tcnica que arroja resultados muy satisfactorios para cierto tipo de computaciones. Ciertamente en todos los algoritmos desarrollados obtenemos una mejora del rendimiento al aumentar el nmero de procesadores utilizados. Sin embargo debemos advertir de que no slo debemos tener en cuenta el tiempo de ejecucin de los algoritmos para evaluarlos. En muchos ambientes la incorporacin de una mayor cantidad de procesadores a la ejecucin de un algoritmo realmente cuesta dinero. En estos casos la variable coste nos permitir medir la rentabilidad de la inclusin de nuevos procesadores en la ejecucin. Por lo tanto deberamos emplear ms o menos procesadores dependiendo de la necesidad que tengamos de acelerar el procesamiento y de los recursos que podamos utilizar (o adquirir), intentando llegar a un compromiso entre rendimiento y coste que sea ptimo para nuestras necesidades. Debemos insistir en que el paralelismo es un campo realmente extenso en el cual convergen una amplia variedad de tcnicas y tecnologas, como vimos en la primera parte del presente documento. Nosotros slo hemos investigado sobre el paralelismo llevado a cabo mediante la utilizacin de clusters; no obstante el hacerlo conlleva el obtener una cierta perspectiva del amplio abanico de posibilidades que existen por explorar. En este panorama cabe destacar la importancia de la existencia de herramientas de desarrollo de software paralelo que hacen del paralelismo una tcnica al alcance de todos. Los estndares como MPI no slo ofrecen este tipo de facilidades, si no que adems aaden portabilidad a los algoritmos implementados mediante su utilizacin. Con todo lo expuesto anteriormente debemos darnos cuenta de que slo necesitamos un grupo de ordenadores convencionales conectados en red bajo Linux para poder ejecutar aplicaciones paralelas de manera eciente. De este modo podemos disponer por muy poco dinero (o incluso nada) de todo un computador paralelo con una potencia relativamente alta. As pues... por qu no aprovecharlo?.
Direcciones URL
1. CHIMP Download <ftp://ftp.epcc.ed.ac.uk/pub/chimp/release/> FireWire <http://www.apple.com/rewire/> FSMLabs Inc. creadores de RTLinux <http://www.rtlinux.org/> Intel Compilers <http://www.intel.com/software/products/compilers/> Internet Parallel Computing Archive <http://wotug.ukc.ac.uk/parallel/> LAM/MPI Parallel Computing <http://www.lam-mpi.org/> MMX Emulator <http://www-sop.inria.fr/prisme/personnel/pion/progs/mmx-emu/> MPI Forum <http://www.mpi-forum.org/> MPICH - A Portable Implementation of MPI <http://www.mcs.anl.gov/mpi/mpich/> MPICH Downloads <http://www.mcs.anl.gov/mpi/mpich/download.html> MPICH Parches <http://www.mcs.anl.gov/mpi/mpich/buglist-tbl.html> OpenSSH - Versin libre de SSH <http://www.openssh.com/> Packet Engines Gigabit Ethernet with Linux <http://www.scyld.com/network/yellown.html> 209
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
210 14. 15. 16. 17. 18. 19. 20. 21. PVM - Parallel Virtual Machine <http://www.epm.ornl.gov/pvm/pvm_home.html> SWAR Homepage at Purdue University <http://shay.ecn.purdue.edu/~swar/> The Aggregate <http://aggregate.org/> The Beowulf Underground <http://www.beowulf-underground.org/> The Berkeley NOW Project <http://now.cs.berkeley.edu/> The Globus Project <http://www.globus.org/> USB - Universal Serial Bus <http://www.usb.org/> WineHQ - Windows Emulator <http://www.winehq.com/>
DIRECCIONES URL