Logo Studenta

Estudio-de-sistemas-multicore-para-computo-de-alto-rendimiento

¡Este material tiene más páginas!

Vista previa del material en texto

UNIVERSIDAD NACIONAL AUTÓNOMA DE MÉXICO 
POSGRADO EN CIENCIA E INGENIERÍA DE LA COMPUTACIÓN 
 
 
 
“ESTUDIO DE SISTEMAS MULTICORE 
PARA CÓMPUTO DE ALTO RENDIMIENTO” 
 
 
T E S I S 
 
QUE PARA OBTENER EL GRADO DE: 
 
MAESTRA EN CIENCIAS 
(COMPUTACIÓN) 
 
P R E S E N T A: 
 
CLARA VICENTE HERNÁNDEZ 
 
DIRECTOR DE TESIS: 
 HÉCTOR BENÍTEZ PÉREZ. 
 
 
México, D.F. 2010. 
 
 
 
 
UNAM – Dirección General de Bibliotecas 
Tesis Digitales 
Restricciones de uso 
 
DERECHOS RESERVADOS © 
PROHIBIDA SU REPRODUCCIÓN TOTAL O PARCIAL 
 
Todo el material contenido en esta tesis esta protegido por la Ley Federal 
del Derecho de Autor (LFDA) de los Estados Unidos Mexicanos (México). 
El uso de imágenes, fragmentos de videos, y demás material que sea 
objeto de protección de los derechos de autor, será exclusivamente para 
fines educativos e informativos y deberá citar la fuente donde la obtuvo 
mencionando el autor o autores. Cualquier uso distinto como el lucro, 
reproducción, edición o modificación, será perseguido y sancionado por el 
respectivo titular de los Derechos de Autor. 
 
 
 
AGRADECIMIENTOS: 
 
Quiero expresar mi más profundo agradecimiento a: 
 
Mi director de tesis: Dr. Héctor Benítez Pérez. Por su apoyo y confianza depositados a mi 
persona. Por su tiempo y dedicación para realizar este trabajo. 
Mis sinodales: 
Dr. Fabián García Nocetti. 
Dr. Jorge Luis Ortega Arjona. 
Dr. Gerardo Vega Hernández. 
Ing. Mario Rodríguez Manzanera. 
Por sus valiosas aportaciones y comentarios. 
Mis padres y amigos: por su gran apoyo moral en los momentos difíciles. 
Mi esposo: por su apoyo moral y económico. 
Mis hijos: Mary José y José Ángel. Para educarlos en el ejemplo. 
 
Y en memoria de mi querido Dr. Tchijov. 
 
ÍNDICE: 
 
CAPÍTULO 1 INTRODUCCIÓN 
1.1 Introducción. 1 
1.2 Caso de estudio. 4 
1.3 Objetivo general. 4 
1.4 Metas. 5 
1.5 Contribución y Relevancia. 5 
 
CAPÍTULO 2 GENERALIDADES 
2.1 Introducción al capítulo. 7 
2.2 Sistemas con memoria compartida. 7 
2.3 Sistemas con memoria distribuida. 12 
2.4 Características de las arquitecturas referidas. 16 
2.5 Sistema Multicore. 17 
2.6 Métricas de desempeño en multiprocesamiento. 17 
2.7 Ley de Amdahl . 19 
2.8 Resumen de capítulo. 21 
 
CAPÍTULO 3 ARQUITECTURA DEL SISTEMA 
3.1 Introducción al capítulo. 23 
3.2 Descripción de la arquitectura de hardware. 23 
3.3 Descripción de la arquitectura de software. 25 
3.4 OpenMP. 29 
3.5 Nivel de paralelismo. 30 
3.6 Directivas y construcciones de sincronización. 32 
3.7 MPI. 33 
3.8 Llamadas utilizadas para iniciar, administrar y finalizar comunicaciones 34 
3.9 Llamadas utilizadas para transferir datos entre dos procesos. 35 
3.10 Llamadas utilizadas para transferir datos entre varios procesos. 36 
3.11 Ventajas. 38 
3.12 Desventajas. 38 
3.13 Resumen de capítulo. 39 
 
CAPÍTULO 4 CASO DE ESTUDIO 
4.1 Introducción al capítulo. 40 
4.2 Descripción de la red neuronal. 40 
4.3 Caso de estudio 1 Implementación híbrida. 44 
4.4 Caso de estudio 2 Implementación en sistemas multicore. 52 
4.5 Caso de estudio 3 Implementación en serie. 55 
4.6 Resumen de de capitulo. 57 
 
CAPÍTULO 5 MÉTRICAS Y ANÁLISIS DE RESULTADOS 
5.1 Introducción al capítulo. 58 
5.2 Aplicación de métricas de desempeño en sistemas multicore 58 
5.3 resumen de capítulo. 68 
 
 
 
CAPÍTULO 6 CONCLUSIONES 70 
APÉNDICE. 
Código Hibrido. Utilizando las interfaces de programación MPI y OpenMP. 73 
Código serial y/o Paralelo. 84 
Referencias Bibliográficas 91 
ÍNDICE DE FIGURAS. 
1.1 Ejecución de instrucciones de manera secuencial. 2 
1.2 Ejecución de instrucciones de manera simultánea sobre diferentes CPU’s 3 
2.1 Arquitectura de procesadores con memoria compartida. 8 
2.2 Diseño de una región paralela en sistemas con memoria compartida. 10 
2.3 Arquitectura de un Sistema Distribuido. 12 
2.4 Comunicación a través de sockets. 15 
2.5 Caso ideal de aceleración para n procesadores. 19 
3.1 Arquitectura híbrida de multiprocesamiento. 24 
3.2 Sección Crítica. 27 
3.3 Estados de los procesos en una sección crítica. 28 
4.1 Algoritmo general de la Art. 43 
4.2 Matriz de pesos de la red neuronal (Recurso compartido). 46 
4.3 Paralelización de la red ART2A. 47 
4.4 Vectores de dimensionalidad X valores mayores 
y posiciones correspondiente 48 
4.5 Un ciclo completo de entrenamiento de la red ART2A en paralelo. 50 
4.6 Hilos en acción. 52 
 
4.7 Región paralela con hilos. 53 
4.8 (a) Flujo de ejecución de hilos de manera paralela. 55 
4.8 (b) Flujo de ejecución de hilos anidados. 55 
4.9 Diagrama de flujo de la red ART2A de manera secuencial. 56 
5.1 Aceleración de entrenamiento de la ART2A en 4 procesadores. 64 
5.2 Tiempos de ciclo de ejecución del entrenamiento de la ART2A. 67 
 
ÍNDICE DE TABLAS 
5.1 Resultado de entrenamiento de la red neuronal ART2Acon varios hilos 
 Para un valor de RO=0.4 59 
 
5.2 Resultado de entrenamiento de la red neuronal ART2Acon varios hilos 
 Para un valor de RO=0.1 61 
5.3 Resultados de entrenamiento de la red neuronal ART2A para 
3 y 4 procesadores 63 
5.4 Tiempo de ejecución para 10 procesos en 4 procesadores 65 
 
1 
 
 
CAPÍTULO 1. 
1.1 INTRODUCCIÓN: 
Dada la necesidad de contar con máquinas de mayor potencia de proceso, hoy en día es 
común encontrarse con computadoras que incluyen más de un procesador en su 
arquitectura. El utilizar varios procesadores no es nuevo, ya que desde hace tiempo 
existen tarjetas madre que permiten la interacción de varios procesadores (normalmente 
dos, cuatro u ocho) en un solo equipo, de la misma manera como se pueden agrupar 
computadoras en clúster de modo que actúen como si fuera una única computadora. Lo 
que resulta realmente novedoso es que ahora los procesadores estén encapsulados en un 
único chip (procesadores denominados multicore). El motivo es principalmente 
económico, ya que resulta más barato producir un circuito integrado con dos 
microprocesadores (dos cores), que dos procesadores independientes en una tarjeta 
madre. Por otra parte, al construirse sistemas multicore se ahorra energía, se produce 
menor calentamiento y al reducirse las distancias se obtiene un mejor rendimiento 
(performance), que en un solo procesador de rendimiento semejante. Con un solo 
procesador, una aplicación exigente pone a trabajar al tope al procesador, si existen 
diversos cores, sólo trabajará al máximo el core que soporte esa aplicación, los otros 
cores irán mas desahogados. Sin embargo, con los avances tecnológicos en la integración 
de procesadores no solo existen cambios en su arquitectura o en su comunicación interna 
sino que también conllevan un cambio en nuestra manera de pensar, ya que desde el 
inicio de la era de la computadora (1945) a la fecha, los computadores secuenciales han 
sido diseñados basados en el modelo introducido por John von Newman [18, 20, 21], el 
cual consiste en una unidad central de proceso (CPU), una memoria, y unidades de 
entrada y salida, debido a ello, el software y su programación se han orientado 
tradicionalmente a la computación en serie o secuencial, de este modo es natural que los 
algoritmos y programas de computadoras fueran primeramente formulados de acuerdo a 
2 
 
tal concepto. Aún antes de que la primera computadora electrónica fuera construida el 
concepto matemático de algoritmo fue definido como una secuencia finita de operaciones 
[22]. En una máquina secuencial, el procesador ejecuta una secuencia de instrucciones y 
operan con una secuencia de datos (fig. 1.1) [35]. Para su procesamiento unproblema es 
dividido en un conjunto de instrucciones, y su velocidad es limitada por dos factores: la 
capacidad de obtener y ejecutar dichas instrucciones y la velocidad de transferencia entre 
memoria y CPU. 
 
 Instrucciones 
 . . . 
 
 N/N 3/N 2/N 1/N 
fig. 1.1 Ejecución de instrucciones de manera secuencial. 
 
 
Con el desarrollo de diversas tecnologías de interconexión entre unidades (unidades 
funcionales redundantes, pipeline, paralelismo, hiperthreding, multicore, entre otras) y la 
existencia de aplicaciones (científicas, técnicas, medicas, etc.) que requieren procesar 
grandes cantidades de datos o realizar un alto número de operaciones, se hace necesario 
el empleo de múltiples procesadores que cooperen en su ejecución, de manera que cada 
aplicación se divide en un número arbitrario de subprogramas (subconjuntos de 
instrucciones, o tareas independientes), con un fin determinado y estos a su vez pueden 
ejecutarse simultáneamente sobre diferentes procesadores en el mismo instante de 
tiempo[19] (fig. 1.2 ). Los procesadores se comunican unos con otros para intercambiar 
y combinar los resultados parciales obtenidos durante su ejecución. A este modelo 
tecnológico de procesamiento alternativo se le denomina cómputo en paralelo [22,3] y 
pretende conseguir que N procesadores trabajen de forma conjunta para resolver un 
problema N veces más rápido que en un único procesador [3]. En lugar de procesar 
instrucción por instrucción como en una computadora tradicional, en un sistema de 
procesamiento paralelo varias instrucciones se ejecutan simultáneamente, con el 
CPU Problema 
3 
 
propósito de acelerar la velocidad de procesamiento y aumentar así la eficiencia de 
cómputo [19,3]. No obstante, se debe considerar que el uso de múltiples procesadores en 
un mismo sistema computacional introduce requerimientos adicionales, es decir, para que 
varios procesadores puedan trabajar juntos ejecutando el mismo programa 
computacional, estos deben ser capaces de compartir datos y comunicarse cada uno con 
el otro, por lo que debe de haber una sincronización para así evitar condiciones de 
competencia. 
 Problema Instrucciones 
 
 . . . 
 . . . 
 
 . . . 
 
 . . . 
 N/N 3/N 2/N 1/N 
fig. 1.2 Ejecución de instrucciones de manera simultánea sobre diferentes CPUs 
 
 
El presente trabajo está dirigido hacia el estudio y análisis de la programación paralela, a 
tal fin se hace uso de un clúster de computadoras, cada una de ellas con arquitectura 
multicore. Para la programación de estas dos arquitecturas se utiliza programación 
híbrida, haciendo uso de las interfaces de programación MPI y OpenMP. MPI 
distribuye la carga entre las computadoras que conforman el clúster (comunicación inter 
procesos) y OpenMP maneja los cores en una misma máquina. Cabe hacer notar que la 
programación de estas dos arquitecturas es completamente diferente y requiere de 
conceptos con dos visiones diferentes (se explicaran en capitulo 2). 
CPU 1 TAREA 1 
 
TAREA 2 
. 
. 
. 
TAREA n 
… 
CPU n 
CPU 2 
4 
 
1.2 CASO DE ESTUDIO. 
El caso de estudio es el entrenamiento de una red neuronal llamada ART2A. Es una red 
de entrenamiento no supervisado, cuya estructura consiste de dos redes neuronales 
llamada ART [15, 30]. Su objetivo es la detección, localización y clasificación de 
defectos y fallas internas. La información proporcionada a la red para su entrenamiento, 
es a través de una base de datos que contiene información suficiente de cada tipo de 
defecto. La forma de entrenamiento es comparar las entradas presentes con categorías 
aprendidas seleccionadas. Las categorías aprendidas se encuentran almacenadas en una 
estructura multidimensional matricial llamada W [15], que es compartida por diferentes 
procesos. Esta es actualizada o modificada de acuerdo a un parámetro de vigilancia (ρ), 
que expresa el grado mínimo de similitud entre el vector de entrada y cualquier categoría 
definida en W. Si el grado de similitud entre la entrada y cualquier categoría es mayor o 
igual que ρ, entonces el prototipo actual es elegido para representar el grupo contenido. 
Esto dice que la red logra resonancia. Si el grado de similitud es menor que ρ entonces 
otra categoría debe ser seleccionada y comparada con el vector I (es el vector 
normalizado bajo la norma Euclidiana de los datos a ser estudiados). Si cualquier 
prototipo o categoría es alcanzado por el grado de similitud entonces el vector I debe ser 
agregado a W como un nuevo prototipo. 
1.3 OBJETIVO GENERAL. 
El objetivo de este trabajo es estudiar el desempeño de sistemas con arquitectura 
multicore, con base en requerimientos de acceso restringido en recursos comunes a los 
procesadores, usando sistemas paralelos a través de una red de cómputo. 
Se requiere distribuir el procedimiento de entrenamiento de una red neuronal de tipo 
ART2A [15] en una arquitectura de multiprocesamiento que consta de N máquinas con 
características Multicore. El sistema está diseñado para N procesos1 que comparten una 
Red Neuronal ART2A. Este recurso debe ser actualizado o modificado dependiendo de 
los resultados del entrenamiento de la propia red en cada uno de los procesos. Para medir 
 
1 Proceso. Un proceso se define como un programa en ejecución [18], y de una forma un poco más 
precisa como la unidad de procesamiento gestionada por el sistema operativo [35]. 
5 
 
el desempeño de un programa ejecutándose en este tipo de arquitecturas se hace uso de la 
Ley de Amdahl para sistemas distribuidos [23] y de algunas de las funciones de métricas 
de tiempo proporcionadas en las librerías del lenguaje de programación C++. 
1.4 METAS. 
 Desarrollar un sistema de doble multicore con base a una red tipo Ethernet y dos 
sistemas Multicore. Esto es conectando dos máquinas con arquitectura core a 
través de una red de computadoras. 
 Crear un algoritmo paralelo híbrido en lenguaje de programación C++, en el que 
se implementarán las librerías de MPI y OpenMp. 
 Distribuir la carga de trabajo de manera equitativa entre los procesadores 
tomando en cuenta el acceso a memoria de estos (multiprocesadores o multi-
computadores). 
 Evaluar el desempeño de estos sistemas así como determinar potenciales 
condiciones de competencia entre los procesos. 
1.4 CONTRIBUCIÓN Y RELEVANCIA. 
En el desarrollo de la presente tesis se abordó el problema de paralelización del método 
de entrenamiento no supervisado ART2A para redes neuronales [15, 30]. Como es bien 
sabido este tipo de entrenamiento tiene importantes aplicaciones, por ejemplo, en teoría 
del control, robótica, reconocimiento de patrones, entre otras. 
El enfoque con el que se abordó este problema fue mediante el uso de 
multiprocesamiento híbrido en el que se emplean los esquemas de paralelización de 
memoria compartida (SMP) [3,5] y paso de mensajes en arquitectura distribuida (MPI) 
[13,14]. 
Para determinar el rendimiento de ejecución del programa híbrido en múltiples 
procesadores se utilizaron funciones de métricas de tiempo proporcionadas en las 
librerías del lenguaje de programación C++ [1]. 
6 
 
Las afirmaciones que podemos deducir de los resultados obtenidos en los experimentos 
realizados con la implementación mencionada son los siguientes: 
1. En el algoritmo ART2A existe una gran cantidad de dependencia de datos 
inherentes al mecanismo de aprendizaje en el entrenamiento. Esto induce al 
hecho de que en la paralelización de dicho algoritmo siempre exista una porción 
de código no paralelizable, que aunque se encontró como una fracción pequeña, 
esta porción impide escalar el procedimiento de paralelización a un número 
arbitrario deprocesadores [11, 23]. Tenemos entonces que el uso de varios 
procesadores y procesos no es garantía de un manejo eficiente en el 
procesamiento de la información. De hecho el análisis de resultados obtenidos 
durante la ejecución de los programas en donde empleamos ambas arquitecturas 
(explicadas en las secciones 1.2 y 1.3) determinará la mejor aproximación para 
la paralelización en cuanto al flujo propio de la información. 
2. Cuando la dimensión de los vectores de entrenamiento es alta, entonces la 
dependencia de datos en las operaciones internas del procedimiento ART2A 
disminuye, por ejemplo, la multiplicación de matriz por vector, producto interno, 
y normalización de vectores, pueden entonces descomponerse en procesos 
paralelos obteniendo así un mejor rendimiento que en el caso secuencial. 
Remarcamos el hecho de que esto ocurre cuando la dimensión de los vectores es 
alta, pues de otra manera, el tiempo de procesamiento de las instrucciones 
adicionales para conseguir paralelismo superará al tiempo ganado por el proceso 
de paralelización. 
 
En resumen, pudimos observar en los experimentos, que aunque es posible paralelizar el 
procedimiento ART2A es necesario verificar si la dimensionalidad de los vectores de 
entrenamiento, así como también el número de vectores clasificados en W. La dimensión 
de estos nos permitirá mejorar o no el rendimiento del proceso. En resumen: se pudo 
observar que el tamaño de los datos a paralelizar es un factor muy importante a 
considerar en la programación paralela. 
 
7 
 
CAPÍTULO 2. GENERALIDADES: 
2.1 INTRODUCCIÓN AL CAPÍTULO. 
En este capítulo se describen las características de las tecnologías empleadas para 
abordar el cómputo paralelo, la forma en que se comunican e intercambian información, 
así como también la manera de sincronización en ambos arquitecturas. Se explica lo que 
es un sistema multicore y algunas de las métricas de desempeño para evaluar el 
rendimiento de un programa al ejecutarlo en múltiples procesadores. 
 
Para implementar el modelo de cómputo paralelo se consideran dos tipos de 
arquitecturas ampliamente utilizadas, las cuales difieren en la forma en la que se 
comunican los procesadores [22, 6]: 
 
Sistemas con memoria compartida: En una aplicación paralela lo que se pretende es 
ejecutar un programa más rápidamente que en una versión secuencial, para ello lo que se 
hace es utilizar varios procesos, que ejecutan partes de un mismo programa, de tal manera 
que el tiempo empleado en la ejecución paralela de todos ellos sea menor que el tiempo 
empleado por un único proceso en resolver el problema [18]. 
 
Sistemas con memoria distribuida: En una aplicación distribuida existen diferentes 
procesos, que ejecutan distintas partes de un programa, dichos procesos colaboran y se 
comunican entre sí para alcanzar un mismo objetivo. 
2.2 SISTEMAS CON MEMORIA COMPARTIDA “MULTIPROCESADOR” 
Consiste en un número de procesadores idénticos dentro de una misma máquina 
compartiendo una memoria principal global [3,32]. (fig. 2.1). 
8 
 
 
 
 
 BUS 
 
 
 . . . 
 
(fig. 2.1). Arquitectura de procesadores con memoria compartida. 
 
El acceso a la memoria principal global es a través de un bus. El bus es el canal de 
comunicación para llevar a cabo las operaciones de solicitud de memoria simultánea por 
varios procesadores y asegurar que todos los procesadores sean justamente atendidos con 
un mínimo retardo de acceso. El encargado de arbitrar las tareas, sus prioridades y 
recursos disponibles es el Sistema Operativo. Una de las mayores dificultades en 
sistemas de multiprocesamiento de memoria compartida es la competencia por recursos, 
principalmente por el acceso a memoria entre los procesadores [3,27]. Esta se 
incrementa conforme el número de procesadores sea mayor y más procesos activos se 
tengan en el sistema. A mayor grado de multiprogramación se presentan mayores 
necesidades de memoria. Cuando varios procesadores intentan accesar a la memoria 
compartida dentro del un periodo de tiempo pequeño, la memoria no le es posible 
atender todas las peticiones simultáneamente, por lo que algunos de los procesadores 
tendrán que esperar mientras otros son atendidos [3, 6, 21]. 
La programación eficiente en este tipo de arquitecturas se realiza mediante el control de 
hilos paralelos [3, 6,35]. Un hilo (thread) es un flujo de control independiente dentro de 
un proceso. Es esencialmente una ruta de ejecución a través del código de programa en 
proceso (fig. 2.2). Los hilos dentro de un mismo proceso suelen compartir los recursos 
asignados al proceso al cual pertenecen. La manera de identificar un hilo dentro de un 
proceso es por su identificador (ID) que es un valor entero único dentro de cada proceso. 
MEMORIA 
COMPARTIDA 
PROCESADOR 
2 
PROCESADOR 
1 
PROCESADOR 
n 
9 
 
Dos hilos en diferentes procesos pueden tener el mismo número de ID. Sin embargo, cada 
uno realizará operaciones diferentes. 
Con procesadores multicore se reparten los diferentes hilos entre los cores, de modo que 
varias aplicaciones avanzan a la vez, permaneciendo menos tiempo en espera, logrando 
con ello agilizar la ejecución de una tarea [3,22,35]. Debido a que los hilos dentro de un 
mismo proceso comparten las mismas direcciones físicas de memoria, éstos comparten 
las mismas estructuras y datos a nivel proceso. Sin embargo, cada hilo tiene información 
propia que no comparte con otros hilos. Esta información se refiere fundamentalmente 
al contexto de ejecución, pudiéndose destacar los siguientes datos: 
 Contador de programa. 
 Tope de pila. 
 Estado de registros. 
 Estado del hilo (thread). 
 
El estado de un hilo (listo, activo, bloqueado) en cualquier instante está definido por el 
proceso en memoria. Cada procesador ejecuta un hilo diferente, aunque cualquier hilo 
podría estar corriendo en cualquier procesador en cualquier momento. En un sistema de 
dos procesadores cada procesador puede estar corriendo diversos hilos, los cuales pueden 
pertenecer al mismo proceso o a diferentes procesos. Un hilo o proceso no está atado o 
ligado a un procesador particular. Esto lo determina el Sistema Operativo. 
Para un uso eficiente en esta arquitectura se propone el empleo de múltiples hilos 
(multithreads MT), ya que si se tiene un solo hilo esperando por los recursos del sistema 
no se hace uso adecuado del hardware. Si el hilo tiene que hacer cálculos extensivos 
entonces todas las demás aplicaciones tendrían que esperar. El usar multihilos puede 
remover los cuellos de botella. Un programa MT comienza con un hilo inicial, 
denominado hilo maestro. Este hilo inicial crea nuevos hilos, que son considerados hilos 
esclavos. (fig. 2.2) 
 
10 
 
 Región Paralela 
 Hilo Maestro Hilo Maestro 
 
Fig. 2.2 Diseño de una región paralela. El hilo maestro crea hilos esclavos 
 
Los nuevos hilos corren una rutina independiente y suministran otras corrientes de 
instrucciones operativas en el mismo espacio de direccionamiento de datos. El Sistema 
Operativo se ocupa de asegurar que cada hilo se mantenga activo. Esto lo hace con la 
asistencia del hardware y una gran cantidad de registros de transacciones. Cuando el 
temporizador del hardware decide que un proceso ha estado ejecutándose por suficiente 
tiempo entonces ocurre una interrupción1. El Sistema Operativo salva el estado actual del 
hilo mediante la copia de los registros del hilo desde la pila hacia una estructura de 
contexto y la guarda para su uso posterior. Para cambiar hacia diferentes hilos, el Sistema 
Operativo direcciona el procesador a la memoria correspondiente al hilo del proceso, 
luego restaura los registros que fueron guardados en la estructura de contexto en un 
nuevo hilo. A este proceso es llamado intercambio de contexto (contextswich) 
[4,5,18,35]. No hay que olvidar que el crear hilos y hacer intercambios de contexto le 
toma una cantidad finita de tiempo al procesador por lo que al momento de crear hilos se 
debe tomar en cuenta cuantos hilos se van a manejar en la aplicación paralela y asegurar 
que no exista una sobrecarga en intercambio de contextos. De no tomar en cuenta esto, 
se puede consumir mayor tiempo con múltiples hilos al ejecutar el código. Todo esto 
debido al intercambio de contexto y a la introducción de instrucciones propias del modelo 
paralelo que no son necesarias en el programa secuencial. Cabe mencionar que la rapidez 
en el intercambio de contexto varía de una máquina a otra, dependiendo de la velocidad 
 
1 A nivel físico, una interrupción se solicita activando una señal que llega a la unidad de control. 
Ante esta solicitud, la unidad de control realiza un ciclo de aceptación de interrupción. Este ciclo 
se lleva a cabo cuando termina la ejecución de la instrucción máquina que se está ejecutando y 
consiste en las siguientes operaciones: 1. Salva algunos registros del procesador, como son el de 
estado y el contador de programa (CP). 2. Eleva el nivel de ejecución pasándolo al núcleo 3. Carga 
un nuevo valor en el CP por lo que pasa a ejecutar otro programa. 
 
11 
 
de memoria y el número de registros que copiar. Por lo regular el tiempo de conmutación 
varía entre 1 y 1000 microsegundos [35]. 
Otro aspecto es el control de condiciones de competencia. Una condición de 
competencia ocurre cuando varios hilos compiten por un mismo recurso. Para prevenir 
dichas condiciones y evitar que los hilos sean interrumpidos mientras se encuentran 
haciendo alguna operación cuya integridad es indispensable en un procedimiento, es 
necesario protegerlos. Esto se hace mediante mecanismos de sincronización, que no son 
más que la manera de coordinar los hilos para que puedan trabajar en conjunto. La 
sincronización entre hilos se realiza mediante variables globales compartidas que pueden 
ser coordinadas usando secciones críticas, semáforos o mutex. Una Sección Crítica (SC) 
es una porción de código que accesa a un recurso compartido y que solo a un hilo a la vez 
se le permite entrar a ejecutar dicho código, convirtiéndose en una operación atómica2. 
Cada hilo debe pedir permiso para entrar a la sección crítica, mediante algún fragmento 
de código que se denomina de forma genérica entrada en la sección crítica. Cuando un 
hilo sale de la sección crítica debe indicarlo mediante otro fragmento de código, que se 
denomina salida de sección critica. Mediante la utilización de Mutex (exclusión mutua) si 
un hilo se encuentra en la SC, ningún otro podrá entrar. Un semáforo es un objeto que 
permite controlar el acceso a un recurso compartido. Está compuesto de un contador y de 
una cola de espera. Cuando el contador es positivo, indica que existen recursos 
disponibles. Cuando es negativo indica la cantidad de procesos o hilos que esperan por el 
recurso [3, 4, 18.]. 
Un ejemplo de condición de competencia ocurre cuando varios hilos hacen despliegue de 
datos en pantalla. Debido a que el Sistema Operativo sólo le proporciona cierta cantidad 
de tiempo a cada hilo, los hilos compiten por el recurso. Un determinado hilo empezará a 
hacer su despliegue, pero al transcurrir el tiempo asignado para su ejecución, si aún no 
ha terminado de hacer su despliegue, el control del dispositivo de despliegue le será 
 
2 Una operación atómica es una porción de código que no puede ser interrumpida mientras esta en 
ejecución [6]. 
 
 
12 
 
quitado y se transferirá a otro hilo, teniendo como resultado una potencial inconsistencia 
en los datos desplegados. 
2.3 SISTEMAS CON MEMORIA DISTRIBUIDA “MULTICOMPUTADORA”. 
Un sistema Distribuido se define como un grupo de computadoras separadas 
físicamente.Cada máquina tiene su propia memoria y sólo se comunican entre ellas por 
medio de mensajes a través de una red de computadoras [3,18,35]. Cada una de las 
computadoras conectadas a la red posee sus componentes de hardware y software 
que el usuario percibe como un solo sistema. (fig. 2.3), 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fig. 2.3 Arquitectura de un Sistema Distribuido. Cada máquina tiene su propio 
procesador (P) y memoria (M) y se comunican por medio de mensajes a través de una red 
de computadoras. 
PASE DE MENSAJES 
COMUNICACIÓN A 
TRAVÉS DE LA RED 
P 
M 
P 
M 
P 
M 
P 
M 
P 
M 
P 
M 
http://es.wikipedia.org/wiki/Computadores
13 
 
Un Sistema Distribuido se define según dos puntos de vista: 
1. Desde un punto de vista físico, un sistema distribuido es un conjunto de 
procesadores (posiblemente heterogéneos), sin memoria ni reloj común, que se 
encuentran conectados a través de una red de interconexión. fig. 1.4 [3, 21, 22]. 
 
2. Desde el punto de vista lógico, un sistema distribuido es un conjunto de procesos 
que no comparten recursos y que se ejecutan en una o más computadoras y que 
colaboran y se comunican entre ellos mediante el intercambio de mensajes. 
 
De estos dos puntos de vista se desprende que uno de los aspectos más importantes de un 
Sistema Distribuido es comunicar diferentes procesos entre sí con independencia del 
lugar donde se ejecuten. 
La plataforma fundamental sobre la que se construyen los sistemas distribuidos es una 
red de computadoras, lo cual permite que puedan compartir diferentes recursos como son: 
periféricos, datos o incluso procesadores. Una red de computadoras es un sistema de 
comunicación compuesto por una serie de componentes hardware y software que 
proporcionan los servicios necesarios para que los procesos que ejecutan en las distintas 
computadoras puedan comunicarse entre sí. En este tipo de arquitectura, puesto que los 
diferentes procesadores no comparten una memoria común, la única forma de 
comunicación posible es mediante el intercambio de mensajes. Un mensaje es un objeto 
lógico que se intercambia entre dos o más procesos. Para transmitir un mensaje a través 
de una red de interconexión es necesario descomponerlo en una serie de paquetes. Un 
paquete es la unidad de información que se intercambian dos dispositivos de 
comunicación. Para que la comunicación se lleve a cabo, es necesario el empleo de 
protocolos de comunicación. Un protocolo es un conjunto de reglas e instrucciones que 
gobiernan el intercambio de paquetes y mensajes. 
Utilizando pase de mensajes como mecanismo de comunicación entre procesos, 
únicamente existir un enlace de comunicación entre ellos. Los procesos se comunican 
mediante dos operaciones básicas: 
14 
 
 send(destino, mensaje): envía un mensaje al proceso destino. 
 receive(origen, mensaje): recibe un mensaje del proceso origen. 
La comunicación entre los procesos es de manera directa o indirecta, es decir, deben tener 
una forma de referirse a cada uno de ellos. Sin embargo, cualquiera que sea el método 
utilizado, el paso de mensajes siempre se realiza en exclusión mutua. 
La comunicación entre dos procesos es síncrona cuando los dos procesos han de ejecutar 
los servicios de comunicación al mismo tiempo, es decir, el emisor debe estar ejecutando 
la operación send y el receptor ha de estar ejecutando la operación receive. La 
comunicación es asíncrona en caso contrario. 
Existen tres combinaciones más habituales que implementan los distintos tipos de paso de 
mensajes: 
 Envío y recepción con bloqueo: En este caso, tanto el emisor como el receptor se 
bloquean hasta que tenga lugar la entrega del mensaje. Esta es una técnica de 
paso de mensajes totalmente síncrona. 
 Envío sin bloqueo y recepción con bloqueo: Esta es la combinación generalmente 
más utilizada. El emisor no se bloquea hasta que tenga lugar la recepción y por 
tanto puede continuar su ejecución. El procesoque espera el mensaje, sin 
embargo, se bloquea hasta que llega. 
 Envío y recepción sin bloqueo: Se corresponde con una comunicación 
totalmente asíncrona en la que ningún proceso espera. 
Existen dos modelos muy utilizados para el desarrollo de aplicaciones cliente-servidor en 
sistemas distribuidos: Los sockets y las llamadas a procedimientos remotos. 
1. Los sockets aparecieron en 1981 en la versión BSD 4.2 de UNIX [18]. Un socket 
es una abstracción que representa un extremo en la comunicación bidireccional 
entre dos procesos. Ofrece una interfaz para acceder a los servicios de red en el 
nivel de transporte de los protocolos TCP/IP. Utilizando esta interfaz, dos 
procesos que deseen comunicarse deben crear un socket o extremo de 
15 
 
comunicación cada uno de ellos. Cada socket se encuentra asociado a una 
dirección y permite enviar o recibir datos a través de él. (fig. 2.4) 
 Máquina A Máquina B 
 
 
 
 
 
 
2.4 Comunicación a través de sockets 
 
En una llamada a procedimiento remoto (RPC, Remote Procedure Call, Birrel 1984) 
[33,34], el programador no necesita preocuparse de cómo realiza la comunicación entre 
procesos. Simplemente realiza llamadas a procedimientos que serán ejecutados en 
computadoras remotas. En este sentido el programador desarrolla sus aplicaciones en 
forma convencional descomponiendo su software en una serie de procedimientos bien 
definidos. En una RPC, el proceso que realiza la llamada empaqueta los argumentos en 
un mensaje, se los envía a otro proceso y espera resultado. Por su parte, el proceso que 
ejecuta el procedimiento extrae los argumentos del mensaje, realiza la llamada de forma 
local, obtiene el resultado y se lo envía de vuelta al proceso que realizó la llamada. Este 
proceso es totalmente transparente al usuario. 
La sincronización de procesos en sistemas distribuidos es más complicada que en 
sistemas con memoria compartida, debido a que los procesos no comparten una memoria 
ni un reloj global común. Esto dificulta la forma de ordenar los eventos que ocurren en un 
sistema distribuido y la resolución de problemas de sincronización clásicos como los 
descritos en la sección 2.2. En un sistema con memoria compartida, la ordenación de 
eventos es un problema trivial puesto que existe un reloj físico común que permite 
proceso 
 
 
socket 
 
NÚCLEO 
envía 
proceso 
 
 
socket 
 
NÚCLEO 
recibe 
R E D 
16 
 
determinar que evento ocurrió antes que el otro. Esto no ocurre de igual manera en un 
sistema distribuido puesto que cada computadora dispone de su propio reloj. Una forma 
de ordenar eventos en sistemas distribuidos que carecen de un reloj global es utilizar el 
concepto de relojes lógicos propuesto por Lamport en 1978. Este concepto se basa en la 
relación de precedencia definida también por Lamport en 1978. Según Lamport, no es 
necesario recurrir a un reloj físico global para asegurar el orden de eventos en un sistema 
distribuido. Basta con asignar unas determinadas marcas lógicas de tiempo a los eventos 
[25]. 
2.4 CARACTERÍSTICAS DE LAS ARQUITECTURAS REFERIDAS. 
 La diferencia más importante entre un sistema distribuido y un sistema con 
memoria compartida es el acceso a memoria y, por ente, la comunicación entre 
procesos. 
 Los sistemas con memoria compartida permite dividir las aplicaciones en varias 
tareas, lo que beneficia la modularidad y con ello disminución en tiempo de 
ejecución. Por tanto puede atender a varios usuarios de forma eficiente, 
interactiva y simultánea. 
 Una de las características más importantes de los sistemas con memoria 
compartida es ahorro en el tiempo de proceso, ya que la información entre los 
cores viaja en el bus interno, que siempre es más rápido que cualquier bus 
externo, además de ahorro en energía 
 En los sistemas de memoria distribuida una de las características más importantes 
es que se tiene la capacidad de crecimiento. Es relativamente fácil que un sistema 
distribuido crezca para adaptarse a las nuevas demandas de servicio, basta con 
conectar más computadoras a la red. Por otra parte, si un circuito de un 
procesador falla, a lo más afectará a un nodo conectado a la red, por lo que no 
afecta a la ejecución del sistema. Con sistemas de memoria compartida, la falla 
de un circuito afecta de manera potencial la ejecución del sistema. 
17 
 
2.5 SISTEMAS MULTICORE: 
El empleo de varios procesadores dentro de una sola máquina no es un concepto nuevo. 
Desde hace tiempo, las tarjetas madre de algunos equipos han permitido utilizar varios 
procesadores, normalmente dos o cuatro. Así también se tiene que se ha hecho uso de 
computadoras en clúster, de modo que todos actúen como si fueran una única 
computadora. La novedad introducida con las nuevas tecnologías es que ahora los 
procesadores estén montados sobre un único chip, con 2, 4, 6 u hasta 8 núcleos dentro 
del mismo encapsulado. El motivo principal para esto es la economía, pues resulta más 
barato producir ordenadores con dos cores que dos procesadores independientes en una 
misma tarjeta. Además, se produce un ahorro en el tiempo de proceso, ya que la 
información entre los cores viaja en el bus interno, que siempre es más rápido que 
cualquier bus externo. 
Con sistemas multicore, se reparten las diversas tareas entre los diferentes cores, de 
manera que varias aplicaciones avanzan a la vez, permaneciendo menor tiempo posible 
en espera del control del procesador. La tarea de repartir los programas entre los 
diferentes cores es realizada por el sistema operativo, por lo que al no depender de las 
aplicaciones, cualquier programa, sea antiguo o actual, funciona sin problema en un 
core. 
Otra de las ventajas de sistemas multicore es el ahorro de energía. Con un único 
procesador, una aplicación exigente pone a trabajar al tope al procesador, generando gran 
cantidad de calor. Si existen diferentes cores, solo trabajará al máximo el core que 
soporte esa aplicación en un determinado momento. Los otros tendrán una menor carga, 
lo que en conjunto hace que se disipe menos energía [11,3]. 
2.6 MÉTRICAS DE DESEMPEÑO EN MULTIPROCESAMIENTO. 
Existen diversas formas de medir el desempeño de un programa corriendo sobre 
procesadores paralelos. Las medidas más comúnmente usadas son: el tiempo de 
ejecución, precio/desempeño, el speed-up (aceleración) y la eficiencia [23]. 
 
18 
 
La métrica más importante para correr un trabajo sobre una máquina dada es el tiempo de 
ejecución [23]. 
Precio/desempeño de un sistema paralelo es simplemente el tiempo transcurrido por un 
programa dividido por el costo de la máquina que corrió el trabajo. 
El Speed-up (Sc) y la eficiencia son las medidas más frecuentemente usadas para conocer 
que tan eficientemente se está utilizando. 
El Sc (aceleración) es la medida generalmente usada: Para obtenerla se ejecuta el mismo 
programa sobre un variado número de procesadores. El Sc es entonces el tiempo 
transcurrido en un programa secuencial por un procesador dividido entre el tiempo de ese 
mismo programa paralelo en n procesadores. Así la aceleración Sc para n procesadores se 
define como: 
 
Sc = Ec. 2.1 
Donde: 
 = Tiempo de ejecución del programa secuencial en un único procesador. 
 = Tiempo de ejecución del programa paralelo en n procesadores. 
 
La eficiencia E de un programa es la razón entre la aceleración de un programa y el 
número de procesadores utilizados para la ejecución del mismo. 
 
E = Ec. 2.2 
La eficiencia está relacionada con la fracción de tiempo que un procesador está siendo 
utilizado para ejecutar el programa. Idealmente si n procesadores utilizan el 100 % de su 
tiempo solamente para operaciones de computación, la eficiencia será igual a 1. Pero 
como un programa paralelo requiere comunicación entre procesadores, parte del tiempo 
19 
 
de los procesadores es consumido por esta actividad, llevandoa valores de eficiencia 
menor a 1 (E<1). 
Idealmente se espera que el Sc crezca linealmente y la E = 1 para todo n. 
Existen casos donde Sc es superlineal o sea que k procesadores resuelven una tarea en 
menos que un k-esimo del tiempo de corrida secuencial. 
 
 Speed-up (sp) Lineal (ideal) 
 Super lineal 
 Típico. 
 
 
 
Fig. 2.5 Caso ideal de aceración para n procesadores. 
 
2.7 LEY DE AMDAHL: 
Una de las maneras de saber el rendimiento de nuestra aplicación paralela es la aplicación 
de la Ley de Amdahl [3, 11, 23]. El incremento de velocidad de un programa utilizando 
múltiples procesadores en computación distribuida está limitado por la fracción 
secuencial del programa, es decir, aquélla que independientemente de cuantos 
procesadores se tengan para ejecutar el programa, solo puede ser realizada por uno solo 
de ellos; el resto del cálculo no podrá continuar hasta que se haya completado tal parte 
secuencial. 
 
La Ley de Amdahl propone normalizar el tiempo que toma realizar la operación en un 
solo procesador al valor de 1. La fracción del cálculo que se puede realizar 
Procesadores (n) 
20 
 
secuencialmente será (1-P), y la parte paralelizable es P. Con estos datos, el incremento 
de velocidad máximo que puede obtenerse con n elementos de procesamiento está dado 
por la siguiente ecuación: 
 
Sc = Ec. 2.3 
 
Como un ejemplo, si nuestra aplicación no tiene sección secuencial (es decir 1-P) y (la 
parte serializada) P=1, entonces el incremento de velocidad estará dado exactamente por 
el número de elementos de procesamiento: 
=n Ec. 2.4 
Por otra parte, si el 50% del código es secuencial es decir (1-P)=0.5 la ecuación 
queda: 
+ Ec. 2.5 
Suponiendo un número infinito de procesadores, esta ecuación da como resultado 
dos. Si el 50% del código es secuencial, por más procesadores que se agreguen el 
rendimiento nunca será mayor que 2 veces con respecto a una implementación en 
un único procesador. 
Así pues, la Ley de Amdahl establece un concepto esencial para la planeación y 
utilización de cualquier tipo de máquina paralela: el incremento en velocidad que 
podemos obtener está limitado por la fracción secuencial que emplee la 
aplicación, y no por el número de procesadores. Si el problema lo permite, se 
debe buscar implementar programas que tengan la menor cantidad de código 
21 
 
secuencial, debido a que este factor tiene mucha más importancia que el número 
de procesadores a utilizar. 
 2.8 RESUMEN DE CAPÍTULO. 
Para que varios procesadores sean capaces de trabajar juntos sobre el mismo problema 
computacional, deben ser capaces de compartir datos y comunicarse cada uno con otro. 
A lo largo de este capítulo se han expuesto dos arquitecturas especializadas cumpliendo 
estos requerimientos: Sistemas con memoria compartida y Sistemas con memoria 
distribuida. La principal diferencia en estas dos arquitecturas es el acceso a memoria. 
En computadoras con memoria compartida (multiprocesadores) todos los procesadores 
tienen acceso a una memoria principal global, por lo que comparten el mismo espacio de 
direcciones. La comunicación en estas arquitecturas es a través de variables globales y la 
programación eficiente es mediante el manejo de múltiples hilos. Sin embargo, una de 
las mayores dificultades es la coordinación en el acceso a los recursos, ya que un recurso, 
solo puede ser poseído por un solo hilo a la vez. Para evitar que más de un hilo accese a 
un mismo recurso y prevenir inconsistencia de datos es necesario emplear mecanismos de 
sincronización, lo cual hace que los hilos se coordinen para decidir en qué momento que 
hilo tiene derecho a ejecutarse y así prevenir condiciones de competencia. 
En sistemas con memoria distribuida, tanto la sincronización como la comunicación es 
por medio de mensajes enviados a través de la red. La comunicación es entre proceso y 
puede ser de manera directa o indirecta, es decir, deben tener una forma de referirse a 
cada uno de ellos. El paso de mensajes siempre se realiza en exclusión mutua, teniendo 
en cuenta los mecanismos de sincronización (síncrona o asíncrona). Debido a que en este 
tipo de arquitectura no existe un reloj común entre los procesadores la coordinación entre 
eventos es por medio de relojes lógicos (propuesto por Lamport) [25]. 
Además de la diferencia en acceso a memoria, existe un punto muy importante a 
recordar: en una aplicación distribuida lo que se hace es dividir un problema en varios 
procesos para que cooperen en la solución de éste, en una aplicación paralela lo que se 
pretende es acelerar el procesamiento, por lo que el proceso puede ser dividido en tareas 
22 
 
más granulares y cada una seguir un flujo de ejecución diferente, reuniendo al final 
resultados obtenidos. Tener recursos compartidos y gran cantidad de comunicación le 
resta eficiencia a la programación en estas arquitecturas. 
 
23 
 
CAPÍTULO 3. ARQUITECTURA DEL SISTEMA 
3.1 INTRODUCCIÓN AL CAPÍTULO. 
En este capítulo se describe la arquitectura de hardware y software para hacer la 
implementación de cómputo paralelo. Se da una breve descripción de la interfaz y los 
pragmas utilizados para realizar paralelismo en cada una de las arquitecturas 
mencionadas, así como también las ventajas y desventajas que se presentan durante su 
uso. 
3.2 DESCRIPCIÓN DE LA ARQUITECTURA DE HARDWARE. 
Para la construcción física del sistema propuesto se integran dos máquinas multicore con 
base a las interfaces de programación MPI y OpenMP. MPI para distribuir la carga entre 
los nodos que conforman el clúster y OpenMP para el manejo de hilos entre los 
procesadores en una misma máquina. 
Se establece un caso de estudio que permite determinar regiones críticas en el acceso a un 
recurso común que impone las restricciones en tiempo necesarias y permite visualizar la 
potencial serialización entre procesos. El recurso común es una matriz de pesos de la red 
neuronal ART2A llamada W. 
El programa está diseñado para su ejecución en N máquinas agrupadas en un clúster de 
alto rendimiento. En la práctica, para realizar los experimentos de desempeño se 
utilizaron dos máquinas conectadas entre sí a través de una interface de red del tipo LAN 
a una velocidad de 100 Mbps. Cada máquina está equipada con un procesador Intel Core 
2 Duo que es capaz de ejecutar 2 hilos paralelos simultáneamente mediante el uso de dos 
núcleos [3,8]. La plataforma del sistema operativo utilizado es Windows XP de 32 bits. 
La herramienta utilizada para hacer trabajar estas dos máquinas como un clúster es MPI 
[3,7,13], con esto tenemos la capacidad de controlar cada uno de los procesos 
participantes en la ejecución del programa y direccionarlos hacia cualquiera de los dos 
equipos. La arquitectura de hardware se representa en la figura 3.1. 
24 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fig. 3.1 Arquitectura híbrida de multiprocesamiento. 
 
 
Para aprovechar la arquitectura multicore se utiliza el estándar OpenMP. El esquema de 
programación en tales arquitecturas se realiza mediante el control de hilos. Haciendo uso 
de las directivas de OpenMP en el programa, solo hay que identificar la región que no 
tiene dependencia de datos y puede ser paralelizada para ser ejecutada por múltiples hilos 
[3,4,5,6,10]. Esto sin olvidar sincronizar el trabajo de los hilos para evitar condiciones de 
competencia [18,21]. Debido a que los sistemas multicore cuentan con la característica 
de compartir memoria, se dividen las operaciones dentro de cada proceso entre los 
núcleos (cores) con que cuenta el sistema. 
 
Para el desarrollo del código de este programa se utilizó el IDE (Integrate Development 
Environment) Microsoft para la programación en lenguaje C++ y el compilador de Intel 
ICC (Intel Compiler Colection) para obtener la funcionalidad de las directivas de 
OpenMP. Como herramienta de desempeñose utiliza la librería estándar time.h del 
OpenMP 
CPU
2 
MEMORIA 
PRINCIPAL 
1 
CPU
1 
OpenMP 
CPU
2 
MEMORIA 
PRINCIPAL 
1 
CPU
1 
MPI MPI 
RED 
25 
 
lenguaje C para analizar el comportamiento que toman los hilos y su mejora con respecto 
a ese mismo programa de manera secuencial. Así mismo se hace uso de las métricas de 
desempeño como es la ley de Amdahl. 
 
Los resultados parciales obtenidos en cada proceso son comunicados a un proceso 
maestro dentro de la red. Este coordina a los procesos trabajadores y evalúa los 
resultados que le son comunicados por la interfaz MPI a través de la red. También envían 
una respuesta a los procesos trabajadores, indicándoles el procedimiento a seguir para la 
actualización o incorporación de un nuevo vector al recurso compartido. 
Haciendo uso de ambas arquitecturas (descritas en la sección 2.2 Y 2.3) se puede 
observar el desempeño del sistema y su rendimiento en base a métricas de tiempo. Esto es 
evaluando el tiempo consumido al final de cada uno de los procesos, así como los 
recursos de comunicación a través de la red empleados en promedio. 
 
3.3 DESCRIPCIÓN DE LA ARQUITECTURA DE SOFTWARE. 
En los sistemas distribuidos, debido a la ausencia de memoria compartida, toda la 
comunicación y mecanismos de sincronización se basa en la transferencia de mensajes. 
Esta es la parte fundamental y básica en cualquier sistema distribuido. Tal sistema tiene 
la característica de poder compartir recursos como son: hardware, software o datos. Sin 
embargo, para obtener un buen rendimiento, es importante reducir la latencia1 de las 
comunicaciones ya que estas afectan en gran medida al rendimiento. Otro aspecto a tener 
en cuenta para mejorar el rendimiento es evitar la existencia de cuellos de botella o 
recursos centralizados en el sistema. Para que el sistema pueda crecer, el sistema 
operativo debe evitar la existencia de componentes centralizados. En los sistemas de 
memoria compartida, la comunicación y sincronización es a través de variables globales 
 
1 Latencia: Mide el tiempo necesario para transferir un mensaje vacío. La latencia contabiliza la 
sobrecarga introducida por el software de comunicaciones. 
26 
 
compartidas. Para lograr que varios hilos participen en la solución de un mismo 
problema, es necesario emplear mecanismos de sincronización, es decir, la manera de 
coordinar para accesar a un recurso compartido y con ello evitar inconsistencia de datos, 
esto se realiza a través de fragmentos de código que se denomina sección crítica. Para 
que un hilo pueda entrar a una sección crítica este debe pedir permiso, de igual manera 
cuando sale debe notificar para que los demás que están en espera de accesar y ejecutar 
su parte correspondiente puedan accesar. La estructura por tanto, de cualquier mecanismo 
que pretenda resolver el problema de la sección es la siguiente: 
 
Entrada en la sección crítica 
Código de la sección crítica 
Salida de la sección crítica 
 
Una forma representativa de dicho mecanismo es el diagrama 3.2, donde se puede 
observar que una sección crítica es una barrera que protege a un recurso compartido, y 
para que cada uno de los hilos pueda accesar a dicho recurso debe pedir permiso de 
entrar. Una vez que un hilo entre a ejecutar código de la sección crítica, bloquea el 
acceso, y ningún otro podrá entrar, hasta que el hilo que la posee salga de ella. Este 
acceso se controla en la sección crítica mediante un mutex o un semáforo. Sin embargo, 
el problema está en cómo extender un orden parcial a un ordenamiento total y arbitrario, 
usándolo en la resolución de problemas de sincronización. 
 
 
 
 
 
 
 
 
27 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Como se puede observar en las figura 3.2 y 3.3, dentro de la sección crítica los procesos 
pueden estar accediendo y modificando variables comunes, registros de Bases de Datos, 
algún archivo, etc. En general cualquier recurso compartido. La característica más 
importante es que cuando un proceso se encuentra ejecutando código de la sección 
crítica, ningún otro proceso se puede ejecutar su sección. Esto es debido a que cuando un 
proceso entra, la sección crítica se bloquea. Los demás procesos que necesiten accesar a 
dicha sección quedarán en espera hasta que el proceso la libere. Y así sucesivamente, 
hasta que no exista proceso alguno esperando por el recurso protegido por la sección 
crítica. 
Fig. 3.2 Sección Crítica. Solo un hilo a la vez puede ejecutar el código; los demás quedan en 
espera de la liberación. 
SALIDA DE LA SECCIÓN CRÍTICA 
(puede accesar el siguiente proceso en 
espera) 
MECANISMOS DE ACCESO A LA 
SECCIÓN CRÍTICA (MUTEX, SEMÁFORO) 
CÓDIGO DE LA 
SECCIÓN CRÍTICA 
 
 
 
ACCESO A RECURSO 
COMPARTIDO 
SOLO UN PROCESO 
A LA VEZ 
Lista de procesos en espera 
de accesar a la Sección 
crítica. 
0 1 2 3 n 
28 
 
 
La forma típica en la que una sección crítica protege datos compartidos por múltiples 
procesos ejecutándose simultáneamente es la Figura 3.3 
Por ejemplo, cuando un proceso escribe nuevos datos a un elemento dentro de un arreglo 
y actualiza el índice máximo de este arreglo, puede ocurrir una inconsistencia si 
consideramos que otro proceso corriendo simultáneamente en otro procesador trabajando 
sobre el mismo arreglo realiza algún cálculo sobre cada elemento en el arreglo. Si el 
segundo proceso ve el nuevo valor del índice antes que el arreglo contenga un dato válido 
entonces el cálculo es incorrecto. La definición de una sección crítica es una solución 
general a este tipo de problema. Por lo que solamente un proceso está ejecutando dicha 
sección crítica de código a la vez. La notificación de este estado será comunicada 
mediante un bloqueo. El siguiente diagrama de tiempo muestra tres procesos 
compartiendo los mismos datos que son manipulados dentro de una sección crítica del 
código. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fig. 3.3 Estados de los procesos en una sección crítica (ejecutándose y en espera). 
 
Sección 
crítica 
espera 
ejecutando 
Proceso 3 
Proceso 1 
Proceso 2 
Proc. 1 bloquea 
Proc. 2 espera 
Proc. 2 bloquea Proc. 3 bloquea 
Proc. 3 espera 
Proc. 1 libera Proc. 2 libera 
Tiempo 
29 
 
Solo a un proceso a la vez se le permite ejecutar el código de la sección crítica, 
convirtiéndose con ello en una operación atómica. Si ningún proceso está ejecutando 
dentro de la sección crítica, la decisión de qué proceso entra en la sección se hará sobre 
los procesos que desean entrar. Además esta decisión debe realizarse en tiempo finito. 
TIPOS DE COMUNICACIÓN. 
3.4 OpenMP. 
Para hacer la paralelización de hilos en cada uno de los procesos, se utilizan las directivas 
de OpenMP. Las librerías OpenMp proporcionan una forma rápida y eficiente para dar 
soporte a la programación multihilos, sin tener que considerar los detalles internos del 
funcionamiento de los hilos en determinado sistema operativo. Esto permite al 
programador enfocarse en el diseño sin tener que ocuparse de la implementación a detalle 
de los hilos. Además de que permite construir aplicaciones paralelas portables entre 
diferentes plataformas [2, 3, 4, 8]. El mecanismo de OpenMp funciona básicamente a 
través de directivas de compilación más que en el uso de funciones, de forma que la 
implementación del paralelismo se realiza lo más transparente posible para el código del 
programa. 
Las directivas OpenMP se aplican sobre un bloque estructurado, es decir, un enunciado 
simple o compuesto que tenga un solo punto de entrada y un solo punto de salida (sin 
saltos hacia dentro o fuera del bloque) [3]. 
La secuencia típica para crear una construcción OpenMP es: 
 Definir un bloque estructurado, el cual será ejecutado por múltiples hilos en 
paralelo. En OpenMP, este bloque es llamado “región paralela”. 
 Distribuir laejecución de la región paralela entre múltiples hilos 
 Sincronizar el trabajo de los hilos paralelos durante la ejecución de la región 
paralela. 
 Controlar el ambiente de datos. 
30 
 
Cuando un hilo entra en una región paralela, se crea un conjunto de hilos. El hilo original 
se convierte en el hilo maestro del conjunto y tiene como identificador el numero 0, y 
todos los hilos incluyendo al hilo maestro ejecutan la región en paralelo. Al final, el hilo 
maestro recoge los resultados y éste continúa con la ejecución. 
3.5 Niveles de Paralelismo: 
 
En OpenMP, las dos principales formas para asignación de trabajo en hilos son: 
 Niveles de ciclos paralelos. 
 Regiones paralelas. 
Los ciclos individuales son paralelizados con cada uno de los hilos empezando 
una única asignación para el índice del ciclo. A éstos se le llama paralelismo de 
fina granulación. 
Con respecto a las regiones paralelas, cualquier sección del código puede ser 
paralelizado no precisamente por ciclos. Esto es algunas veces llamado 
paralelismo de gruesa granulación. El trabajo es distribuido explícitamente en 
cada uno de los hilos usando el único identificador (myid) para cada hilo. Esto 
frecuentemente se hace por el uso de declaración de if por ejemplo: 
 
if (myid == 0) 
 
donde myid es identificador de cada thread. 
 
Para especificar el número de hilos se puede utilizar la clausula num_threads en la 
directiva parallel, o bien se puede usar la función omp_set_num_threads. Ejemplo: 
 
 
31 
 
 
 
 
 
 
 
 
 
omp_get_thread_num(); regresa el número del hilo dentro del conjunto de hilos que está 
ejecutando la función. La variable thrd_num es privada para cada hilo del grupo, al que 
se le pueden anidar unas dentro de los bloques de otras. Por omisión, las construcciones 
parallel no se anidan, esto se puede cambiar con la función omp_set_nested o con la 
variable de retorno OMP_NESTED. 
Las construcciones de compartición de trabajo distribuyen la ejecución del enunciado 
asociado entre el número de hilos que encuentran, pero no lanzan nuevos hilos. Tampoco 
existe una barrera implícita sobre la entrada de la construcción. 
Ejemplo para el ciclo for: 
 
 
 
 
Donde: 
 var operador_logico rb es una variable entera que no debe ser modificada dentro 
del cuerpo del enunciado for. 
 expresión_incremento: puede ser uno de ++var, --var, var++, var--, 
var+=incremento, var=var-incremento. 
Región a ser 
paralelizada. 
Int a[5][5]; 
Omp_set_num_threads(5); 
#pragma omp parallel 
{ 
 Int thrd_num=omp_get_thread_num(); 
 Zero_init(a[thrd_num], 5); 
} 
#pragma omp for lista_de_clausulas: 
for (var=1b; var operador_ lógico rb; expresión_incremento) 
 
32 
 
 lb, rb, incremento son enteros invariantes dentro del ciclo operador_lógico puede 
ser >,<, >=,<=. 
 
La clausula schedule de la forma: 
Schedule(tipo[ , tamaño_de_trozo]). Especifica cómo son divididas las iteraciones entre 
los hilos del grupo. 
Si tipo es static, las iteraciones son divididas en trozos del tamaño especificado por 
tamaño_de_trozo, y son asignados de acuerdo al número del hilo. Si no, se especifica 
tamaño_de_trozo, las iteraciones son divididas en trozo aproximadamente iguales, con 
un trozo asignado a cada hilo. Si tipo es dynamic, las iteraciones son divididas en series 
de trozos, cada una conteniendo tamaño_de_trozo iteraciones. Cada trozo es asignado a 
un hilo que esté esperando por una asignación. Cuando no se especifica tamaño_de_trozo 
por omisión es 1. 
Si tipo es guided, las iteraciones son asignadas a hilos en trozos con tamaños 
decrecientes. Cuando un hilo termina su trozo de iteración asignado, se le asigna 
dinámicamente otro trozo, hasta que no quede ningún trozo. 
Si tipo es runtime, los tamaños de los trozos se especifican en tiempo de ejecución. Esto 
se establece con la variable de entorno OMP_SCHEDULE. 
 
Existe una barrera implícita al final de la construcción para el ciclo for, a menos que la 
clausula nowait sea especificada. 
3.6 Directivas y construcciones de sincronización. 
En adición a las barreras de sincronización implicadas a algunas construcciones está la 
directiva barrier. 
#pragma omp barrier 
33 
 
Se puede declarar explícitamente para sincronizar todos los hilos en un proceso. Cuando 
esta directiva se encuentra, cada hilo espera hasta que todos los otros han alcanzado este 
punto. 
Para declarar una sección crítica se emplea la siguiente directiva: 
#pragma omp critical [(name)] 
Bloque estructurado 
Un hilo espera al comienzo de la sección crítica hasta que ningún otro hilo esté 
ejecutando una región crítica. 
Estas son algunas de las directivas más utilizadas en OpenMP. Existen otras cuya 
referencia se pueden ver en [10] 
3.7 MPI: 
MPI (“Message Passing Interface”, Interfaz de Paso de Mensajes) es un estándar para la 
comunicación entre procesos que define la sintáxis y la semántica de las funciones 
contenidas en una librería de paso de mensajes, diseñada para ser usada en programas que 
exploten la existencia de múltiples procesadores. Su principal característica es que no 
precisa de memoria compartida, por lo que es muy importante en la programación para 
sistemas distribuidos. 
Los elementos principales que intervienen en el paso de mensajes son: el proceso que 
envía, el proceso que recibe y el mensaje. Dependiendo de si el proceso que envía espera 
a que el mensaje sea recibido, se puede hablar de pase de mensajes síncrono o asíncrono. 
En el paso de mensajes asíncrono, el proceso emisor no espera a que el mensaje sea 
recibido, y continúa su ejecución, siendo posible que vuelva a generar un nuevo mensaje 
y a enviarlo antes de que se haya recibido el anterior. Por este motivo se suelen emplear 
buzones, en los que se almacenan los mensajes a espera de que un proceso los reciba. 
Generalmente empleando este sistema, el proceso emisor sólo se bloquea o para cuando 
finaliza su ejecución, o si el buzón está lleno. 
34 
 
En el paso de mensajes síncrono, el proceso que envía espera a que un proceso lo reciba 
para continuar su ejecución. 
La Interfaz de Paso de Mensajes es un protocolo de comunicación entre computadoras. 
Es el estándar para la comunicación entre los nodos que ejecutan un programa en un 
sistema de memoria distribuida. Las implementaciones en MPI consisten en un conjunto 
de bibliotecas de rutinas que pueden ser utilizadas en programas escritos en los lenguajes 
de programación como son: C, C++, Fortran y Ada. La ventaja de MPI sobre otras 
bibliotecas de paso de mensajes es que los programas que utilizan la biblioteca son 
portables [7,13,14]. 
Con MPI el número de procesos requeridos se asigna antes de la ejecución del programa, 
y no se crean procesos adicionales mientras la aplicación se ejecuta. MPI le asigna a cada 
proceso una variable que se denomina rank (identificador del proceso dentro del 
comunicador en el rango de 0 a p-1, donde p es el número total de procesos). El control 
de la ejecución del programa se realiza mediante la variable rank, que permite determinar 
qué proceso ejecuta determinada porción de código. 
En MPI se define un comunicador como una colección de procesos que pueden enviarse 
mensajes entre sí. El comunicador básico se denomina MPI_COMM_WORLD. MPI 
también permite definir subgrupos de comunicadores a partir del comunicador básico, 
teniendo por tanto cada proceso un identificador único dentro de cada grupo [13]. 
3.8 Llamadas utilizadas para inicializar, administrar y finalizar 
comunicaciones. 
MPI dispone de 4 funciones primordiales que se utilizan en todo programa con MPI. 
Estas son: 
1. MPI _Init. Esta función debe ser utilizada antes de llamar a cualquier otra 
función de MPI y solo debe ser llamada una sola vez. 
Int MPI_Init(int *argc, char ***argv) 
 
35 
 
2. MPI_Comm_size. Permite determinar el número total de procesos que 
pertenecen a un comunicador. 
Int MPI_Comm_size(MPI_Commcomunicador, int* numprocs) 
 
3. MPI_Comm_rank permite determinar el identificador (rank) de proceso actual. 
Su sintaxis es: 
Int MPI_Comm_rank(MPI_Comm comunicador, int* identificador) 
 
4. MPI_Comm_Finalize. Esta función termina una sesión MPI. Debe ser la última 
llamada a MPI que un programa realice. Permite liberar la memoria usada por 
MPI. 
Int MPI_Init(int *argc, char ***argv) 
3.9 Llamadas utilizadas para transferir datos entre dos procesos: 
La transferencia de datos entre dos procesos se consigue mediante las llamadas: 
 MPI_Send permite enviar información desde un proceso a otro. 
 MPI_Recv permite recibir información desde otro proceso. 
Estas llamadas devuelven un código que indica su éxito o fracaso, y ambas funciones son 
bloqueantes, es decir que el proceso que realiza la llamada se bloquea hasta que la 
operación de comunicación se complete. 
En MPI un mensaje está conformado por el cuerpo del mensaje, el cual contiene los datos 
a ser enviados, y su envoltura, que indica el proceso fuente y el destino. El cuerpo del 
mensaje en MPI se conforma por tres piezas de información: buffer, tipo de dato y count. 
 El buffer es la localidad de memoria donde se encuentran los datos de salida o 
donde se almacenan los datos de entrada. 
 El tipo de dato, indica el tipo de dato a ser enviado en el mensaje. 
36 
 
 El count es el número de copias del dato a ser enviado. 
La envoltura de un mensaje en MPI típicamente contiene la dirección destino, la 
dirección de la fuente y cualquier otra información que se necesite para transmitir y 
entregar el mensaje. La envoltura de un mensaje en MPI consta de cuatro partes: 
1. La fuente, identifica al proceso transmisor. 
2. El destino, identifica al proceso receptor. 
3. El comunicador. El comunicador especifica el grupo de procesos a los cuales 
pertenecen la fuente y el destino. 
4. Una etiqueta (tag), permite clasificar el mensaje. El campo etiqueta es un entero 
definido por el usuario y se utiliza para distinguir los mensajes que recibe un 
proceso [13]. 
3.10 Llamadas utilizadas para transferir datos entre varios procesos. 
MPI posee llamadas para comunicaciones grupales que incluyen operaciones tipo 
difusión (broadcast), recolección (gather), distribución (scatter) y reducción. A 
continuación presentamos algunas funciones empleadas en nuestra aplicación: 
 MPI_Barrier permite realizar operaciones de sincronización. Este tipo de función 
suele emplearse para dar por finalizada una etapa del programa, asegurándose de 
que todos los procesos han terminado antes de dar comienzo a la siguiente 
instrucción. 
 MPI_Bcast permite a un proceso enviar una copia de sus datos a otros procesos 
dentro de un grupo definido por un comunicador. 
 MPI_Scatter establece una operación de distribución, en la cual un dato se 
distribuye en diferentes procesos. 
Cualquier programa paralelo con MPI puede implementarse con tan solo 6 funciones, 
todas ellas empiezan con MPI_ y obligan a que todos los programas escritos en MPI 
contengan la directiva: 
37 
 
#include “mpi.h” 
Este archivo contiene las definiciones, macros y prototipos de función necesarios para 
compilar los programas escritos en MPI. 
MPI suministra dos tipos de operaciones de comunicación: 
 Una operación punto a punto. Esta operación involucra a dos procesos, uno de 
los cuales envía un mensaje y el otro recibe el mensaje. 
 Una operación colectiva. Involucra un grupo de procesos. Los grupos definen el 
alcance de las operaciones de comunicación colectivas. 
La fuente y el destino de un mensaje se identifican mediante el rango dentro del grupo. 
Para comunicación colectiva, el emisor especifica el conjunto de procesos que participan 
en la operación. Luego, el emisor restringe el acceso y proporciona un direccionamiento 
independiente de la máquina a través de los rangos. No obstante, MPI permite definir 
otros grupos y dentro de cada grupo cada proceso tiene un identificador (un número 
entero) único, permitiendo que un proceso pueda pertenecer simultáneamente a varios 
grupos y tener un identificador distinto en cada uno de ellos [14]. Esto es con el fin de 
evitar comunicación extra y solo los procesos que tengan más relación se encuentren en 
un mismo grupo. Esto se hace partiendo del comunicador universal mediante la siguiente 
función. 
 
int MPI_Comm_split (MPI_comm comm, int color, int key, MPI_Comm *newcom); 
MPI_Comm_split(MPI_COMM_WORLD, color, myid, &comMaTrab); 
MPI_COMM_WORD es un entero y es el identificador universal del grupo. 
 
La palabra clave color divide los procesos y newcom es el nombre del nuevo grupo que 
se creará. Cada proceso tiene un identificador único dentro de cada grupo. 
38 
 
 VENTAJAS Y DESVENTAJAS 
3.11 VENTAJAS: 
Un programa multihilos se puede correr de manera concurrente en sistemas con un solo 
procesador. 
Un programa secuencial se puede convertir a versión multihilos. Solo se necesita 
identificar la región a paralelizar e insertar directivas de compilador en lugares 
apropiados, teniendo en cuenta la dependencia de datos, y con ello evitar deadlocks. 
Las librerías de MPI se encargan de hacer el intercambio de la información de manera 
transparente, por lo que el usuario solo se enfoca en el desarrollo lógico del mensaje. 
Existe una implementación de dominio público llamada MPICH [27,29]. 
3.12 DESVENTAJAS: 
OpenMP tiene una ventaja en la simplicidad de la programación y la portabilidad desde 
los programas seriales, aunque los sistemas de memoria-compartida en general tienen una 
pobre escalabilidad. Agregando procesadores adicionales a un esquema de memoria-
compartida incrementa el tráfico en el bus del sistema, haciendo más lento el tiempo de 
acceso a memoria y demorando la ejecución de un programa. 
Un esquema de memoria-distribuida, sin embargo, tiene la ventaja de que cada 
procesador está separado con su propio bus de acceso a la memoria. Por ésta causa, son 
más escalables. En adición, es posible construir sistemas más grandes y baratos 
conectado computadoras vía red de trabajo. Por otra parte, si un procesador dentro de un 
sistema de memoria compartida falla, es posible la caída del sistema. Por el contrario, si 
esto ocurre en un sistema de memoria distribuida, el sistema puede continuar aún con los 
procesadores disponibles, ya que sólo afectará a un solo nodo. 
Debido a la compartición de variables, es necesario utilizar secciones críticas, deteniendo 
de alguna manera la ejecución de otros hilos que requieran accesar a algún recurso 
protegido por la sección crítica. 
39 
 
En sistemas distribuidos, debido a la ausencia de memoria compartida, los mecanismos 
de comunicación y sincronización entre los procesos son a través de la red, por lo que se 
puede llevar a consumir mayor tiempo en comunicacion que en procedimientos de 
cálculo propios del problema. 
3.13 RESUMEN DE CAPÍTULO: 
En este capítulo se describen las arquitecturas del hardware y software para llevar a cabo 
cómputo paralelo en arquitectura multicore y su integración a una red de computadoras 
(clúster de computadoras), creando en esta forma una plataforma de multiprocesamiento 
híbrida basada en dos importantes modelos de memoria: compartida y distribuida. En 
este esquema se tienen recursos de software compartidos entre los diferentes procesos. 
Para la implementación de estas dos arquitecturas se propone el uso de dos interfaces de 
programación que permiten realizar de manera transparente la programación en paralelo: 
OpenMP y MPI. 
 OpenMP en sistemas multicore para la ejecución de un proceso de manera más 
rápida. 
 MPI para distribuir la carga entre los diferentes procesos y procesadores 
participantes en la aplicación. 
En el capítulo 4 se plantea la arquitectura de software que realiza la división de los 
procesos que entrenan la red neuronal, en un proceso administrador y n-1 procesos 
trabajadores. Esto seplantea con el fin de que solo exista comunicación entre los 
procesos que realizan entrenamiento (procesos trabajadores) y que tengan que 
comunicarse datos. Sin embargo, para llevar a cabo este modelo de programación en 
paralelo, es necesario emplear mecanismos tales como: sincronización en el acceso a los 
recursos compartidos y la forma en que se comunican los diferentes procesos. 
 
40 
 
CAPÍTULO 4 CASO DE ESTUDIO. 
4.1 INTRODUCCIÓN AL CAPÍTULO. 
En este capítulo se describe detalladamente las etapas de la red neuronal que es el caso de 
estudio. Se describen tres casos diferentes: En el primer caso se describe el 
multiprocesamiento en ambas arquitecturas, se realiza la implementación de la interfaz 
MPI y los pragmas de OpenMP obteniendo una ejecución hibrida de ambas. Como 
segundo caso se aborda el paralelismo sólo en sistemas multicore. Debido a la 
transparencia en la utilización de los pragmas propios de OpenMP, solo es necesario 
identificar la región a paralelizar en el que no debe existir dependencia de datos. Por 
último, como tercer caso se hace la implementación de manera serial. 
En cada uno de los casos se toma tiempo de ejecución, esto para determinar la 
conveniencia del procesamiento paralelo. 
4.2 DESCRIPCIÓN DE LA RED NEURONAL ART2A. 
ART2A es una red neuronal de entrenamiento no supervisado, cuya estructura consiste de 
dos redes neuronales ART [16]. Su objetivo de es la detección, localización y 
clasificación de defectos y fallas internas. La información proporcionada a la red para su 
entrenamiento es a través de una base de datos que contiene información suficiente de 
cada tipo de defecto. La forma de entrenamiento es comparar las entradas presentes con 
categorías aprendidas seleccionadas. Las categorías aprendidas se encuentran 
almacenadas en una estructura multidimensional (matriz) [15]. Su entrenamiento se 
basa en 3 fases: 
1. La fase de pre-procesamiento. 
2. La fase de búsqueda. 
3. La fase de adaptación. 
41 
 
 
1 La fase de pre-procesamiento es la creación de un vector de entrada I. El vector 
de entrada I contiene información del fenómeno a ser estudiado A, bajo la 
siguiente ecuación: 
I= . . . . . . . .Ec. 4.1 
 
Dando como resultado un vector normalizado I. 
Los prototipos de W pueden ser inicializados con valores aleatorios o constantes 
en el rango de [0,1]. El parámetro de vigilancia ρ es el grado mínimo de similitud 
entre el vector de entrada I, y cualquier categoría definida en que pertenece a 
W. 
El grado de aprendizaje β afecta que tan rápido el algoritmo realiza los cambios. 
Este es elegido para evitar que las categorías se muevan demasiado rápido y 
por tanto desestabilizando el proceso de aprendizaje. 
El parámetro de elección α є [0, ∞] define la máxima profundidad de búsqueda 
para un adecuado agrupamiento suministrando un desborde de punto flotante. 
 
1. La fase de búsqueda, es una fase iterativa que puede ser dividida dentro de dos 
procesos: 
 
A. La elección. 
B. La comparación. 
 
A. La elección. Una vez que el vector de entrada I es calculado, este se debe 
comparar con los prototipos ya definidos en W. Este proceso está encargado de 
42 
 
encontrar la categoría óptima, definida como la categoría similar para I respecto 
a la conjunción difusa. 
I= { , }. . . . .Ec. 4.2 
 
El valor máximo de la conjunción difusa corresponde a una alta actividad de red 
Tj (número de vectores aprendidos en W), donde j es la posición del vector 
ganador dentro de W. 
 
B. El proceso de comparación. Si el grado de similitud entre la entrada y cualquier 
categoría es mayor o igual a ρ, entonces el prototipo j, es elegido para representar 
el grupo que contiene la entrada, se dice que la red alcanza resonancia. Si el 
grado de similitud es ρ, entonces otra categoría debe ser 
seleccionada y comparada con el vector I. Si cualquier prototipo o categoría no 
alcanza el grado de similitud, entonces el vector I debe ser agregado a W como 
un nuevo prototipo. 
 
2. La adaptación es la última fase en el algoritmo, donde el prototipo ganador tiene 
que ser actualizado con respecto al patrón de entrada por: 
 = β( ) + (1 - β) Ec.4.3 
 
El siguiente diagrama de flujo representa el entrenamiento de la red neuronal ART2A. 
 
 
 
 
 
43 
 
Figura 4.1 Algoritmo general de la red ART 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
CASOS DE ESTUDIO: 
El caso de estudio es el entrenamiento de la red neuronal descrita. El entrenamiento es 
realizado en un sistema multiprocesador. El objetivo es estudiar el comportamiento de los 
sistemas multiprocesador cuando se tiene un recurso compartido. 
Para realizar el entrenamiento, se hace uso de varias técnicas. MPI para realizar la 
comunicación entre procesos y haciendo uso del software de Intel “OpenMP” para 
I, W, ρ, β, α 
T(j)= 
j=N 
red 
j = j + 1 
T(J)=max{T(j): j=1, . . . . N} 
Y= 
 W =[W,I] Y(J) =0 = β(I* )+(1-β) 
44 
 
manjar hilos dentro de cada proceso. La paralelización se lleva a cabo dentro de un ciclo 
para manejar los hilos en cada proceso y así acelerar la operación matricial. El número 
de hilos empleados en la aplicación se maneja de acuerdo al número de procesadores en 
la máquina. En este caso particular, cada máquina tiene 2 procesadores (núcleos) y 
creamos 2 hilos, con el fin de que cada hilo se ejecute en un núcleo diferente y evitar 
consumo de tiempo en intercambio de contexto [4,6]. Para obtener datos correctos se 
hace la sincronización de los hilos. Al final de una región paralela hay una 
sincronización implícita manejada de manera transparente por OpenMP. Solo al hilo 
maestro (0) se le permite continuar con la ejecución. 
 
El procedimiento para tratar el problema de entrenamiento de redes ART2A se detalla en 
las secciones siguientes: 
4.3 Caso 1: “IMPLEMENTACIÓN HÍBRIDA” 
Se cuenta con un clúster de computadoras con arquitectura multicore. Para la 
programación se hace una implementación de ambas interfaces de programacion 
OpenMP y MPI, obteniendo un paradigma de programación híbrido. MPI para conectar 
las máquinas dentro del grupo para formar una máquina virtual con mayor capacidad de 
procesamiento. Por otra parte, se utiliza OpenMp para explotar el paralelismo 
proporcionado por la arquitectura de memoria compartida. 
Como se ha mencionado anteriormente, el entrenamiento de la red neuronal está diseñado 
para N procesos. En la práctica se realizó en dos máquinas con características multicore 
conectadas a través de una red LAN, teniendo un total de 4 procesadores para la 
ejecución del problema (dos por máquina). Debido al análisis realizado en el que se 
determinó que existe dependencia de datos, compartición de recursos y una necesaria 
comunicación entre los procesos, la resolución de problema se diseñó de la siguiente 
manera: 
 
45 
 
Los procesos se dividen en: proceso administrador o consumidor (proceso 0) y en 
procesos trabajadores o productores (n-1 procesos). 
I. El proceso consumidor (0), se encarga de recoger datos de los n-1 procesos 
productores. Este proceso no realiza tareas de cálculo matricial, solamente realiza 
tareas de sincronización, evaluación y envío de ordenes hacia los demás procesos 
que se derivan de la ponderación de los resultados recolectados. El proceso 0 
contiene un buffer de recolección de datos correspondientes a la evaluación de la 
multiplicación de los vectores de entrada por la matriz de pesos en los procesos 
trabajadores. Cada proceso trabajador envía su resultado parcial al proceso 0, el 
cual se encarga de obtener un resultado global para el cada iteración del proceso 
ART2A. 
El proceso 0 controla las comparaciones de los resultados parciales con las 
siguientes variables globales: 
a. Una variable llamada RO (ρ) que es el valor de vigilancia dentro de la 
red. 
b. Una variable llamada ALFA (β) que es

Continuar navegando