• No se han encontrado resultados

Implementación de un algoritmo evolutivo basado en MOS

N/A
N/A
Protected

Academic year: 2020

Share "Implementación de un algoritmo evolutivo basado en MOS"

Copied!
144
0
0

Texto completo

(1)

Universidad Politécnica de Madrid

Facultad de Informática

Proyecto fin de carrera

Implementación de un algoritmo

evolutivo basado en MOS

Autor

: Manuel Zaforas

Tutores

: José María Peña Sánchez

Antonio LaTorre de la Fuente

(2)

Manuel Zaforas

Madrid, Julio 2008

Tutores:

José María Peña Sánchez (jmpena@fi.upm.es)

Antonio LaTorre de la Fuente (atorre@fi.upm.es)

(3)

Cita: "La selección natural, es una fuerza siempre dispuesta a la acción y tan inconmen-surablemente superior a los débiles esfuerzos del hombre como las obras de la Naturaleza lo son a las del Arte."

Charles Darwin.

El origen de las especies, capítulo III.

(4)
(5)

Agradecimientos

Este proyecto es el colofón a una etapa de mi vida marcada por muchas personas y experiencias

positivas, que me han llevado a donde ahora estoy y a formarme como ingeniero y como persona.

En primer lugar quiero agradecer a mis padres, ya que en gran medida todo lo que soy y lo bueno

que tengo se lo debo a ellos, que me han apoyado siempre incondicionalmente en todo lo que he hecho.

A mi hermana Carlota por toda la paciencia que tiene conmigo y por haber sido siempre mi amiga.

Gracias sobre todo a Nuria, porque desde que te conocí eres el faro que ilumina mi vida y que me

hace feliz al margen de todo lo demás.

Gracias a todos los compañeros con los que he compartido estudios, prácticas y sufrimientos durante

la carrera, especialmente a Javi, Trevi, Jaime, Alvarito, Rafa, Marí Paz, Jose, Marco, Mariajo, Laura,

Jess, Raquel, Luis, Miguel, Soto, Juanito y todos los que me dejo pero que hemos luchado juntos en este

campo de batalla llamado FI, y de vez en cuando hemos hecho una parada para relajarnos y visitar a los

patos tomando una paella. Gracias también a toda la gente de Delegación, Coleópteros, Alfa y Omega,

Histrión y todos los follones en los que he estado metido en la FI.

Gracias a toda la gente del Laboratorio de Sistemas Operativos del DATSI por todo lo que he

apren-dido con ellos y por lo bien que nos lo hemos pasado en esas largas sobremesas de pueblos y caminos.

Gracias a Fernando Pérez por darme la oportunidad de entrar en el laboratorio y por todo lo que he

aprendido de él. Gracias a los doctorandos: Chuso, Juan, Santi y Alberto por todo lo que saben y la

fa-cilidad con que lo transmiten, estando siempre dispuestos a echar una mano. Gracias también a Alberto,

Germán, Luis y el resto de becarios que compartimos el peso del yugo de nuestras becas rodeados de

(6)

Gracias especialmente a los AR: Rojo, Santi, Nacho, Zuazo, Diego, Ato, P. Lorenzo, P. José Manuel,

Chunia y Javi Lorenzo, por esas largas, divertidas e improductivas reuniones en el Rufos o en torno a

unas palomitas quemadas. Gracias también a todos los que siempre están ahí para escaparse al ático

cuando es necesario o para desahogarnos dando patadas a un balón, especialmente a Edu, Ian, Líder,

Pablo, Alex, Sonso (que eres como uno más), Merino, Manza, Chuso, Héctor, Paco, Braci, Luquitas y

todos los demás. Gracias sobre todo al P. Carlos por haber sido un segundo padre para mí.

Gracias a toda la gente del equipo de basket, especialmente a Alfre por todas las cosas que hemos

vivido juntos.

Y por último gracias a Chema y Toni, por toda la paciencia que han tenido conmigo y por todo lo

que he aprendido de ellos, porque sin ellos este proyecto no sería una realidad.

Gracias también a tantos que me dejo en el tintero y en general a todos porque sin duda no habría

(7)

Índice

Agradecimientos . . . I

Índice . . . III

Índice de figuras . . . IX

Índice de tablas . . . XIII

Acrónimos y abreviaturas . . . XVII

PARTEI INTRODUCCIÓN Y OBJETIVOS

1. Introducción y objetivos . . . 3

1.1. Introducción . . . 3

1.2. Objetivos . . . 4

1.3. Estructura de la memoria . . . 6

PARTEII ESTADO DE LA CUESTIÓN 2. Computación de altas prestaciones con arquitecturas paralelas . . . 9

2.1. Introducción . . . 9

(8)

2.2.1. Multiprocesadores . . . 12

2.2.2. Multicomputadores . . . 13

2.2.2.1. Clúster . . . 14

2.2.2.2. Magerit . . . 14

2.3. Topologías y redes de interconexión . . . 15

2.3.1. Tecnologías de interconexión . . . 16

2.4. Rendimiento en computación paralela . . . 17

2.4.1. Factor de aceleración: Speedup . . . 17

2.4.2. Ley de Amdahl . . . 18

2.4.3. Ley de Gustafson . . . 19

2.5. Proceso de paralelización: Principios de diseño . . . 20

2.5.1. Descomposición . . . 21

2.5.2. Asignación . . . 23

2.5.3. Orquestación . . . 23

2.5.3.1. Comunicación unicast vs. broadcast . . . 23

2.5.3.2. Comunicación estructurada vs. no estructurada . . . 24

2.5.3.3. Comunicación estática vs. dinámica . . . 25

2.5.3.4. Comunicación síncrona vs. asíncrona . . . 25

2.5.4. Despliegue . . . 25

2.6. Herramientas de programación paralela . . . 26

2.6.1. HPF . . . 26

2.6.2. MPI . . . 27

2.6.2.1. Funcionamiento de MPI . . . 28

2.6.3. OMP . . . 28

3. Algoritmos evolutivos . . . 31

3.1. Introducción . . . 31

3.2. Algoritmos genéticos . . . 33

(9)

Índice

3.2.1.1. Método de la ruleta . . . 36

3.2.1.2. Método de la ruleta extendido con rangos . . . 37

3.2.1.3. Método de selección por torneo . . . 38

3.2.2. Operador de cruce . . . 39

3.2.2.1. Cruce de un punto . . . 39

3.2.2.2. Cruce en dos puntos . . . 39

3.2.2.3. Cruce uniforme . . . 40

3.2.2.4. Cruce aritmético . . . 40

3.2.2.5. Cruce cíclico . . . 40

3.2.2.6. Cruce ordenado . . . 41

3.2.3. Operador de mutación . . . 41

3.2.3.1. Mutación por inversión . . . 41

3.2.3.2. Mutación por intercambio repetido . . . 42

3.2.3.3. Mutación uniforme . . . 42

3.3. Algoritmos EDA . . . 42

3.3.1. Heurísticas para el aprendizaje . . . 44

3.3.1.1. Modelo sin dependencias . . . 45

3.3.1.2. Modelos con dependencias bivariantes . . . 45

3.3.1.3. Modelos con múltiples dependencias . . . 45

3.4. Algoritmos evolutivos paralelos . . . 46

3.4.1. Modelos con población global . . . 46

3.4.1.1. Variante síncrona con maestro-esclavos . . . 46

3.4.1.2. Variante semisíncrona con maestro-esclavos . . . 47

3.4.1.3. Variante asíncrona concurrente . . . 47

3.4.2. Modelos de islas . . . 47

3.4.2.1. Topologías de interconexión . . . 48

(10)

PARTEIII DISEÑO Y DESARROLLO DE LA SOLUCIÓN

4. Multiple offspring sampling genetic algorithm en GAEDALib . . . 53

4.1. Introducción . . . 53

4.2. Diseño y arquitectura de MOS . . . 54

4.2.1. Aproximación MOS central . . . 54

4.2.2. Aproximación MOS autonomic . . . 57

4.2.3. Relación de MOS y GAEDALib . . . 58

4.3. Clase GAMOSGA . . . 59

4.4. Técnicas MOS . . . 61

4.4.1. Clase GAMOSTechnique . . . 63

4.4.2. Técnicas MOS GA . . . 65

4.4.3. Técnicas MOS EDA . . . 65

4.4.4. Conjunto de técnicas . . . 65

4.5. Genomas MOS . . . 66

4.5.1. Clase GAMOSGenome . . . 68

4.6. Conversor MOS . . . 69

4.7. Serializador MOS . . . 70

PARTEIV ANÁLISIS DE RESULTADOS 5. Análisis de resultados . . . 75

5.1. Introducción . . . 75

5.2. Resultados con funciones matemáticas . . . 78

5.2.1. Problema MaxBit . . . 78

5.2.1.1. Resultados con Multiple Offspring Sampling (MOS) . . . 79

5.2.2. Problema Royal Road . . . 83

5.2.2.1. Resultados con MOS . . . 83

(11)

Índice

5.2.3.1. Resultados con MOS . . . 86

5.2.4. Función Rastrigin . . . 91

5.2.4.1. Resultados con MOS . . . 91

5.3. Resultados con el TSP . . . 97

5.3.1. Introducción al problema TSP . . . 97

5.3.2. Variaciones en el número de nodos y en la población . . . 97

5.3.3. Resultados con hibridación de técnicas basadas en GAs . . . 103

5.3.3.1. Análisis de la participación y la calidad . . . 105

5.3.4. Evolución central versus autonómica . . . 107

5.3.4.1. Análisis de tiempos . . . 111

PARTEV CONCLUSIONES Y LÍNEAS FUTURAS 6. Conclusiones y líneas futuras . . . 115

6.1. Conclusiones . . . 115

6.2. Líneas futuras . . . 116

(12)
(13)

Índice de figuras

2.1. Taxonomía de Flynn . . . 11

2.2. Arquitecturas UMA y NUMA . . . 12

2.3. Arquitectura de un multicomputador . . . 13

2.4. Magerit. CeSViMa . . . 14

2.5. Topologías de red . . . 16

2.6. Ley de Amdahl . . . 19

2.7. Etapas del proceso de paralelización . . . 21

2.8. Impacto del límite de la concurrencia . . . 22

2.9. Comunicación unicast vs. broadcast . . . 24

2.10. Comunicación estructurada vs. no estructurada . . . 24

2.11. Comunicación síncrona vs. asíncrona . . . 25

2.12. Multithreading con OMP . . . 28

3.1. Ejemplo del método de selección de la ruleta . . . 37

3.2. Método de la ruleta vs. método de la ruleta con rangos . . . 38

3.3. Cruce en un punto . . . 39

3.4. Cruce en dos puntos . . . 39

3.5. Cruce uniforme . . . 40

3.6. Cruce aritmético . . . 40

(14)

3.8. Cruce ordenado . . . 41

3.9. Operador de mutación por inversión . . . 41

3.10. Operador de mutación por intercambio . . . 42

3.11. Operador de mutación uniforme . . . 42

3.12. Ejemplo de un modelo gráfico parax= (A,B,C,D) . . . 44

3.13. Topologías de islas implementadas en GAEDALib . . . 49

4.1. Visión general del funcionamiento del algoritmo MOS central . . . 55

4.2. Diagrama de secuencia del algoritmo MOS . . . 56

4.3. Diagrama de secuencia del algoritmo MOS autonomic . . . 58

4.4. Clases de GAGeneticAlgorithm . . . 59

4.5. Tipos de técnicas MOS . . . 63

4.6. Diagrama de clase de genomas MOS . . . 67

4.7. Funcionamiento del conversor MOS . . . 69

4.8. Funcionamiento del serializador MOS . . . 71

5.1. Superficie de la función MaxBit conn=2 . . . 79

5.2. Superficie de la función Griewank conn=2 yd=4000 . . . 86

5.3. Superficie de la función Rastrigin conn=2,ω=2πya=10 . . . 91

5.4. Comparativa de técnicas para el problema Swiss42 . . . 99

5.5. Comparativa de técnicas para el problema Brazil58 . . . 99

5.6. Comparativa de técnicas para el problema Gr120 . . . 100

5.7. Comparativa del fitness con la técnica IntPermOXSIM en Gr120 . . . 101

5.8. Comparativa del tiempo con la técnica IntPermOXSIM en Gr120 . . . 102

5.9. Comparativa de los resultados para el TSP con hibridación MOS central . . . 104

5.10. Evolución de la participación y la calidad. Combinación de 3 técnicas con el TSP gr120 105 5.11. Evolución de la participación y la calidad para una combinación de 3 técnicas en el TSP gr120 sin porcentaje mínimo de participación . . . 107

5.12. Comparativa del fitness para el TSP con hibridación MOS autonomic . . . 109

(15)

Índice de figuras

5.14. Comparativa del fitness para el TSP brazil58 con evolución MOS central frente autonomic110

5.15. Comparativa del fitness para el TSP gr120 con evolución MOS central frente autonomic 110

5.16. Comparativa del tiempo para el TSP swiss42 con evolución MOS central frente autonomic111

5.17. Comparativa del tiempo para el TSP brazil58 con evolución MOS central frente

auto-nomic . . . 111

(16)
(17)

Índice de tablas

1.1. Alternativas para la configuración de un algoritmo evolutivo . . . 4

2.1. Etapas de la paralelización y sus objetivos . . . 21

2.2. Comparativa de herramientas para programación paralela . . . 26

3.1. Algunos de los algoritmos evolutivos más representativos . . . 33

3.2. Ejemplo del cálculo de la probabilidad del método de la ruleta . . . 36

3.3. Ejemplo del cálculo de la probabilidad del método de la ruleta con rangos . . . 38

5.1. Técnicas GA definidas . . . 76

5.2. Técnicas EDA definidas . . . 77

5.3. Equivalencia entre identificadores de técnicas . . . 77

5.4. Resultados para MaxBit con hibridación MOS central yn=12 . . . 80

5.5. Resultados para MaxBit con hibridación MOS central yn=30 . . . 81

5.6. Resultados para MaxBit con hibridación MOS central yn=100 . . . 82

5.7. Resultados para Royal Road con hibridación MOS central,k=4,b=8 yg=7 . . . 84

5.8. Resumen de fitness para el problema Royal Road con técnicas individuales . . . . 85

5.9. Resumen de mejores fitness para el problema Royal Road con hibridación MOS . . . 85

5.10. Resultados para Griewank con hibridación MOS central,n=10 yd=4000 . . . . 87

5.11. Resultados para Griewank con hibridación MOS central,n=20 yd=4000 . . . . 88

(18)

5.13. Resumen de fitness de las peores técnicas para la función Griewank . . . 90

5.14. Resultados para Rastrigin con hibridación MOS central,n=5,a=10 yω=2π . . . 92

5.15. Resultados para Rastrigin con hibridación MOS central,n=20,a=10 yω=2π . . 93

5.16. Resultados para Rastrigin con hibridación MOS central,n=30,a=10 yω=2π . . 94

5.17. Resumen fitness técnicas individuales para función Rastrigin . . . 95

5.18. Resumen mejores fitness para función Rastrigin con hibridación MOS yn=20 . . . 96

5.19. Resumen mejores fitness para función Rastrigin con hibridación MOS yn=30 . . . 96

5.20. Resultados para el TSP con las 7 técnicas evolutivas, 1 nodo y 1000 individuos . . . 98

5.21. Fitness con la técnica IntPermOXSIM en Gr120, variando nodos y población . . . . 100

5.22. Tiempo en segundos con la técnica IntPermOXSIM en Gr120, variando el número de

nodos y de individuos . . . 102

5.23. Resultados para el TSP con hibridación MOS central de técnicas GA . . . 104

(19)

Índice de algoritmos

3.1. Algoritmo genético básico . . . 35

(20)
(21)

Acrónimos y abreviaturas

UP Unidad de Proceso

SISD Single Instruction Single Data

MISD Multiple Instruction Single Data

SIMD Single Instruction Multiple Data

MIMD Multiple Instruction Multiple Data

UMA Uniform Memory Access

NUMA Non Uniform Memory Access

cc-NUMA Cache Coherent Non Uniform Memory Access

SMP Symmetric Multi-Processing

CeSViMa Centro de Supercomputación y Visualización de Madrid

UPM Universidad Politécnica de Madrid

SCI Scalable Coherent Interface

IEEE Institute of Electrical and Electronics Engineers

PCI Peripheral Component Interconnect

(22)

HPF High Performance Fortran

HPF-2 High Performance Fortran versión 2.0

F95 Fortran 95

PVM Parallel Virtual Machine

MPI Message Passing Interface

MPI-2 Message Passing Interface versión 2.0

MPI I/O Message Passing Interface In/out

MPICH Message Passing Interface Chameleon

MPICH2 Message Passing Interface Chameleon versión 2.0

LAM/MPI Local Area Multicomputer Message Passing Interface

OpenMPI Open Message Passing Interface

OMP Open Multi Processing

IBM International Business Machines

IA Inteligencia Artificial

GA Genetic Algorithms

EDA Estimation of Distributions Algorithms

MGP Modelo Gráfico Probabilístico

UMDA Univariate Marginal Distribution Algorithm

PBIL Population Based Incremental Learning

MIMIC Mutual Information Maximization for Input Clustering

COMIT Combining Optimizers with Mutual Information Trees

BMDA Bivariate Marginal Distribution Algorithm

EBNA Estimation of Bayesian Network Algorithm

(23)

0. Acrónimos y abreviaturas

EMNA Estimation of Multivariate Normal Algorithm

EGNA Estimation of Gaussian Network Algorithm

GALib Genetic Algorithm Library

GAEDALib Genetic Algorithm Estimation of Distribution Algorithms Library

MOS Multiple Offspring Sampling

TSP Traveling Salesman Problem

RAND Research and Development

AX Aritmetic Crossover

UC Uniform Crossover

OX Order Crossover

CX Cycle Crossover

EOC Even Odd Crossover

OPC One Point Crossover

TPC Two Points Crossover

BC Blended Crossover

REM Repeated Exchange Mutation

SIM Simple Inversion Mutation

UM Uniform Mutation

GM Gaussian Mutation

SM Swap Mutation

PI Permutation Initializer

SC Simple Comparator

UI Uniform Initializer

PLSC Partial Least Squares Correct

BIC Bayesian Information Criterion

(24)
(25)

Parte I

(26)
(27)

Capítulo 1

Introducción y objetivos

1.1.

Introducción

Los algoritmos evolutivos son métodos adaptativos que suelen usarse para solucionar problemas de

búsqueda y optimización no lineales y con espacios de búsqueda que pueden ser muy grandes. Dada

una población de posibles soluciones a un problema concreto, la computación evolutiva expande esta

población con nuevas y mejores soluciones, obtenidas a partir de los individuos de la población anterior.

Este patrón de funcionamiento se inspira en la teoría de la evolución postulada por Darwin en 1859 [6].

Los genes sirven para codificar la representación de un individuo en el que modelizamos una solución al

problema.

Los padres se irán cruzando o combinando de alguna manera y sufriendo alteraciones para generar

los genes de los hijos. El objetivo es conseguir que la población vaya mejorando de generación en

genera-ción produciendo nuevos individuos que mejoren a los anteriores. Siguiendo esta tendencia intentaremos

llegar a una solución válida.

Inicialmente, estos algoritmos fueron considerados desde un punto de vista teórico sin una

aplica-ción muy extendida en el mundo real. Sin embargo, la actividad investigadora en este área ha llegado a

desarrollar todo un modelo teórico y madurar lo suficiente como para poder aplicarse en la solución de

problemas reales en muchos ámbitos. Además, el rápido avance de la tecnología permite disponer cada

vez de forma más sencilla y económica de una gran potencia de cálculo, necesaria para sacar partido a

esta aproximación teórica. Esto ha provocado que los algoritmos evolutivos estén ciertamente en auge,

siendo su uso cada vez más extendido para solucionar problemas en muy diversos campos.

Estas técnicas de optimización están siendo cada vez más utilizadas en diversos escenarios de

(28)

solu-ciones que crecen de forma no lineal, lo cual incluye campos tan dispares como la química molecular, la

resistencia de materiales, la robótica o la teoría de juegos, entre otros.

El concepto de algoritmo evolutivo engloba toda una familia de técnicas y enfoques teóricos que

tienen en común el mismo patrón de iteración evolutiva y codificación de soluciones como individuos.

Dos de las vertientes más destacables hoy en día son los GA y los algoritmos EDA que, junto con algunas

otras técnicas evolutivas, han conseguido resultados muy interesantes.

El enfoque de los GA fue desarrollado por J.H. Holland en torno a 1975 [15]. Éste es el enfoque más

clásico en el que los padres son seleccionados de una manera arbitraria y recombinados mediante ciertos

operadores de cruce y mutación, dando lugar a una nueva descendencia.

En el enfoque de los algoritmos más avanzados como los EDA los operadores de cruce y mutación

son sustituidos por un modelo probabilístico que es construido a partir de la población actual y a partir

del cual se inferirán los individuos que formarán la siguiente población.

La continua investigación en el área de los algoritmos evolutivos plantea nuevos retos

constantemen-te y propone nuevas técnicas, variaciones o configuraciones, que aportan mejoras a los modelos más

básicos.

1.2.

Objetivos

Una de las cuestiones que se nos plantean a la hora de intentar solucionar un problema con un

algorit-mo evolutivo es saber qué aproximaciones y configuraciones son las más adecuadas a nuestro problema.

Como ya hemos visto anteriormente, existen diferentes enfoques de algoritmos evolutivos y, dentro de

éstos, muchas formas de ajustarlos definiendo diferentes operadores, probabilidades, codificaciones y

otros parámetros.

En la tabla 1.1 se presenta un resumen de los elementos a considerar en un algoritmo evolutivo.

Parámetro Opciones

Tipo de algoritmo GA, EDA con redes bayesianas, EDA con redes gaussianas...

Codificación binaria, entera, real...

Operadores cruce, mutación, evaluación, comparación...

Otros parámetros tamaño de la población, probabilidad de cruce y mutación...

(29)

1.2. Objetivos

La elección y combinación de todos estos elementos supone un problema de optimización en sí

mis-mo. Este proyecto tiene como objetivo la implementación de un nuevo algoritmo evolutivo, denominado

Multiple Offspring Sampling (MOS), que sea capaz de combinar dinámicamente diferentes algoritmos,

codificaciones, operadores y parámetros para llegar a la mejor solución posible de la manera más rápida.

Para poder aplicar este nuevo enfoque basado en una arquitectura de hibridación de algoritmos es

necesario desarrollar un mecanismo para evaluar la calidad de la población durante la ejecución. También

es necesario desarrollar el concepto de “técnica” como combinación de posibles parámetros y permitir

un ajuste dinámico de la participación de las mismas.

En resumen, los objetivos de este proyecto serían los siguientes:

Implementación de un algoritmo con soporte para diferentes técnicas evolutivas.

Desarrollo de la capacidad de evaluación de la calidad de una técnica evolutiva.

• Definición e implementación de estas medidas de calidad.

Orquestación de las técnicas.

• Ajuste dinámico de la participación en base al rendimiento utilizando medidas de calidad.

• Facilitar el diseño y la introducción de nuevas técnicas de recombinación.

Definición de genomas con soporte para múltiples codificaciones.

• Conversión entre codificaciones.

• Serialización de codificaciones.

Con la introducción de todas estas novedades al concepto clásico de hibridación pretendemos mejorar

los resultados obtenidos hasta ahora con algoritmos evolutivos tradicionales o, en el peor de los casos, ser

capaces de detectar la mejor técnica de recombinación de entre todas las disponibles sin un conocimiento

a priori del rendimiento de las mismas. Del mismo modo, pretendemos dar un soporte para el desarrollo

de nuevas investigaciones sobre la materia y la implementación de nuevas técnicas y operadores que

podrán ser incluidos de forma rápida y sencilla.

Estas metodologías a pesar de proponer un método depurado de búsqueda, siguen requiriendo una

cantidad notable de recursos computacionales, concretamente de consumo de procesador. Por ello un

factor muy importante y que va de la mano de los algoritmos evolutivos es el de paralelismo y

compu-tación de altas prestaciones. Además la propia formalización y estructura de los algoritmo evolutivos los

(30)

Para demostrar las ventajas de este nuevo modelo lo aplicaremos para solucionar problemas clásicos

en la literatura, como el problema del Traveling Salesman Problem (TSP) y problemas de optimización

de funciones matemáticas clásicas en el mundo de la computación evolutiva.

1.3.

Estructura de la memoria

La memoria del proyecto está organizada en seis partes. Tras esta primera parte de introducción y

objetivos del proyecto tenemos la parte dedicada al estado de la cuestión, desglosada en dos capítulos.

El primero está dedicado al estado de la cuestión en lo relativo a computación de altas prestaciones y el

segundo dedicado a la teoría de algoritmos evolutivos.

La siguiente parte, compuesta por los capítulos cuatro y cinco, desglosa al detalle el diseño y

desarro-llo de la solución propuesta para la implementación del algoritmo MOS. En este apartado se expondrán

detalladamente todas las decisiones de diseño adoptadas así como la arquitectura del sistema. En

con-creto, se detallarán especialmente el diseño y funcionamiento de las técnicas MOS, los genomas MOS,

la conversión entre genomas y la serialización de las poblaciones MOS.

En la cuarta parte se hará un detallado análisis de los resultados obtenidos sobre diferentes

proble-mas de búsqueda y optimización para varias combinaciones de parámetros aplicando el algoritmo MOS.

Asimismo, se hará una comparativa de los mejores enfoques para solucionar cada problema. A

continua-ción, en el capítulo séptimo, se presentarán las conclusiones y las futuras líneas de investigación en este

campo. Por último, se incluirá el capítulo de anexos, con información complementaria al desarrollo de

(31)

Parte II

(32)
(33)

Capítulo 2

Computación de altas prestaciones con

arquitecturas paralelas

En este capítulo se da una visión general de la evolución de las arquitecturas paralelas para

compu-tación de altas prestaciones, centrándonos fundamentalmente en los multicomputadores y su aplicación

en el campo de la computación científica. Se analizará también la necesidad de estos sistemas, las

ten-dencias actuales y las últimas tecnologías para llevar a cabo desarrollos con programación paralela.

2.1.

Introducción

Una de las constantes a lo largo de la historia de la informática ha sido la necesidad de incrementar

constantemente la potencia de cálculo disponible. La implementación de algoritmos y aplicaciones cada

vez más complejas y con un coste computacional más alto, ha permitido ir resolviendo problemas más

complejos y llegar a soluciones más precisas manejando grandes volúmenes de datos.

La ejecución de aplicaciones científicas de cálculo intensivo ha puesto de manifiesto la necesidad

de unas arquitecturas hardware de alto rendimiento capaces de satisfacer los fuertes requisitos de estas

aplicaciones.

A pesar de la vertiginosa evolución de las arquitecturas hardware, y de la continua capacidad de la

industria de ofrecer sistemas con mayor capacidad de cálculo, el desarrollo de software con mayores

necesidades de recursos siempre es mucho más rápido. Esta relación no lineal entre el hardware ofrecido

por los fabricantes y las necesidades del software desarrollado en el mundo científico plantea la necesidad

de proponer nuevos modelos capaces de adaptarse a las necesidades de los científicos e ingenieros de una

(34)

Frente a la imposibilidad de construir procesadores con capacidad suficiente para llevar a cabo estas

tareas con un coste y en un tiempo razonables, es necesario buscar alternativas. Ante esta perspectiva

la solución más razonable es la introducción de paralelismo. El paralelismo se basa en la ejecución

simultánea en varios procesadores, bien en la misma o en diferentes máquinas. El reparto del trabajo entre

varias instancias permite avanzar mucho más rápido para alcanzar los objetivos y, por tanto, aumentar

notablemente las prestaciones.

El concepto de paralelismo es una revolución en contraposición con la computación secuencial

tra-dicional, ya que permite abaratar de manera espectacular los costes y afrontar retos antes inimaginables,

proporcionando unos sistemas de enormes prestaciones que permiten a los científicos e ingenieros

reali-zar nuevos experimentos y diseños.

Por otro lado, la computación paralela plantea nuevos y complejos retos para los programadores, que

deben de amoldarse a la nueva filosofía y abandonar su concepción de programas secuenciales. Se debe

ser capaz de fragmentar las tareas a realizar de manera adecuada para que éstas puedan ejecutarse de

for-ma paralela. Esto supone una for-mayor complejidad en el diseño y entran en juego nuevas preocupaciones

que antes no teníamos como el acceso a los datos, la sincronización de los procesos o el intercambio de

información. Todo esto hace muy compleja la programación paralela y es necesario dominar la

arquitec-tura y las herramientas existentes para obtener realmente una ganancia y sacar el máximo partido a las

arquitecturas paralelas.

2.2.

Arquitecturas paralelas: Taxonomía

Existen varios modelos de arquitecturas paralelas. Una de las clasificaciones clásicas y generalmente

aceptada es la realizada por el profesor de la Universidad de Stanford Michael J. Flynn en 1972 [11]. Esta

clasificación conocida como “la taxonomía de Flynn” diferencia entre paralelismo de datos y paralelismo

de instrucciones.

El paralelismo de datos se refiere a la posibilidad de realizar una misma operación sobre varios

datos de forma paralela, mientras que el paralelismo de instrucciones hace referencia a la posibilidad de

ejecutar de forma paralela diferentes instrucciones.

La tabla 2.1 muestra las posibles combinaciones al hacer paralelismo de datos y de instrucciones

(35)

2.2. Arquitecturas paralelas: Taxonomía SISD MISD C on ju nt o D at os Conjunto Instrucciones UP SISD C on ju tn o D at os Conjunto Instrucciones UP UP MISD SIMD MIMD C on ju nt o D at os Conjunto Instrucciones UP UP UP UP SIMD C on ju nt o D at os Conjunto Instrucciones UP UP UP UP UP UP UP UP MIMD

Figura 2.1:Taxonomía de Flynn

Single Instruction Single Data(SISD): Modelo secuencial tradicional. Las instrucciones se eje-cutan secuencialmente y cada instrucción se ejecuta sobre un solo dato.

Single Instruction Multiple Data(SIMD): Ejecución secuencial de instrucciones, pero aplicando cada instrucción a un conjunto de datos de forma paralela. Un ejemplo de esto es Altivec, un

conjunto de instrucciones para coma flotante desarrollado por Apple, IBM y Motorola y que sigue

la filosofía SIMD. Otro ejemplo es la tecnología SSE introducida, también para cálculos en coma

flotante, por Intel en su familia de procesadores Pentium III como extensión para el juego de

instrucciones MMX. Otro campo en el que se ha explotado esta tecnología es el de los procesadores

gráficos, de gran auge en los últimos años.

Multiple Instruction Single Data(MISD): Este modelo tiene poco sentido en computación tra-dicional. Su desarrollo se limita al campo de la investigación, por ejemplo en los procesadores

(36)

Multiple Instruction Multiple Data(MIMD): Estas arquitecturas son las más interesantes y las que implementan la mayoría de computadores paralelos. La idea es tener varios procesadores que

ejecuten instrucciones de forma paralela sobre conjuntos de datos independientes entre sí.

Como hemos comentado anteriormente, las arquitecturas más interesantes y extendidas, en lo que se

refiere a computadores paralelos, son las MIMD. Ahora bien, dentro de este contexto paralelo existen

diferencias sustanciales entre distintas máquinas que lo implementan. La característica más importante a

estudiar es el tipo de mapa de memoria utilizado y cómo accedemos a él.

Inicialmente distinguiremos entre multiprocesadores, si se trata de máquinas con un único espacio

de direcciones, y multicomputadores, si son máquinas con múltiples espacios de direcciones, uno para

cada procesador.

2.2.1. Multiprocesadores

Los multiprocesadores son máquinas con varias unidades de proceso pero una memoria común. El

acceso de todos los procesadores a esta memoria común hace muy compleja la construcción de estas

má-quinas, elevando su coste, pero le da la facilidad al programador de ver un único mapa y poder compartir

la memoria. El acceso a esta memoria se puede realizar fundamentalmente de dos formas:

UMA(Uniform Memory Access): La memoria es compartida y el acceso es uniforme desde todos

los procesadores.

NUMA(Non Uniform Memory Access): Todos los procesadores pueden acceder a toda la

memo-ria, pero no de manera uniforme. Dependiendo de la memoria a la que queramos acceder tendrá

un coste u otro.

UMA NUMA

Bus de conexión

M M M M

UP UP UP UP

UMA

Bus de conexión

M M M M

UP UP UP UP

NUMA

(37)

2.2. Arquitecturas paralelas: Taxonomía

Las máquinas Non Uniform Memory Access (NUMA) son más escalables y, generalmente,

imple-mentan complejos algoritmos de coherencia de caches cc-NUMA, cuyo objetivo es minimizar los accesos

a la parte de memoria más costosa de acceder. Algunas máquinas NUMA que han tenido éxito comercial

son el SGI Origin y el Cray T3.

Las máquinas Uniform Memory Access (UMA) son más costosas de implementar y menos

esca-lables. No es habitual que tengán muchos procesadores. En la literatura se usan indistintamente los

términos UMA y Symmetric Multi-Processing (SMP) para referirse a este tipo de arquitecturas.

Algu-nos ejemplos de máquinas UMA son los nodos de máquinas SMP de Sun o HP y, más recientemente,

procesadores comerciales como los Intel Core y los AMD Athlon entre otros.

2.2.2. Multicomputadores

La característica fundamental de los multicomputadores es que son arquitecturas con memoria

dis-tribuida no compartida, de manera que cada procesador tiene su propio mapa de memoria. El conjunto

de procesador, memoria y, en ocasiones, dispositivos de entrada/salida se denomina nodo. Los nodos se

comunicarán entre sí mediante un sistema o red de interconexión a través de paso de mensajes.

Multicomputador

Red de conexión

M

UP

Multicomputador

M

UP M

UP M

UP

Figura 2.3:Arquitectura de un multicomputador

Los multicomputadores son más sencillos de construir y más escalables que los multiprocesadores,

pero incorporan la dificultad a la hora de programar aplicaciones, ya que la paralelización la debe realizar

el programador explicitamente mediante paso de mensajes, con toda la complejidad que esto implica.

En muchos casos, uno o varios de los nodos de un multicomputador son, a su vez, multiprocesadores

con varios núcleos.

(38)

2.2.2.1. Clúster

Una evolución del concepto de multicomputador son los clúster. Un clúster es un multicomputador

cuyos nodos son computadores de componentes comunes y relativamente baratos y que están conectados

por una red de alta velocidad mediante un switch. El objetivo de un clúster es obtener una máquina de

mayor potencia a partir de computadores no necesariamente muy potentes y a un precio razonable. Al

usar componentes más o menos comunes y habituales en el mercado, el coste de un clúster en relación a

la potencia de cálculo obtenida es bajo.

El modelo de programación de un clúster es necesariamente paso de mensajes entre nodos a través

de la red. Para ello existe una capa de software intermedio, o middleware de comunicaciones, que facilita

esta labor. Un clúster es tremendamente escalable y muy flexible, ya que se le pueden añadir o sustituir

nodos con relativa facilidad. No es necesario que todos los nodos de un clúster tengan la misma

arqui-tectura, ni siquiera es necesario que tengan el mismo sistema operativo. Esto es lo que se denomina un

clúster heterogéneo, frente al concepto de clúster homogéneo, donde sí son iguales todos los nodos.

2.2.2.2. Magerit

Un ejemplo de un clúster lo podemos ver en la figura 2.4. Este clúster, llamado Magerit, es una

máquina perteneciente al Centro de Supercomputación y Visualización de Madrid (CeSViMa), el centro

de supercomputación ubicado en la Universidad Politécnica de Madrid (UPM). Magerit es actualmente

la segunda máquina más potente de España y, en el momento de su instalación, llegó a ser la 34a más

potente del mundo. Es un clúster compuesto por 1204 nodos eServer BladeCenter JS20 y JS21, con dos y

cuatro procesadores IBM PowerPC single-core 970FX de 64 bits a 2’2 GHz. Están conectados mediante

una red Myrinet de alta velocidad. Magerit tiene una potencia pico de 20 Tflops aproximadamente.

(39)

2.3. Topologías y redes de interconexión

2.3.

Topologías y redes de interconexión

Uno de los aspectos clave en computación paralela es la comunicación entre los nodos. Al trabajar de

forma paralela en muchas ocasiones los nodos van a necesitar intercambiarse información y comunicarse

unos con otros para sincronizarse. La necesidad de obtener un alto rendimiento nos obliga a tener muy en

cuenta los tiempos y las latencias de comunicación, ya que podrían suponer un enorme cuello de botella.

Aunque tuviésemos muchos nodos muy potentes, si la red de comunicaciones no es capaz de realizar el

intercambio de información a una velocidad razonable, perderíamos gran parte de nuestra potencia de

cálculo. En la sección 2.3.1 repasaremos algunas de las tecnologías más relevantes para interconexiones

de multicomputadores y multiprocesadores.

Otro aspecto importante, sobre todo en multiprocesadores, es la topología de la red de interconexión

que diseñemos, ya que podemos tener modelos en los que no todos los procesadores estén directamente

conectados entre sí. Esto da lugar a diferentes topologías o formas de colocar y conectar nuestros nodos.

La topología más adecuada dependerá del número de nodos que tengamos, la velocidad de nuestra red y

el tipo de aplicaciones paralelas que vayamos a ejecutar.

En la literatura existen dos conceptos que nos ayudan a definir las topologías de nuestra red:

Anchura de bisección:Número mínimo de conexiones a cortar para obtener dos sistemas iguales.

Ancho de banda en bisección: Ancho de banda a través de los nodos cortados al obtener la anchura de bisección.

Estos conceptos caracterizan una topología de red y nos permiten estudiar facilmente cual será su

escalabilidad.

Existen multitud de topologías de red. La figura 2.5 recoge algunas de las topologías más clásicas

y que más se implementan en sistemas reales. La topología que elijamos definirá en gran medida las

características de nuestra red y, por lo tanto, influirá de manera significativa en el rendimiento y coste

de nuestro sistema. Para profundizar más en este tema, se puede consultar alguna de las referencias

existentes en la literatura, de entre las que destacan las obras de P. de Miguel [8] y D. Culler[5], más

(40)

Lineal Malla Anillo Árbol

Cubo 3D Estrella Conexión completa Barras cruzadas

Figura 2.5:Topologías de red

2.3.1. Tecnologías de interconexión

Algunas de las tecnologías de interconexión más relevantes, tanto por la tecnología aportada como

por su éxito comercial, se detallan a continuación, junto con algunas de sus carácterísticas más

intere-santes.

SCI:Scalable Coherent Interface. Estándar IEEE desde 1992, conforma una estructura en anillo de

1, 2 ó 3 dimensiones. Es capaz de mantener la coherencia entre las caches de los procesadores que

conecta, de manera que podría sustituir a un bus de un multiprocesador, aunque su uso en clústers

es sólo como conexión entre nodos. Puede ser la base para implementar una memoria compartida

virtual. Alcanza velocidades de 2500 MB/s obteniendo latencias de 1-2 microsegundos, por lo que

es adecuado para envío de mensajes cortos.

QsNet:QsNet: Quadrics. Evolución de las redes de interconexión de las Meiko Computing Sur-face, usadas después en las Alphaserver SC. Se compone de un switch (de 16 ó 128 puertos)

y tarjetas adaptadoras PCI que alcanzan hasta 350 MB/s. Se desarrolló una segunda versión en

2003, llamada QsNet II, que alcanza hasta 1.3 GB/s con conexiones bidireccionales y latencias

entre 3 y 5 microsegundos. Internamente usa una topología fat tree.

(41)

2.4. Rendimiento en computación paralela

principales características es que el procesamiento de las comunicaciones de red se realiza a través

de chips integrados en las tarjetas de red, liberando a la cpu de esta labor. Sus características hacen

que sea altamente escalable, por lo que es la tecnología más utilizada en grandes clústers.

Infiniband: Puede ser usado para conexiones entre subsistemas o entre procesadores. Hoy por hoy tiene un precio alto, pero es muy versátil ya que tiene especificaciones para conexiones de

cobre y de fibra óptica. Está compuesto por switches de 8 a 124 puertos, que proporcionan 7

microsegundos de latencia en mensajes cortos. Permite diferentes configuraciones y puede llegar

a velocidades de 12 GB/s. Las especificaciones son libres, no está ligado directamente a ninguna

empresa.

2.4.

Rendimiento en computación paralela

Cuando paralelizamos un programa o algoritmo para ejecutarlo en un multiprocesador o un

multi-computador nuestro principal objetivo es acelerar su ejecución sacando el máximo partido posible a la

máquina que tenemos por debajo. Existen diferentes medidas que nos ayudan a estudiar el rendimiento

real de nuestro programa, así como las posibilidades de paralelizarlo y obtener un mejor rendimiento.

2.4.1. Factor de aceleración: Speedup

El speedup es la principal medida que nos indica la ganancia que obtenemos con nuestra

paraleli-zación. Se calcula como el cociente entre el tiempo de cálculo en una máquina secuencial y el mismo

cálculo en una máquina paralela con determinado número de procesadores. Obviamente, el speedup de

un programa variará de una máquina paralela a otra, y en función de cómo se haya realizado la

paraleli-zación. Cuanto más alto sea el speedup, más ganancia habremos obtenido con nuestra paraleliparaleli-zación.

Speedup=Tsecuencial Tparalelo

(2.1)

Otra medida de interés relacionada con el speedup es la eficiencia. Se define como el cociente entre

el speedup y el número de procesadores en los que ejecutamos, y su valor está comprendido entre 0 y 1.

E f iciencia= Speedup Nprocesadores

(2.2)

Nos interesa que la eficiencia tenga un valor lo más cercano a 1 que sea posible, aunque

general-mente obtendremos un valor menor. En el hipotético caso de que la eficiencia fuera 1, significaría que

(42)

los procesadores. Llegar a esta situación es casi imposible. La dificultad de repartir equitativamente el

tiempo de proceso estriba en gran medida en cómo sea nuestro algoritmo y lo fácil que sea de paralelizar.

Suele ser muy habitual que haya partes de nuestro algoritmo que no podamos paralelizar de ninguna

ma-nera. Al margen de esto, el hecho de paralelizar siempre supone una mínima carga adicional en concepto

de sincronización y comunicación entre nodos y, en ocasiones, intercambios de datos de un tamaño más

que considerable. Esto hace que nuestra paralelización nunca vaya a ser perfecta, en el sentido de que

frecuentemente obtendremos un rendimiento inferior a 1. En cualquier caso, el objetivo siempre ha de

ser obtener una eficiencia lo más alta posible.

Por otro lado existen algunos casos, bastante atípicos, en los que debido a la propia naturaleza del

algoritmo o a la arquitectura de la máquina que utilicemos, es posible alcanzar una ganancia mayor que

uno. Esta circunstancia se denomina superlinealidad y se da en circunstancias muy concretas.

2.4.2. Ley de Amdahl

En 1967 el ingeniero Gene Amdahl definió una fórmula, conocida como la Ley de Amdahl [1], que

probaba que, a partir de cierto punto, el hecho de agregar más procesadores a una máquina paralela no

producía una mejora significativa en la velocidad de ejecución.

La Ley de Amdahl distingue entre las partes de un programa que son paralelizables (Pparalelizable)

y las que son intrínsecamente secuenciales (Psecuencial) y nunca podremos paralelizar. De manera que

siempre se cumple:

Pparalelizable+Psecuencial=1 (2.3)

Si sustituimos en la fórmula 2.1 del speedup y simplificamos usando la fórmula 2.3 obtenemos:

Speedup=Pparalelizable+Psecuencial Psecuencial+

Pparalelizable

Nprocesadores

= 1

Psecuencial+

Pparalelizable

Nprocesadores

(2.4)

La fórmula 2.4 calcula el factor máximo de aceleración en función de las partes de nuestro programa

(43)

2.4. Rendimiento en computación paralela 20.00 18.00 16.00 14.00 12.00 10.00 8.00 6.00 4.00 2.00 0.00 S p e e d u p

1 2 4 8 16 32 64

1 2 8 2 5 6 5 1 2 1 0 2 4 2 0 4 8 4 0 9 6 8 1 9 2 1 6 3 8 4 3 2 7 6 8 6 5 5 3 6

Número de procesadores

Ley de Amdahl

Porcentaje Paralelización 50% 75% 90% 95% 100%

Figura 2.6:Ley de Amdahl

En la figura 2.6 podemos ver gráficamente el speedup que obtendríamos, en función del número

de procesadores, para programas con diferentes porcentajes de código paralelizable. Como se puede

observar claramente, llega un momento en que, para un determinado número de procesadores, no es

posible incrementar más el speedup, ya que éste se estanca. Esto sucede en todos los casos salvo en

el trazo pintado en amarillo que representa problemas que son 100 % paralelizables. En este caso la

relación entre el número de procesadores y el speedup es totalmente lineal (los ejes están escalados) y

crece constantemente.

Existen pocos problemas que sean 100 % paralelizables y que alcancen speedups lineales. Los que lo

son se definen por su naturaleza intrínsecamente paralela en la que el problema se puede descomponer en

tareas totalmente independientes y, generalmente, la solución final es una agregación de las soluciones

parciales. Algún ejemplo de este tipo de problemas es la búsqueda de claves criptográficas por fuerza

bruta o la búsqueda de jugadas en un programa de ajedrez.

2.4.3. Ley de Gustafson

En contraposición a la Ley de Amdahl (sección 2.4.2) el ingeniero y científico John L. Gustafson hizo

una revisión de la misma en 1988, lo que dio lugar a lo que se conoce como la Ley de Gustafson [14].

Guftanson afirmaba que los cálculos de Amdahl eran incorrectos, porque éste consideraba constantes

Psecuencial yPparalelizable, lo que no es cierto en un programa que ejecuta de forma paralela. Lo correcto

era usar los valores medios en un sistema paralelo, que se definen comoPsecuencial0 yPparalelizable0 . Según

(44)

tanto, deberíamos de reevaluar la fórmula del factor de aceleración definida por Amdahl (fórmula 2.4),

lo que da lugar a la nueva Ley de Gustafson, que es lineal:

Speedup=P

0

secuencial+P

0

paralelizableNprocesadores

Psecuencial0 +Pparalelizable0 =Nprocesadores+ (1−Nprocesadores)P

0

secuencial (2.5)

En cualquier caso, tanto la Ley de Amdahl como la de Gustafson son simplificaciones. La

escala-bilidad y el factor de aceleración de un sistema paralelo hay que estudiarlos para una implementación

concreta de un algoritmo sobre una máquina dada.

2.5.

Proceso de paralelización: Principios de diseño

Dado un programa secuencial, el hecho de paralelizarlo es una tarea muy laboriosa y compleja que

requiere una buena metodología y planificación.

En primer lugar es necesario definir una serie de conceptos que fijen el marco de trabajo del proceso

de paralelización:

Tarea:Es la unidad mínima de cómputo. Se ejecuta siempre secuencialmente y no se puede des-componer más. Existe concurrencia sólo entre tareas. Pueden existir tareas de grano fino frente a

tareas de grano grueso.

Proceso:Entendemos el proceso como una entidad abstracta que realiza las tareas asignadas a los procesadores. Los procesos se comunican y sincronizan para realizar las tareas.

Procesador:Máquina física sobre la que se ejecuta un proceso.

Una vez hechas estas definiciones podemos comprender cómo debemos diseñar la paralelización.

Para poder afrontar con una mínimas garantías la labor de paralelización de un programa es necesario

llevar a cabo las siguientes cuatro fases [5]:

Descomposición:Partición de la carga computacional secuencial en tareas.

Asignación:Reparto de las tareas a los procesos.

Orquestación:Coordinación de los accesos necesarios a los datos, la comunicación y sincroniza-ción entre los procesos.

(45)

2.5. Proceso de paralelización: Principios de diseño

La figura 2.7 muestra gráficamente las diferentes etapas del proceso de paralelización y la relación

entre ellas.

Figura 2.7:Etapas del proceso de paralelización

La tabla 2.1 recoge los principales objetivos que se espera conseguir en cada una de estas etapas con

el fin de obtener el mejor rendimiento posible en la paralelización que vamos a realizar:

Etapa Dependencia de la arquitectura Principales objetivos

Descomposición Probablemente no Análisis de la concurrencia.

Asignación Probablemente no Balanceo de carga. Minimizar comunicación.

Orquestación Sí Reducir comunicación para acceso a datos.

Reducir comunicación y sincronización.

Pla-nificar tareas para evitar dependencias.

Despliegue Sí Explotar al máximo la localidad en la

topolo-gía de red.

Tabla 2.1:Etapas de la paralelización y sus objetivos

A continuación comentaremos en profundidad cada una de estas etapas del proceso de paralelización.

2.5.1. Descomposición

Para esta primera fase de descomposición debemos centrarnos inicialmente en el algoritmo. Nuestro

(46)

núme-ro de tareas, y buscando que sean descomposiciones de grano lo más fino posible. Esto nos dará más

flexibilidad para la agrupación posterior.

Existen dos enfoques a la hora de afrontar esta tarea:

Descomposición del dominio: En primer lugar, determinamos una partición de los datos, para asociar después unos cálculos sobre estos datos.

Descomposición funcional: Primero descompondremos los cálculos para asignarles depués los datos que vayan a necesitar.

Debemos tener cuidado en la redundancia tanto en el cómputo como en el almacenamiento de los

datos, ya que en la mayoría de los casos supone una penalización, aunque en ocasiones pueda ser

benefi-cioso. De la misma manera debemos de poner especial énfasis en minimizar, en la medida de lo posible,

las dependencias entre tareas, para evitar sincronizaciones y comunicaciones. Tenemos que procurar

también que las tareas representen cantidades similares de trabajo.

El límite de la concurrencia que podemos obtener viene definido por la ley de Amdahl (sección

2.4.2).

La figura 2.8 muestra un ejemplo de un algoritmo implementado de forma secuencial que podemos

dividir en dos fases. En este ejemplo, la segunda fase depende de los resultados de la primera. Podemos

paralelizar cada fase independientemente y obtener una aceleración casi lineal.

(47)

2.5. Proceso de paralelización: Principios de diseño

2.5.2. Asignación

La etapa de asignación pretende asignar las tareas, definidas en la fase anterior, a los procesos.

De-bemos buscar equilibrio en la carga de trabajo que asignemos a cada proceso, así como procurar reducir

al máximo la comunicación y sincronización necesarias entre procesos.

A la hora de equilibrar la carga, debemos tener en cuenta algoritmos de planificación por si fuese

ne-cesario equilibrar las funciones. Equilibrar la carga puede ser una tarea muy compleja si hemos definido

pocas tareas, si éstas son de grano gordo o si tienen muchas dependencias entre ellas.

Para reducir la comunicación debemos procurar asignar tareas que ejecutan concurrentemente a

di-ferentes procesos, y asignar tareas que se comunican muy frecuentemente a un mismo proceso.

Fundamentalmente existen dos esquemas de asignación:

Asignación estática: Definimos la asignación de los procesadores al comienzo de la ejecución. Esto no nos supone muchas sobrecargas más que al comienzo, pero tiene el problema de que el

equilibrado de la carga puede ser malo y no podremos hacer ya nada para corregirlo en tiempo de

ejecución.

Asignación dinámica: La asignación se va ajustando a medida que ejecutamos en función de la carga de cada nodo del sistema. Permite hacer un balanceo adecuado de la carga, pero nos

introduce retardos debido al coste en tiempo y consumo de procesador que supone hacer esta

asignación dinámica.

2.5.3. Orquestación

El objetivo de la orquestación es estructurar la comunicación entre los procesos, estableciendo la

sin-cronización entre los mismos. También es necesario definir la manera en la que nombramos y manejamos

los datos por parte de los distintos procesos.

En cuanto a la comunicación entre procesos, existen varios patrones de comunicación que la definen,

y que repasaremos en las siguientes subsecciones.

2.5.3.1. Comunicación unicast vs. broadcast

Cuando hablamos de comunicación unicast a nivel de proceso nos referimos a la comunicación que

se establecerá entre un proceso y algunos de los otros procesos que se estén ejecutando en ese momento.

A su vez, estos procesos se comunicarán con otros procesos. La clave de este paradigma unicast frente

(48)

mucho más escalable, aunque en ocasiones más costoso, en contraposición con la comunicación global o

broadcast, donde un proceso se ha de comunicar con todos los demás. Existen mecanismos, generalmente

hardware, que nos permiten sacar un gran rendimiento de la comunicación broadcast, en comparación al

envío unicast de un número similar de mensajes.

(a)Comunicación unicast (b)Comunicación broadcast

Figura 2.9:Comunicación unicast vs. broadcast

2.5.3.2. Comunicación estructurada vs. no estructurada

La comunicación estructurada se refiere a si el patrón de comunicación que implementarán los

pro-cesos responde a una topología o estructura determinada, con el fin de alcanzar la mejor solución. Por el

contrario, cuando usamos comunicación no estructurada la solución que buscamos no depende de la

es-tructura de comunicación entre nodos y sus comunicaciones se realizan en ocasiones de forma aleatoria,

o al menos no siguen una estructura definida.

(a)Comunicación estructurada (b)Comunicación no estructurada

(49)

2.5. Proceso de paralelización: Principios de diseño

2.5.3.3. Comunicación estática vs. dinámica

Este patrón de comunicación simplemente define si la comunicación será la misma durante toda la

ejecución o irá cambiando en función de las necesidades o reglas que se hayan definido. Una

comunica-ción estática es más fácil de definir, mientras que una comunicacomunica-ción dinámica puede resultar más difícil

de implementar y de equilibrar.

2.5.3.4. Comunicación síncrona vs. asíncrona

Cuando al enviar información de un proceso a otro esperamos a que el receptor reciba el mensaje

estamos hablando de comunicación síncrona, los dos procesos se sincronizan en la comunicación, ya

que uno espera al otro. Si enviamos el mensaje y seguimos ejecutando sin esperar la confirmación de

recepción del otro proceso estamos hablando de comunicación asíncrona.

En el caso de la comunicación asíncrona tiene la ventaja de que los procesos no se quedan bloqueados

en la comunicación, ya que envían la información y siguen ejecutando. Sin embargo, con este mecanismo

no podremos sincronizar unos procesos con otros y, en ocasiones, esto es necesario.

(a)Comunicación síncrona (b)Comunicación asíncrona

Figura 2.11:Comunicación síncrona vs. asíncrona

2.5.4. Despliegue

El objetivo de esta etapa es asignar los procesos a los procesadores en los que ejecutarán. Sólo tiene

sentido cuando paralelicemos en multicomputadores. En ocasiones puede ser necesario migrar procesos

de un procesador a otro, pero esto puede suponer muchos problemas, ya que la memoria es local a cada

(50)

2.6.

Herramientas de programación paralela

Existen diferentes herramientas que facilitan la labor del programador a la hora de implementar

una paralelización de un programa. Las diferentes herramientas se orientan a un modelo y arquitectura

diferentes, siendo más adecuada una u otra dependiendo del caso. Estas herramientas consisten en un

Application Programming Interface (API), que nos da una capa de abstracción (de alto o bajo nivel,

según veremos) y que es utilizada por el programador para paralelizar su algoritmo.

En este caso vamos a analizar las herramientas High Performance Fortran (HPF), Message Passing

Interface (MPI) y Open Multi Processing (OMP), ya que son las tres más relevantes en cuanto a su

historia, lo extendido de su uso y filosofía de operación.

La tabla 2.2 muestra una breve comparativa de las principales característias de cada una de estas tres

tecnologías.

HPF MPI OMP

Año primera versión 1993 1994 1997

Versión actual HPF-2 MPI-2 OMP 3.0

Lenguajes soportados Fortran Fortran, C/C++, Java... Fortran, C/C++

Modelo programación Directivas Llamadas biblioteca Directivas

Arquitecturas SIMD, MIMD... SIMD, MIMD... SMP

Uso y repercusión Disminuyendo. Muy extendido. En auge.

Extensiones MPI I/O

Tabla 2.2:Comparativa de herramientas para programación paralela

2.6.1. HPF

Se trata de un lenguaje de programación completo basado en Fortran. Su objetivo es la programación

paralela en máquinas de tipo SIMD con paralelismo de datos. Fue pensado para cálculo intesivo

cien-tífico. Tiene un buen rendimiento y es compatible con Fortran 95 (F95). La mayoría de las llamadas se

hacen en forma de directivas en el programa fuente.

El proceso de compilación es complejo y el rendimiento obtenido es difícil de prever. La primera

versión surgió en 1993 en la Universidad de Rice y su desarrollo hoy en día va por la versión 2.0. Al

estar pensado para programar en lenguaje Fortran su uso no está excesivamente extendido, fuera de los

(51)

2.6. Herramientas de programación paralela

2.6.2. MPI

MPI surge como un acuerdo entre empresas, universidades y centros de investigación para definir

una interfaz común de paso de mensajes. MPI se ha convertido en el estándar de facto del modelo de

paso de mensajes orientado a multicomputadores. Una alternativa, anterior a MPI, es Parallel Virtual

Machine (PVM), se trata de una serie de herramientas software que permiten la paralelización. PVM

Apareció en 1989 y fue desarrollado por el Oak Ridge National Laboratory.

La primera versión de MPI apareció en 1994. En 1997 fue lanzada la versión MPI-2, que todavía hoy

sigue vigente y que incorporó la entrada salida paralela con MPI I/O y otras mejoras muy significativas.

En un entorno MPI el programador debe ocuparse de casi todo. MPI únicamente proporciona una

capa de abstracción sobre el hardware, pero dejando al programador la responsabilidad de gestionar la

lógica del intercambio de mensajes.

Existen bindings de MPI para múltiples lenguajes, entre los que se encuentran álgunos de los más

difundidos como Fortran, C, C++, Java o Python. El uso de MPI está extendido en prácticamente todos

los entornos multicomputador tanto a nivel empresarial como en universidades y centros de investigación.

La biblioteca Genetic Algorithm Estimation of Distribution Algorithms Library (GAEDALib), con

la que se ha llevado a cabo este trabajo, se basa en tecnología MPI para soportar el paso de mensajes

entre nodos.

MPI ha triunfado en el sector de los multicomputadores y de la informática general. Esto es debido

al gran esfuerzo que se hizo por parte de las principales empresas y entidades investigadores en ese

momento por conseguir un estándar de facto, pero también se debe a las bondades del diseño de MPI,

que reseñamos a continuación:

Estandarización.

Portabilidad: multiprocesadores, multicomputadores, redes, entornos heterogéneos...

Buenas prestaciones.

Amplia funcionalidad.

Existencia de implementaciones libres.

Una de las características mas atractivas de MPI es que existen varias implementaciones libres

(52)

MPICH:Fue la primera implementación que se llevó a cabo, realizada por el Argonne National Laboratory y la Universidad del Estado de Mississippi. Hoy en día ya está disponible MPICH2

que implementa MPI-2.

LAM/MPI:Implementado por el Ohio Supercomputing Center, hoy en día se ha combinado con otros esfuerzos para crear el proyecto OpenMPI que implementa nuevas mejoras.

También existen optimizaciones de alguna implementaciones realizadas por algunos fabricantes. Por

ejemplo la implementación Message Passing Interface Chameleon (MPICH)-GM realizada por la

em-presa Myricom para sus redes Myrinet.

2.6.2.1. Funcionamiento de MPI

Cualquier implementación de MPI consiste en una biblioteca que nos ofrece un interfaz común de

llamadas. Estas llamadas nos permiten realizar todas las acciones necesarias para gestionar el paso de

mensajes. Podemos agrupar las llamadas en cuatro categorías:

1. Llamadas utilizadas para inicializar, administrar y finalizar comunicaciones.

2. Llamadas utilizadas para transferir datos entre un par de procesos.

3. Llamadas para transferir datos entre varios procesos.

4. Llamadas utilizadas para crear tipos de datos definidos por el usuario.

2.6.3. OMP

OMP es un API que permite paralelismo en máquinas con memoria compartida. OMP se basa en una

arquitectura de hilos que realizan tareas paralelas sobre la misma memoria, como muestra la figura 2.12.

Por eso es un requisito que por debajo tengamos memoria compartida aunque cada hilo pueda ejecutarse

en un procesador diferente.

(53)

2.6. Herramientas de programación paralela

OMP tiene un modelo de programación basado en directivas que son interpretadas por el compilador.

OMP da una visión de más alto nivel que otras aproximaciones paralelas como MPI, ya que descarga al

programador de la labor de gestionar la lógica de comunicación. La configuración está controlada por

variables de entorno.

OMP surgió en 1997 inicialmente como extensión para el lenguaje fortran y más adelante soportando

también C y C++. Actualmente está disponible la versión 3.0 con múltiples mejoras y extensiones.

El modelo de programación paralela que propone OMP ofrece muchas ventajas al programador:

Simplicidad, no es necesario el paso explícito de mensajes.

El tratamiento y descomposición de los datos es realizado automáticamente por las directivas.

Introducción de paralelismo con muy poco esfuerzo y modificaciones en el código fuente.

Posibilidad de compilación para ejecución secuencial sin modificar el código. Las directivas OMP

son ignoradas por el compilador.

La introducción de directivas no afecta en general a la estructura de nuestros algoritmos, lo que

minimiza la posibilidad de cometer errores.

Posibilidad de hacer paralelismo de grano fino y de grano grueso.

Existen implementaciones de algunos fabricantes muy optimizadas, como la de IBM.

Sin embargo, este modelo también presenta algunos incovenientes:

La concurrencia sólo es eficiente en plataformas SMP.

Necesidad de un compilador específico con soporte para OMP.

La escalabilidad está limitada por la arquitectura de la memoria.

La captura de errores no es fiable.

No es posible sincronizarse entre un subconjunto de hilos.

Obtener una buena optimización requiere conocimientos de la arquitectura.

En resumen, todas estas tecnologías y herramientas vistas a lo largo de este capítulo suponen un

soporte para el desarrollo y ejecución de nuevas aplicaciones de cómputo intensivo. En nuestro caso el

hecho de disponer de este tipo de arquitecturas nos permitirá llevar a cabo la implementación y pruebas

de las aportaciones que propone este proyecto al campo de los algoritmos evolutivos, un área que

tradi-cionalmente ha requerido de gran potencia de cálculo para obtener resultados interesantes en problemas

(54)
(55)

Capítulo 3

Algoritmos evolutivos

En este capítulo se da una visión general de la teoría de algoritmos evolutivos desarrollada en los

últimos 40 años. Definiremos todos los términos utilizados en este campo. Igualmente, comentaremos

algunos ejemplos de problemas clásicos que se solucionan con este tipo de algoritmos.

Nos centraremos fundamentalmente en los algoritmos genéticos, analizando algunos de los

ope-radores clásicos. En general, definiremos su funcionamiento y la aproximación que hace la biblioteca

GAEDALib [9] al respecto.

También nos interesará conocer la aproximación de los algoritmos EDA y comentaremos brevemente

su estructura basada en redes y métodos de aprendizaje y simulación.

Por último, analizaremos algunos aspectos sobre la ejecución de algoritmos evolutivos paralelos y

sobre la hibridación de múltiples algoritmos evolutivos.

3.1.

Introducción

Los algoritmos evolutivos surgen con la necesidad de desarrollar nuevas técnicas avanzadas de

op-timización que sean capaces de resolver problemas complejos de gran magnitud en tiempos razonables.

Surgen dentro del campo de la Inteligencia Artificial (IA) como alternativa de optimización heurística.

Su funcionamiento se basa en una búsqueda guiada pero aún así requieren sistemas de gran capacidad de

cómputo. Su buen rendimiento es posible, en muchos casos, gracias al uso de técnicas de paralelismo,

tal y como se vio en el capítulo 2.

Inspirados en la evolución natural, definida por Charles Darwin en el siglo XIX en su teoría de la

evolución [6], estos algoritmos pretenden superar las limitaciones de los algoritmos de optimización

(56)

La aplicación de este enfoque a muchos problemas de optimización en el mundo real ha demostrado

que son una alternativa muy interesante que en muchas ocasiones ha conseguido soluciones de alta

calidad con un alto rendimiento.

Los algoritmos evolutivos suponen un proceso iterativo que consiste en evolucionar o hacer crecer

una población, de manera similar al proceso natural. Los individuos de la población codifican las

solu-ciones a nuestro problema, y son seleccionados en base a su adecuación a la solución óptima buscada,

este comportamiento se inspira en el modelo natural.

Uno de los aspectos más importantes, a la hora de plantearnos solucionar un problema con un

algo-ritmo evolutivo, es encontrar una buena representación para codificar el problema y modelizarlo de la

manera adecuada. Se ha demostrado empíricamente en los últimos años que elegir una representación

adecuada es fundamental para obtener la solución esperada [17].

Del mismo modo, serán decisivos los operadores y parámetros que decidamos utilizar en nuestro

algoritmo para conseguir el éxito.

Los algoritmos evolutivos no dejan de ser una gran familia de algoritmos. Dentro de esta familia

podemos encontrar diferentes aproximaciones que han ido surgiendo a lo largo de la historia y desarrollo

de este campo de investigación. Los pilares de esta taxonomía fueron definidos de forma paralela durante

los años 70 por diferentes científicos e ingenieros que han pasado a la historia como los padres de la

computación evolutiva.

Por citar algún nombre, podemos destacar al profesor de psicología de la Universidad de Míchigan,

J.H. Holland [15], considerado uno de los padres de la computación evolutiva; el profesor de la

Uni-versidad de Dortmund Hans-Paul Schwefel que desarrolló la teoría para la estrategia evolutiva [30]; el

profesor I. Rechenberg de la Universidad Técnica de Berlín que aplicó las estrategias evolutivas al campo

de la aeronáutica [26] y [27]; y, por último, el profesor L.J. Fogel, padre de la programación evolutiva

que también investigó en el campo de la aeronáutica y la cibernética [12].

Algunas de las aproximaciones tradicionales mas relevantes dentro del mundo de los algoritmos

evolutivos las podemos ver en la tabla 3.1. En ocasiones, simplemente difieren en los detalles de la

Referencias

Documento similar

María. Parece haber con centra do toda su atención e n ellas. Mas no es a sí. L aurcz la desvía con brusq ue da d y María Teresa se promete solemnemen te descubrir el mundo que

Un método de estudio aparte de ser una herramienta muy útil al momento de estudiar también nos ayuda a agilizar nuestra mente y tener una buena memoria para futuro?. Palabras

Lo que observamos en las teorías freudianas y nietzscheanas sobre los individuos, los grupos y las relaciones entre las personas es igualmente observable y

o Si dispone en su establecimiento de alguna silla de ruedas Jazz S50 o 708D cuyo nº de serie figura en el anexo 1 de esta nota informativa, consulte la nota de aviso de la

La aplicación debe ser capaz de prever errores simples en el sistema dado antes de comenzar la simulación, como, por ejemplo, parámetros necesarios no especifcados o falta de

El desarrollo de una conciencia cáritas es esencial para identificar cuando un momento de cuidado se convierte en transpersonal, es necesaria para identificar

El quincenario de los frailes de Filipinas, condena para el Archipiélago los propósitos de nivelación jurídica que para todo territorio español, peninsular o ultramarino, se

Es importante mencionar, que en los últimos 5 años, China ha venido mostrando un gran avance en la industria textil y de la confección, ingresando en mercados como Europa,