You are on page 1of 54

Investigacin e ingeniera de software

Computacin Paralela

Abitboul Pablo (774945)


Dal Lago Mario (786047)
Pisano Sergio (785248)
Tutores:
Dr. Raimundo D'Aquila
Mg. Mara Claudia Abeledo

Contenido
RESUMEN................................................................................................................. 3
PALABRAS CLAVE.................................................................................................... 3
ABSTRACT................................................................................................................ 4
KEYWORDS.............................................................................................................. 4
1.

INTRODUCCIN................................................................................................5

2.

ESTADO DEL ARTE........................................................................................... 7

3.

OBJETIVOS........................................................................................................ 9

4.

DESARROLLO................................................................................................. 10

5.

CONCLUSIONES............................................................................................. 39

6.

REFERENCIAS................................................................................................. 40

7.

ANEXO............................................................................................................. 42

Resumen
Actualmente nos encontramos ante la disyuntiva de cmo seguir
incrementando la performance de los sistemas de computacin.
Estamos viendo grandes avances en la computacin paralela, la cual
se perfila como el nuevo paradigma a seguir, aportando una
performance superior a la de los sistemas tradicionales.
Pero la adopcin de este nuevo paradigma no es tan sencilla. Nos
enfrentamos ahora a la nueva complejidad propia de los algoritmos
paralelos.
Si bien el aumento de performance no es lineal a la cantidad de
procesadores, este nuevo enfoque de la computacin aporta mucha
mas capacidad a los sistemas actuales, imponindose como la nueva
solucin al problema de la escalabilidad.

Palabras Clave
Computacin, Arquitecturas, Programacin, Paralelo, Concurrente,
Algoritmos

Abstract
We are now faced with the dilemma of how to further enhance the
performance of computer systems.
We are seeing great advances in parallel computing, which is
emerging as the new paradigm to follow, providing superior
performance
to
that
of
traditional
systems.
But adoption of this new paradigm is not so simple. We are now facing
the new inherent complexity of parallel algorithms.
As will be seen, the performance increase is not linear to the number
of processors, but also see that this new approach provides much
more computing capability to the existing systems, emerging as the
new solution scalability.

Keywords
Computing,
Algorithms.

Architectures,

Programming,

Parallel,

Concurrent,

1.

Introduccin

En estos tiempos, en los que nos estamos acercando a la


imposibilidad fsica de seguir miniaturizando los componentes de un
microprocesador, se alzan con ms peso las voces que proclaman a la
computacin paralela como el siguiente escaln en la evolucin del
procesamiento de datos.
La idea de que la escalabilidad de transistores y frecuencias de reloj
llego a su fin, esta casi unnimemente aceptada.
Hay quienes afirman que la ley de Moore (aquella que predeca que la
cantidad de transistores por unidad de superficie se duplica cada 18
meses) comenz a carecer de validez.
Si bien estas afirmaciones hoy por hoy son un poco extremistas, es
cierto que la miniaturizacin de los transistores se acerca a un umbral
en el cual no podr proseguir. Las caractersticas fsicas de los
elementos que los conforman, impedirn en un futuro seguir
miniaturizando los mismos.
En los ltimos aos, pudimos observar como el incremento de las
frecuencias de reloj se fue desacelerando, quedando estas
prcticamente
estabilizadas
en
un
rango
comprendido
aproximadamente entre los dos y tres gigahertz.
Todo indica que estamos prximos al fin de la escalabilidad tal y como
la conocemos hasta ahora. Teniendo en cuenta este panorama, es
aqu donde el nuevo paradigma de computacin paralela es
considerado como la mejor alternativa a seguir.
Las ventajas de adoptar dicho paradigma son varias y muy buenas,
pero la mas importante es la facilidad y el reducido costo que
conlleva incrementar la eficiencia con un sistema de estas
caractersticas.
Mientras que en sistemas tradicionales, un incremento de eficiencia
se traduce en un cambio de arquitectura, con el alto costo que esto
significa, en un sistema paralelo se reduce al agregado de mas
procesadores.
Como todo paradigma, este tambin tiene sus contras. Por un lado,
duplicar la cantidad de procesadores no significa duplicar el poder de
procesamiento. Segn la Ley de Amdah, El incremento de velocidad
de un programa utilizando mltiples procesadores en computacin
distribuida est limitado por la fraccin secuencial del programa.
Como veremos mas adelante, los programas no son ciento por ciento
paralelizables, con lo cual su parte secuencial limita el aumento de
performance al agregar procesadores.
Otra de las contras de este paradigma es la dificultad a la hora de
escribir algoritmos.
Los algoritmos de programacin paralela son ms difciles de
construir que los algoritmos secuenciales. La concurrencia obliga al
5

programador a disear la comunicacin y sincronizacin entre


procesos e hilos.
A lo largo de este trabajo, se analizaran las arquitecturas mas
populares para el procesamiento en paralelo de informacin, as como
tambin las diferentes tcnicas de paralelizacin y los diferentes
algoritmos, haciendo un contraste entre procesamiento concurrente y
paralelo.

2.

Estado del Arte

2.1

Resea histrica

La idea de la computacin paralela naci hace mucho tiempo, cuando


los encargados de disear y programar las primeras computadoras se
dieron cuenta de que los problemas de mbito cientfico podan ser
fcilmente descompuestos en fragmentos, y que podan resolverse de
forma simultanea.
Teniendo en cuenta el gran volumen de datos que se procesaban en
los problemas cientficos, la idea de calcular los mismos
paralelamente era muy tentadora, y fue as como se disearon los
primeros sistemas de procesamiento paralelo de datos.
David Slotnick colaborador de Von Neumann ideo una maquina
paralela, la cual en principio fue desestimada por considerrsela muy
compleja para la poca. Pero Slotnick continuo desarrollando su idea,
la cual desembocara en la ILLIAC IV (1964) que es considerada la
primera maquina masivamente paralela de la historia.
Estas nuevas "Supercomputadoras" procesaban informacin mucho
mas rpido que las computadoras seriales, pero implicaban un
altsimo costo de fabricacin, y tambin una enorme complejidad a la
hora de programar algoritmos que aprovechasen sus nuevas
caractersticas.
Fue por estos motivos que la computacin paralela fue limitada
durante mucho tiempo al mbito cientfico, ya que la nueva industria
de la computacin comercial no poda permitirse semejantes costos.
2.2

Computacin paralela hoy

Hace unos aos vimos cerca el fin de la escalabilidad en la


computacin
comercial.
Las
caractersticas
fsicas
de los
componentes de los sistemas pronto impedirn que se siga
miniaturizando y escalando frecuencias.
Por este motivo desde hace tiempo se encaro un cambio de
paradigma en la industria de la computacin, la cual esta migrando
progresivamente a sistemas paralelos.
Esto implica una nueva manera de ver y de pensar.

Los primeros pasos del cambio se fueron dando con la programacin


concurrente, la cual simula paralelismo en un sistema con una nica
unidad de procesamiento.
Las tcnicas empleadas para gestionar la intercomunicacin entre
procesos en un sistema concurrente, pueden ser aprovechadas en
algunos de los sistemas paralelos.
Luego las arquitecturas evolucionaron a las primeras maquinas
multiprocesador, las cuales transformaron este aparente paralelismo
que era la concurrencia, en un real procesamiento paralelo de datos.
Las grandes empresas de desarrollo de software y hardware estn en
pleno desarrollo de liberaras y frameworks para que la programacin
de software paralelo sea mucho ms sencilla entre estas existen:
Intel: Intel Threading Building Blocks1
Microsoft: Task Parallel Libreary2
Tambin existen organizaciones como la OpenMP 3 que creo una API
para el desarrollo de software concurrente y paralelo.
Adems de liberara existen varios lenguajes de programacin que
incorporan a la concurrencia como ncleo central incluyendo soporte
nativo, palabras claves, etc. Entre ellos podemos nombrar a Erlang 4,
Clojure5, y el nuevo lenguaje de Microsoft Axum6.
La mayora de estos lenguajes estn basados en el modelo de Actor 7,
que es un modelo matemtico de la computacin concurrente que
trata a los "actores" como los primitivos universales de la
computacin en paralelo: en respuesta a un mensaje que recibe, un
actor puede tomar decisiones locales, crear ms actores, enva ms
mensajes, y determinar cmo responder al siguiente mensaje
recibido.
El
modelo
de
actor
se
origin
en
1973.
Se ha utilizado tanto como un marco para una comprensin terica de
la concurrencia, y como base terica para varias aplicaciones
prcticas de los sistemas concurrentes.
2.3

Como encarar el cambio

Para encarar este cambio, hay que hacerlo desde varios frentes
simultneamente.
1

http://software.intel.com/en-us/intel-tbb/
http://research.microsoft.com/en-us/projects/tpl/
3
http://openmp.org/wp/
4
http://www.erlang.org/
5
http://clojure.org/
6
http://msdn.microsoft.com/en-us/devlabs/dd795202.aspx
7
http://en.wikipedia.org/wiki/Actor_model
2

Por un lado el hardware debe adaptarse al nuevo paradigma,


proveyendo mltiples unidades de procesamiento. En este aspecto es
donde quizs se avanzo ms rpido hasta el da de hoy, ya que en la
actualidad disponemos de sistemas multiprocesador eficientes.
Por otra parte los sistemas operativos deben poder gestionar
eficientemente al nuevo hardware, aprovechando sus nuevas
caractersticas y abstrayendo en algunos casos la complejidad al
usuario y o programador.
Finalmente y para sacar el mximo provecho de estos sistemas, la
comunidad de programadores deber idear nuevas tcnicas y
patrones de diseo que faciliten la implementacin de este nuevo
paradigma, ya que los nuevos algoritmos son sustancialmente mas
complejos que los anteriores.
2.4

El futuro de la computacin paralela

El hardware ya esta aqu hoy. El gran desafo ahora es poder


construir software que obtenga beneficios de las nuevas
arquitecturas.
Muchos problemas nuevos surgen a la hora de disear software
paralelo.

3.

Objetivos

Este trabajo se propone los siguientes objetivos:


a) Entender hacia donde se dirige la tecnologa con el propsito de
mejorar y hacer ms eficiente el uso del HW y el SW, a travs de la
programacin paralela y la utilizacin de procesadores multincleo.
b) Comprobar la facilidad de escalamiento de las arquitecturas
distribuidas utilizando algoritmos paralelos.
c) Conocer las ventajas y desventajas que otorgan los algoritmos
paralelos respecto de los secuenciales en determinados tipos de
aplicacin.

10

4.

Desarrollo

4.1

Arquitecturas Paralelas

Actualmente existen en mercado una gran variedad de sistemas


capaces de procesar datos de forma paralela. Debido a la gran
variedad, vamos a clasificar los sistemas en dos grandes categoras
para facilitar su estudio, mencionando sus debilidades y fortalezas.
La primera se refiere a las arquitecturas denominadas UMA (uniform
memory access) y NUMA (non uniform memory access).
Dentro de cada una de estas categoras existen diferentes
implementaciones, destacndose para UMA a SMP (Sistema de
multiprocesamiento simtrico) y para NUMA a MMP (procesamiento
masivamente paralelo)
El incremento de performance obtenido por una arquitectura paralela
esta acotado por diferentes factores, que no pueden dejar de tenerse
en cuenta.
No obtendremos mas eficiencia en los algoritmos a menos que ellos
estn especficamente diseados para el entorno en los cuales sern
ejecutados.
Arquitecturas UMA
SMP (Symmetrical Multiprocessing, multiproceso simtrico)

Figura 1 Arquitectura SMP

Este es el enfoque mas sencillo de procesamiento paralelo. La


arquitectura SMP es muy similar a un sistema tradicional, al que se le
11

agregan varios procesadores. La gran sencillez de esta arquitectura


permite ser gestionada por una sola copia del sistema operativo. Los
procesadores comparten todos los recursos del sistema, y son
jerrquicamente iguales. Por este motivo la arquitectura se llama
simtrica.
En SMP cualquier procesador puede realizar cualquier tarea sin
importar su localizacin en memoria, con lo cual las tareas pueden
cambiar fcilmente de procesador, garantizando la eficiencia.
La principal caracterstica de memoria compartida para todos los
procesadores, la cual es accedida por un bus comn.
Ventajas y Desventajas
El bus debe ser controlado para que lo utilice un solo procesador en
cada instante de tiempo. Esta es una de las principales desventajas
de este modelo, ya que si en sistemas monoprocesador el bus de
acceso a memoria es uno de los principales cuellos de botella, en
sistemas con ms de un procesador la situacin es mucho peor, ya
que son varios los procesadores a la espera de dicho bus.
Por este motivo, la escalabilidad en este tipo de sistemas suele estar
limitada a algunas decenas de procesadores.
Mas all del problema de la performance, al utilizar un esquema de
memoria compartida hay una serie de cuestiones que tambin
debemos considerar.
Una de ellas es la inconsistencia de datos. Al tener ms de un
procesador accediendo a la misma memoria se pueden generar
inconsistencias en los datos, ya que un procesador puede modificar
datos que estn siendo utilizados por otro.
Por el mismo motivo se pueden generar condiciones de competencia
(race conditions) y deadlocks.
Estos son los tpicos problemas de IPC (Inter proccess comunication comunicacion entre procesos), y debemos utilizar alguna de las
estrategias clsicas para resolverlos o evitarlos.
Por el lado de las ventajas debemos mencionar la facilidad de
programacin, ya que el sistema operativo gestiona los recursos, y las
tcnicas utilizadas son similares a las tcnicas de programacin
concurrente.
Otra ventaja radica en la facilidad de escalamiento, (que si bien es
limitada a unas pocas decenas de procesadores) ya que solo consta
en agregar mas procesadores.
12

Los sistemas SMP son aptos para gran cantidad de aplicaciones, entre
las cuales podemos mencionar a las que usan memoria compartida,
como los sistemas de soporte a la decisin, y los sistemas de
procesamiento de transacciones On-Line.
Dentro de esta categora podemos encontrar a las siguientes
maquinas comerciales:

HP 9000 Clase K, T y V
Sun UE6000 y E10000
DEC 8400
IMB RS/6000 J50 y R50 .

PRAM Model
Para el diseo de algoritmos paralelos se usa una variacin llamada
PRAM (Parallel Random Access Machine). Simplificando, son muchas
CPU conectados a memoria ilimitada, que es compartida por todos los
CPU.
Cuando se especifica un algoritmo PRAM se deben definir primero el
tipo de acceso a memoria.
Los 4 tipos disponibles son:
Parmetros de Acceso a memoria
Concurrent Read,
Concurrent Write (CRCW)
Concurrent Read, Exclusive
Write (CREW)
Exclusive Read, Concurrent
Write (ERCW)
Exclusive Read, Exclusive
Write (EREW)

Descripcin
Muchos threads pueden leer de la misma ubicacin
de memorial mismo tiempo y mltiples threads
pueden escribir en la misma posicin de memoria
al mismo tiempo.
Mltiples threads pueden leer de la misma posicin
de memoria al mismo tiempo y un solo thread
puede escribir en una determinada posicin de
memoria en un momento dado.
Un thread puede leer una posicin de memoria en
un tiempo determinado y muchos threads pueden
escribir en la misma posicin de memoria al mismo
tiempo.
Un thread puede leer una posicin de memoria en
un momento dado y un thread puede escribir una
posicin de memoria en un momento dado.

Arquitecturas NUMA
MPP (Massively
paralelo)

Parallel

Processing,

13

procesamiento

masivamente

Figura 2 Arquitectura MPP

Como
se
menciono
con
anterioridad,
el
procesamiento
simtricamente paralelo tiene las limitaciones propias de la memoria
compartida.
Para tratar de evitar estos problemas, se disearon las mquinas
masivamente paralelas.
Estas
maquinas
son
bsicamente
unidades
de
computo
independientes llamadas nodos, y poseen su propio procesador, su
propia memoria, sus canales I/O y una copia del sistema operativo.
Para comunicarse unas con otras utilizan un bus comn dedicado a
este propsito, y lo hacen mediante el pase de mensajes.
Bajo esta tcnica de pase de mensajes, los nodos son programados
para ejecutarse aisladamente, y se comunican con otros nodos
solamente cuando el programador lo explicita mediante alguna
sentencia concreta.
Estos mensajes contendrn la informacin que se desee compartir
entre los procesos, y sern enviados a travs de primitivas, pero la
responsabilidad del contenido del mensaje es exclusiva del
programador. De esta manera se libera el bus de comunicacin entre
nodos, ya que es utilizado nicamente cuando el programador as lo
requiere.
Ventajas y Desventajas
Este tipo de arquitectura es muy escalable y puede crecer hasta
cientos o miles de procesadores, de echo las supercomputadoras mas
poderosas del mundo son maquinas masivamente paralelas. Al no
tener la limitacin de un bus compartido de acceso a memoria, para
agrandar el sistema se pueden agregar tantos procesadores como se
necesite.
Pero esta fuerza de procesamiento no es sencilla de lograr. Programar
un sistema de estas caractersticas es una tarea extremadamente
14

compleja, ya que cada nodo es un sistema independiente en si


mismo, que debe ser programado en forma independiente.
Redes distribuidas
Las redes distribuidas se idearon hace mucho tiempo, y en ese
momento se pensaba que era posible interconectar muchos nodos de
una red para que actuasen como una nica maquina de forma
transparente.
Luego se vio que las redes distribuidas funcionan eficientemente con
un nmero limitado de problemas, que son aquellos particionables de
forma que cada particin es absolutamente independiente del resto, y
que requiere nula intercomunicacin entre los nodos. En la mayora
de los algoritmos la comunicacin entre nodos es fundamental. En
estos casos el sistema pierde eficiencia, y su administracin se
dificulta muchsimo.
En la actualidad hay sistemas funcionando con este principio, como el
SETI@HOME8 o el FOLDING@HOME9 que consisten en un software que
cualquier usuario puede instalar en su PC, el cual se conecta a una
red y colabora procesando paquetes de informacin fraccionada.
SMP Paralelo
La arquitectura SMP Paralelo, es un hibrido entre el SMP comn y el
MMP.
Podemos encontrar aqu nodos SMP comunes, interconectados entre
si a travs de un canal de alta velocidad.
Este enfoque elimina los problemas de escalabilidad propios de los
sistemas SMP, ya que nos permite seguir agregando nodos sin
comprometer la performance del sistema completo.
Como contrapartida, cada nodo debe poseer una copia del sistema
operativo, y se pierde eficiencia en el uso de memoria compartida, ya
que esta se accede asimtricamente.
En la actualidad existen mltiples aplicaciones que utilizan esta
tecnologa, encontrndose entre ellas Oracle10, Informix11, etc.
En estas aplicaciones, se reparten las tareas de forma que se
minimice la comunicacin entre nodos, logrndose as desempeos
muy altos. Adicionalmente se puede disear la aplicacin para que un
8

SETI@HOME en http://setiathome.ssl.berkeley.edu/
FOLDING@HOME en http://folding.stanford.edu/
10
ORACLE SMP en http://www.oracle.com/global/es/products/middleware/application-grid.html
11
INFORMIX en http://www-01.ibm.com/software/data/informix/
9

15

nodo asuma las funciones de otro en caso de fallo, de esta manera se


aumenta la disponibilidad total del sistema.
Algunos ejemplos de servidores SMP Paralelo son el IBM RS/6000 12 o
el NCR WorldMark 5100M13
ccNUMA
Tomando como base el modelo SMP paralelo que tiene gran
flexibilidad y es fcilmente escalable, observamos que su principal
problema es la perdida de performance en aplicaciones que utilizan
de forma masiva la memoria compartida.
ccNuma soluciona estos problemas, y funciona de la siguiente
manera:
El sistema esta compuesto de varios nodos SMP interconectados, pero
la principal diferencia con SMP Paralelo, es que el sistema operativo
gestiona los recursos de manera que todo el sistema se comporte
como uno solo, y la complejidad subyacente quede oculta.
De esta manera observamos que la programacin es mucho mas
simple, ya que a ojos del programador el sistema se comporta como
un SMP uma, y se pueden utilizar las mismas tcnicas, sin la limitante
de escalamiento antes mencionada.
Estos sistemas se aplican al mismo tipo de problemas que resuelve
un SMP uma, pero que requieran de una potencia de procesamiento
mucho mayor.
Generalidades sobre las arquitecturas
El paso de mensajes y la memoria compartida, son tcnicas de
intercomunicacin entre procesos, que no dependen del hardware,
lenguaje de programacin o bibliotecas.
Desde este enfoque vemos que es posible un sistema SMP con paso
de mensajes, sin utilizar las facilidades de la memoria compartida, as
como tambin se puede construir un sistema MMP que utilice una
memoria compartida simulada.
No obstante, el principal objetivo del procesamiento paralelo es la
maximizacin de rendimiento, con lo cual siempre se busca utilizar la
tcnica mas adecuada a la arquitectura que ya poseemos, con la cual
obtendremos los mayores beneficios.
Mas all de la arquitectura elegida, hay que destacar que el buen
diseo del software es fundamental para obtener una ganancia en
performance comparada con un monoprocesador, ya que un mal
diseo de software puede provocar incluso un desempeo menor.
12
13

IBM RS/6000 en http://www-03.ibm.com/systems/p/


NCR WorldMark 5100M en http://ncr.vecmar.com/NCR_WorldMark5100.htm

16

Trabajo redundante
No importa como un algoritmo concurrente sea, siempre hay partes
que son seriales. Cuando el resultado de la computacin serial debe
ser compartido, se ejecuta en un procesador y se transmite el
resultado a los otros procesadores que requieren la informacin.
Transmitir esa informacin agrega overhead al tiempo de ejecucin.
En otro caso si los datos usados estn disponibles en los otros
procesadores, se pueden generar los resultados en cada procesador
sin necesidad de transmitir los resultados.
En el paralelismo de memoria compartida, los datos estn disponibles
por default.

4.2

PVM: Un Framework para la Computacin Paralela Distribuda

El sistema PVM es un entorno de programacin para el desarrollo y


ejecucin de grandes aplicaciones concurrentes o paralelas que
consisten de componentes de mucha interaccin, pero que son
relativamente independientes.
Su propsito es operar en una coleccin de elementos informticos
heterogneos e interconectados mediante una o ms redes. Los
procesadores que participan pueden ser mquinas escalares,
multiprocesadores,
o
computadoras
para
fines
especiales,
permitiendo que componentes de aplicacin se ejecuten sobre la
arquitectura ms adecuada para el algoritmo. PVM proporciona una
interfaz sencilla y general que permite la descripcin de varios tipos
de algoritmos (y sus interacciones), mientras que la infraestructura
subyacente permite la ejecucin de aplicaciones en un entorno
informtico virtual que soporta mltiples modelos de computacin
paralela. PVM contiene facilidades para la ejecucin concurrente,
secuencial o condicional de componentes de la aplicacin, es porttil
a
una
variedad
de
arquitecturas,
y apoya ciertas formas de deteccin de errores y la recuperacin.
Introduccin
En los ltimos aos, el procesamiento paralelo y distribuido se ha
conjeturado que es la solucin ms prometedora a las necesidades de
computacin del futuro. Significativos avances en algoritmos
paralelos y arquitecturas han demostrado el potencial de aplicacin
de tcnicas de computacin concurrente para una amplia variedad de
17

problemas. Sin embargo, la mayor parte de los esfuerzos de


investigacin se han concentrado ya sea en modelos computacionales
[1], las versiones paralelas de los algoritmos, o arquitecturas de
mquinas; se le ha dado relativamente poca atencin a los entornos
de desarrollo de software o tcnicas de construccin de programas
que se requieren a fin de traducir algoritmos en programas
operativos.
Este aspecto se est volviendo cada vez ms importante mientras el
procesamiento paralelo evoluciona a partir de la solucin de
problemas stand-alone, matemticamente precisos, hacia sistemas
de software ms grandes y ms complejos.
Estos sistemas consisten a menudo en muchos componentes que
interactan cada uno con sus requerimientos singulares. Estos
requerimientos son lo suficientemente diversos como para dificultar la
programacin de los mismos en un Framework unificado, incmodos y
a veces poco prcticos para ejecutar el sistema en una sola mquina.
Un ejemplo de tal sistema es la aplicacin mecnica de fluidos,
llamado BF3D, se describe en [10]. Esta aplicacin no es slo de
cmputo intensivo; utiliza grandes cantidades de memoria, crea
grandes cantidades de datos de salida, y requiere terminales en 2D y
3D de grficos para mostrar los resultados.
El algoritmo consiste fundamentalmente en la solucin de un conjunto
de ecuaciones diferenciales en un espacio tridimensional, usando una
cuadrcula escalonada de forma adecuada. El algoritmo puede ser
paralelizado de diferentes maneras, lo que permite su ejecucin en
varias
categoras
de
mquinas
paralelas.
Sin
embargo
multiprocesadores tpicos rara vez soportan E/S externas de alto
ancho de banda o grficos de alto rendimiento, de manera que
necesita la separacin de la computacin, administracin de salida, y
los componentes de visualizacin grfica del sistema. Otro ejemplo de
una aplicacin con diferentes requerimientos para los distintos subalgoritmos es el proyecto de simulacin del Medio Ambiente Mundial
[2], un esfuerzo de simulacin para estudiar grandes concentraciones
de contaminantes y caractersticas de dispersin en funcin de
diversos factores ambientales. Los requisitos ideales de esta
simulacin computacional son el procesamiento vectorial (para el
anlisis de flujo de fluidos), multiprocesamiento distribudo (modelado
de transporte de contaminantes), computacin escalar de alta
velocidad (simulacin de efectos de la temperatura), y grficos en
tiempo real para la interaccin del usuario.
Desde otro punto de vista, muchas aplicaciones que pueden ser
objeto de ejecucin concurrente pueden ser programadas utilizando
el paso de mensajes o algoritmos de memoria compartida. Cuando los
ambientes que soportan a ambos estn disponibles, un algoritmo
hbrido, a un nivel suficientemente alto de granularidad, puede
utilizarse como ventaja. Un sencillo, pero ilustrativo ejemplo de ello es
la multiplicacin de la matriz utilizando descomposiciones por
18

subbloques [11]. En un entorno compuesto por diferentes tipos de


mquinas escalares y multiprocesadores, algoritmos altamente
eficaces y eficientes pueden ser implementados para la multiplicacin
de matrices, con algunos subbloques que son multiplicados con
prescheduling esttico sobre mquinas de memoria compartida y
otros
utilizando
estrategias
"pipe-multiplican-roll"
sobre
computadoras de memoria distribuda. Los resultados empricos
obtenidos mediante este mtodo se presentan en la seccin 5.
Cabe sealar que los entornos de computacin ms tpicos ya poseen
la diversidad necesaria de hardware para resolver tales aplicaciones
paralelas de gran tamao, y tambin contienen soporte para
mltiples modelos de computacin concurrente. Redes locales de alta
velocidad con estaciones de trabajo grficas, motores escalares de
alto rendimiento, un multiprocesador ocasional, y tal vez una
computadora vectorial son la norma y no la excepcin, y lo seguir
siendo durante los prximos aos. Sin embargo, para aprovechar esta
coleccin de capacidades y utilizarlas de forma productiva requiere de
esfuerzos considerables en la coordinacin y la reconciliacin entre
diferentes modelos de computacin y arquitecturas todo ha tenido
que hacerse manualmente. El proyecto PVM (Mquina Virtual
Paralela) es un intento de proporcionar un marco de trabajo unificado
en el que los grandes sistemas en paralelo se pueden desarrollar en
forma sencilla y de manera eficiente. El objetivo general de este
proyecto es permitir que una coleccin heterognea de mquinas en
una red pueda ser vista como un recurso de computacin
concurrente. Los algoritmos de aplicacin se expresan mediante el
paradigma ms adecuado, el sistema de PVM los ejecuta en el
hardware disponible ms apropiado, ya sea directamente o mediante
la emulacin del modelo computacional en particular. Adems, con
frecuencia se desea incorporar software existente (preferentemente
con poca o ninguna modificacin) en un sistema mas grande. PVM
est diseada para permitir esto en una forma cmoda y natural.
El sistema de PVM proporciona un conjunto de primitivas de interfaz
de usuario que pueden ser incorporados a lenguajes procedimentales
existentes. Las primitivas existen para la invocacin de los procesos,
la transmisin de mensajes y la recepcin, la radiodifusin, la
sincronizacin a travs de barreras, la exclusin mutua y memoria
compartida. Los procesos pueden ser iniciados de forma sincrnica o
asincrnica, y pueden ser condicionados por el inicio o la terminacin
de
otro
proceso,
o
por
la
disponibilidad
de
datos.
La transmisin de mensajes, as como un archivo de salida puede ser
precedida por las llamadas de primitivas especialmente provistas
para garantizar que los datos sean transmitidos o almacenados en
una mquina de forma independiente. Los sistemas de aplicacin
pueden ser programados utilizando estas primitivas en el lenguaje de
eleccin; diferentes componentes incluso pueden ser programados en
diferentes lenguajes. Las construcciones de PVM permiten por lo
tanto, el paradigma de programacin ms adecuado y el lenguaje que
19

se utilizar para cada componente individual de un sistema paralelo,


sin perder la capacidad de los mismos de interactuar y cooperar.
Cabe mencionar que las primitivas de interfaz de usuario de PVM han
sido, en parte, fruto de un conjunto de construcciones de
programacin porttil que se describen en [3]; una aplicacin escrita
utilizando estas primitivas, tambin podra ser ejecutada
directamente en un multiprocesador especfico cuando sea
necesario.
El sistema de PVM se compone de un software de soporte que se
ejecuta en los anfitriones que participan en una red; la red puede ser
local, de rea amplia o una combinacin de ambas, y el pool de
anfitriones puede ser variado dinmicamente. Los anfitriones pueden
ser mquinas escalares, estaciones de trabajo, o procesadores en
paralelo - los ltimos siendo considerados como un recurso
computacional atmico por PVM. Este software de soporte interpreta
peticiones generadas por construcciones de nivel de usuario y lleva a
cabo las acciones necesarias en una mquina de forma
independiente. El software de PVM se compone esencialmente de una
coleccin de algoritmos de protocolo para implementar en forma
confiable la transferencia secuenciada de datos, consenso distribuido,
y la exclusin mutua. En un intento por hacer que el sistema sea lo
ms robusto posible, estos algoritmos tambin incorporan
mecanismos de deteccin de errores - el proceso y la notificacin de
error en el procesador se proporciona a las aplicaciones, lo que les
permite tomar medidas correctivas. Adems, la heurstica se incluye
en los algoritmos para exclusin mutua y consenso, que permiten la
prevencin de deadlocks en varias situaciones.
Varios proyectos similares a PVM se han emprendido en el pasado, y
algunos estn an en curso. Algunos ejemplos representativos son
enumerados a continuacin en comparacin con PVM. La biblioteca
DPUP [4] emula un multiprocesador dbilmente acoplado en una red
local, al igual que el sistema dsim [5] y el medio ambiente csmico
[6]. Los dos ltimos sistemas requieren de pre configuracin de una
mquina virtual en la que las aplicaciones ejecutan y soportan slo
mecanismos de pasaje bsico de mensajes. El proyecto Amber [9] es
algo diferente en que el medio ambiente elegido como objetivo es
una coleccin homognea de multiprocesadores. Uno de los modos
de funcionamiento dentro de DPUP, tales como proyectos como
Marionette [7] y MSPCM [8], utiliza el enfoque de amo-esclavo, donde
un proceso central de control es responsable de, o est implicado en
todos los eventos del sistema. Adems de afectar el rendimiento y ser
un modelo no natural para ciertas clases de problemas, este proceso
central es crtico, y su falla conduce a un colapso total de todo el
sistema. Otro defecto comn a todo lo anterior es el uso de circuitos
virtuales para la comunicacin por redes. Adems de los overheads
que no pueden ser justificados, los lmites prcticos sobre el nmero
de
conexiones
de
afectan
a
la
escalabilidad de
las
aplicaciones. Adems la recuperacin de fallos y la depuracin es
20

mnima. El sistema de PVM es totalmente distribuido, soporta un pool


de anfitriones, y asume que slo un mecanismo de entrega de
datagramas poco confiable y no secuencial est disponible. Desde el
punto de vista de la aplicacin, las construcciones de PVM son
sustancialmente ms generales en naturaleza y abarca tanto el
paradigma de pasaje de mensajes y de memoria compartida sin
embargo, mediante la sustitucin de bibliotecas alternativas,
programas sin modificar se pueden ejecutar en multiprocesadores
especficos.

4.3

Programacin paralela y distribuida.

La programacin paralela y distribuida presentes desafos en varios


mbitos. Deben adoptarse
nuevos enfoques para el diseo y
arquitecturas de software. Muchos de los supuestos fundamentales
que se llevan a cabo en el modelo secuencial de la programacin no
se aplican en el mbito de la paralela. Cada aspecto del desarrollo de
software de Ciclo de Vida (SDLC) se ve afectada cuando los requisitos
de paralelismo o de distribucin - desde el diseo inicial hasta las
pruebas y la documentacin. Oportunidades para el paralelismo y
multiproceso sern identificados durante diversas actividades en el
SDLC. Es importante que el desarrollador de software entender la
relacin entre la programacin multincleo y el SDLC.
Tal vez la decisin ms importante y crtica que se puede hacer para
un diseo de software que se incluyen la programacin multiproceso
o paralelo es si el uso de modelos de procedimiento o modelos
declarativa. Las diferencias fundamentales en el enfoque, la tcnica,
el diseo y aplicacin entre los modelos de procedimiento declarativo
y
modelos
son
tan
dramticos
que
21

requieren paradigmas radicalmente diferentes de programacin


informtica.
La tendencia es que los ordenadores con varios procesadores en la
mayora de los casos reemplazar configuraciones en un solo
procesador empresarial, acadmico y gobierno. Para aprovechar los
entornos multiprocesador, los desarrolladores de software deben
expandirse en las herramientas y tcnicas que ya poseen. Software
proyectos que requieren una programacin multincleo o paralelo
regalo nico retos a los que estn acostumbrados a slo el modelo de
programacin secuencial. Mientras se esconda y abstraerse de parte
de la complejidad de la programacin paralela y el multithreading,
usted no tiene real accesos directos alrededor de esta idea. El
despliegue de aplicaciones de software robusta, correcta y escalable
que puede tomar.
Multiprogramacin Vs Multiprocesamiento
La multiprogramacin es una tcnica de Scheduling que realizan los
SO que permite a ms de un trabajo ejecutar cdigo. Generan la
ilusin en un single core que los procesos se ejecutan
simultneamente.
En el caso de multiprocesadores es una computadora con ms de un
procesador de propsito general, donde se usan todos los
procesadores para ejecutar los trabajos en forma concurrente.
Programacin Paralela
Es el arte y ciencia de implementar un algoritmo usando un set de
instrucciones o tareas designadas para ejecutarse de manera
concurrente.

Figura 3. Multiprogramacin Vs Multiprocesamiento

Diseo e implementacin de Aplicaciones Multicore


22

El diseo y la implementacin de aplicaciones multicore usan tcnicas


de programacin paralelas para disear software que tome las
ventajas de los CMP. El proceso de diseo especifica el trabajo de
alguna tarea. Ese diseo puede ser implementado usando librearas
de templates, librearas de clases, librearas de threading, llamadas al
sistema operativo o tcnicas de
bajo nivel como pipelining, o
vectorizacion.
Los desafos de la programacin Multicore
Hasta hace muy poco, las herramientas y tcnicas usadas por los
desarrolladores de software estaban centradas en la nocin del
modelo Secuencial en la ejecucin de un programa. La mayora de
las instituciones educativas siempre trabajaron en el contexto de
maquina con un solo procesador. Dos de las principales razones del
poco nfasis en la Programacin paralela son:
Costo: Las computadoras de un solo procesador son ms accesibles.
Tradicin: las ideas fundamentales detrs del desarrollo de software
fueron por dcadas para maquinas de un solo procesador. Los
algoritmos bsicos para buscar, ordenar, contar, fueron desarrollados,
refinados y perfeccionados bajo un modelo de programacin
secuencial y esos mismos algoritmos son los que se siguen usando
hoy en da.
Las tcnicas de programacin secuencial son importantes y siempre
van a tener un lugar. Sin embargo la computacin multiprocesador
ahora est disponible. Esto genera un montn de diferentes formas
para organizar y descomponer nuestros programas.
Las arquitectura de software que incluyan un mix de programacin
secuencial, multiprocesamiento y multithreading sern las ms
comunes.
La tendencia es que las maquinas multiprocesador reemplacen a las
de un solo procesador. Para sacar ventaja de los entornos
multiprocesador nosotros como desarrolladores de software tenemos
que agregar nuevas herramientas y tcnicas a nuestro repertorio. Los
proyectos de software multicore o paralelos presentan desafos
nicos.
Que es el modelo Secuencial?
En el modelo secuencial de programacin las instrucciones de un
programa de computadora son ejecutadas una a la vez. El programa
se ve como una receta y cada paso es ejecutado por la computadora
en el orden y cantidad especificada. El diseador del programa parte
el software en una coleccin de tareas. Cada tarea es ejecutada en un
orden especfico y cada tarea espera su turno. El programa tiene un
Principio, medio y fin bien definidos. Adems las tareas estn
relacionadas tal que si la primera tarea no puedo completar su tarea
por alguna razn entonces la segunda tarea nunca arranca. Cada
tarea espera el resultado de la previa antes de poder ejecutarse. Se
dice que las tareas son interdependientes. Esto cambia cuando los
23

requerimientos
del
multiprocesamiento.

software

incluyen

multithreading

Que es concurrencia?
Dos sucesos se dice que son concurrentes si se producen dentro del
mismo intervalo de tiempo.
Por ejemplo, dos tareas pueden ejecutarse concurrentemente en el
mismo segundo, pero con la ejecucin de cada tarea dentro de las
diferentes fracciones de segundo.
La primera tarea puede llevarse a cabo en la primera dcima de
segundo. La segunda tarea puede llevarse a cabo durante la prxima
dcima parte de segundo. Luego La primera tarea de ejecucin puede
comenzar de nuevo en la tercera dcima de segundo, etc.
Cada tarea puede alternar de ejecucin. Sin embargo, la duracin de
un segundo es tan corta que parece que ambas tareas se ejecutan de
forma simultnea.
Vamos a tratar con los desafos de la concurrencia en trminos de tres
categoras:
Software development
Software deployment
Software maintenance
Diez desafos de la concurrencia
1. Descomposicin del software en instrucciones o set de tareas
que se necesitan ejecutar simultneamente
2. Comunicacin entre 2 o ms tareas que se ejecutan en paralelo
3. Acceso o actualizacin concurrente de datos por 2 o ms tareas
4. Identificacin de las relaciones entre partes de las tareas en
ejecucin.
5. Controlar el uso de recursos para muchas tareas
6. Determinar el numero ptimos de tareas a ejecutar en paralelo
7. Crear un entorno de pruebas para simular los requerimientos y
condiciones del procesamiento paralelo
8. Recrear las excepciones del software para remover defectos
9. Documentar
y
comunicar
multiprocesamiento

diseos

que

contengan

10.
Implementar interfaces para que los compiladores y/o
Sistemas operativos soportes programacin paralela
24

Comunicacin entre tareas


Si se tienen dos tareas, A y B, que se ejecutan concurrentemente y
una de las tareas depende de la informacin de la otra, las tareas
deben tener alguna manera de comunicar la informacin. Si las tareas
necesidad de compartir algn recurso (es decir, el archivo, la
memoria, un objeto, un dispositivo, etc.) las tareas deben tener
alguna manera de transmitir la informacin de que el recurso est
disponible o que el recurso se solicita. La comunicacin entre las
tareas
se
llama
Comunicacin
entre
procesos
(IPC).
Los procesos tienen espacios independientes de direcciones. Estos
espacios de direcciones independientes sirven para aislar los
procesos de entre s. Este aislamiento es un mecanismo de proteccin
til, y esta proteccin es a veces una razn para elegir ms de
multiprocesamiento sobre multithreading. El sistema operativo
mantiene
los
recursos
de
los
procesos
por separado. Esto significa que si usted tiene dos procesos, A y B,
entonces los datos declarados en el proceso de A no son visible para
el proceso B. Por otra parte, los acontecimientos que suceden en el
proceso A son desconocidas por el proceso B, y viceversa. Si el
proceso A y B estn trabajando juntos para llevar a cabo alguna tarea,
la informacin y eventos debe ser comunicada de forma explcita
entre los dos procesos. Los datos y eventos de cada proceso son
locales.

Figura 4. Comunicacin entre procesos

Mecanismos de IPC
La especificacin
comunicacin

POSIX

soporta

25

mecanismos

bsicos

de

Archivos

Pipes

Memoria Compartida

Colas de mensajes

Sockets

Semforos

Acceso concurrente a datos o recursos por mltiples tareas


Hay 2 problemas comunes que aparecen cuando se ejecutan tareas
en forma concurrente. Estos problemas terminan corrompiendo los
datos o colgando la tarea.
Condicin de Carrera
Si dos o ms tareas intentan cambiar una porcin de datos
compartidos al mismo tiempo y el valor final de los de datos depende
simplemente de la tarea que llega primero, entonces una condicin
de carrera ha ocurrido. La informacin que est sujeta a condiciones
de carrera no es confiable.

Deadlock
Es el bloqueo permanente de procesos del sistema, esperando por el
mismo recurso. Para tratar los deadlock existen 3 tecnicas principales
que son la deteccin, la prevencin y la prediccin.
Identificar las relaciones entre tareas que ejecutan concurrentemente
Synchronization Relationship
Start-to-start (SS)
Finish-to-start (FS)
Start-to-finish (SF)
Finish-to-finish (FF)

Descripcin
Una tarea no
arranque.
Una tarea no
inicie.
Una tarea no
termine.
Una tarea no
termine.

puede arrancar hasta que otra tarea


puede terminar hasta que otra tarea
puede arrancar hasta que otra tarea
puede terminar hasta que otra tarea

Que es un proceso
Un proceso es una unidad de trabajo creada por el sistema operativo.
Es necesario notar que proceso y programa no necesariamente son
26

equivalentes. Un programa consiste en mltiples tareas y cada tarea


puede ser asociada a uno o mas procesos.
Que es el context Switch
Un context switch ocurre cuando el uso del procesador es cambiado
de un proceso hacia otro proceso.
Que es un Thread
Tambien llamados procesos livianos, permiten hacer mas eficiente la
planificacin de los procesos, y comparten todos los recursos de un
proceso, son la base de la programacin concurrente y paralela.
Cuantos Procesos o Threads son suficientes?
Hay un punto en que la sobrecarga en la gestin de varios
procesadores supera la mejora de velocidad y otras ventajas
adquirida en la paralelizacin. El viejo adagio "nunca se tienen
suficientes procesadores " simplemente no es verdad. La
comunicacin entre hilos o sincronizacin entre procesadores tiene un
costo. La complejidad de la sincronizacin o la cantidad de
comunicacin entre procesadores pueden requiere cmputo tanto que
el desempeo de las tareas que estn haciendo el trabajo pueden ser
afectados negativamente. En estos casos, es ms eficaz escribir un
programa basado en el modelo secuencial.
Por ejemplo, si desea ordenar una lista de 100 nmeros, se podra
intentar dividir la lista de 100 en grupos de 10, una ordenar cada
grupo en paralelo, y luego fusionar los grupos de 10 en una lista
ordenada. Pero el tiempo que llevara a dividir la lista en grupos de
10, comunicar dicha lista a cada grupo, y a continuacin, combinar los
resultados en un solo grupo evitando una condicin de carrera
requiere un mayor esfuerzo y el tiempo que se necesitara para
ordenar los nmeros simples utilizando un mtodo secuencial. Por
otra parte, si se tienen terabytes de nmeros, el enfoque paralelo
podra ser ms productivo.
La pregunta es en cuntos procesos, tareas o hilos se debe dividir
un? Hay un nmero ptimo de procesadores para cualquier
programa paralelo dado? En qu momento la adicin de ms
procesos o equipos al grupo de cmputo las cosas se enlentecen en
lugar de acelerarlos?
Resulta que los nmeros cambian dependiendo del programa. Algunas
simulaciones cientficas necesitan varios miles de procesadores,
mientras que para algunas aplicaciones de negocios podra ser varios
cientos son suficientes. Para algunas configuraciones de clienteservidor, ocho procesadores son ptimos y los nueve hacen que el
servidor funciona mal.
El lmite de los procesos de software puede ser alcanzado antes de
que se alcance el nmero ptimo de procesadores o equipos. Del
mismo modo, podra ver los rendimientos decrecientes en el hardware
27

antes de que se haya alcanzado el nmero ptimo de tareas


concurrentes.
Lo ideal sera que algo en el modelo de descomposicin del problema
o la descomposicin del modelo solucin puede ayudar a determinar
cuntos hilos o procesos son necesarios.
Recuerde que algunos de los desafos de los mecanismos de IPC entre
los procesos. Estos mecanismos IPC tienen que ser sincronizados. Si la
comunicacin entre dos o ms tareas no est bien sincronizada,
entonces los datos pueden sufrir condiciones de carrera, deadlock.
La complejidad en la aplicacin del modelo de descomposicin tiene
que ser considerada. Cuando el nmero de tareas cooperantes en una
aplicacin crece, la complejidad de las interdependencias aumenta
tambin. Esto puede llevar a una implementacin de software muy
inconstante y frgil.
Depuracin y Testing
Al probar un programa secuencial, se puede trazar la lgica paso a
paso.
Si se comienza con datos conocidos y se asegurara que el sistema
est en un estado conocido, entonces el resultado o el flujo de la
lgica es predecible. Pruebas y depuracin en el modelo secuencial
depende del estado inicial y el estado actual, dada la entrada
especificada.
Esto cambia en los entornos multiproceso y multihilo. Es difcil
reproducir
exactamente
el
contexto de las ejecuciones paralelas o simultneas a causa de las
polticas de funcionamiento del sistema de programacin, cargas de
trabajo dinmicas en el equipo, tiempos de procesador, procesos y
prioridades de subprocesos, latencia de las comunicaciones, la
ejecucin latencia, y el azar que participan en contextos paralelos.
Para reproducir con exactitud el estado del medio ambiente durante
la prueba y la depuracin requiere que cada tarea del sistema
operativo pueda volver a crearse en el estado en que estaba
trabajando.
El estado del procesador debe ser conocido. El estado de memoria
virtual y el cambio de contexto deben ser reproducidos
exactamente. En algunos casos, incluso el trfico de red tendra que
volverse a crear!
Los datos se debern establecer y restablecer a sus valores
originales.
Esta crea un ambiente de depuracin o pruebas no determinantico.
Recrear la misma secuencia de eventos con el fin de probar o depurar
un programa es a menudo complicado.
La razn de que estas cosas tendran que volver a crear es que todos
ellos pueden ayudar a determinar qu proceso o subproceso puede
ejecutar y en qu procesador pueden ejecutar.
Y es la mezcla particular de la ejecucin de procesos y subprocesos
que podra ser la razn de deadlock, condicin de carrera, u otro
problema.
28

Estas cuestiones tambin afectan a la programacin secuencial.


El tipo de previsibilidad que est presente en el modelo secuencial
simplemente no existe en la programacin concurrente.
Esto obliga al desarrollador a adquirir nuevas tcticas para probar y
depurar programas. Tambin requiere que El desarrollador encuentre
nuevas maneras de demostrar la correctitud de un programa.
La correctitud puede ser un concepto muy difcil de alcanzar para los
programas que impliquen sistemas complejos en paralelo.
El tratamiento de los procesos y subprocesos en diferentes entornos
de sistema operativo como Linux, Solaris, Darwin, y as
sucesivamente pueden variar. Algunos sistemas tienen hilos con
diferentes prioridades. Algunos sistemas tienen prioridades de misin
crtica, las prioridades de tiempo, las prioridades normales, las
prioridades de fondo, y as sucesivamente. Los sistemas operativos
pueden tener diferentes tipos de programadores, las diferentes
implementaciones de los mecanismos de IPC, y diferentes
implementaciones de hilos de ncleo en comparacin con las
discusiones de usuario.
Comunicar el diseo de los componentes multiprocesador
Existen muchas arquitecturas diferentes, cada una con sus
caractersticas. Esas diferencias se trasladan a diferentes
configuraciones de compilacin. Usar caractersticas de una
arquitectura en particular genera software que no es portable hacia
otras arquitecturas.
Exclusin Mutua
Los threads a veces deben proteger el acceso a posiciones de
memoria compartida. Haciendo eso se habilita a que solo un thread a
la vez tenga acceso a variables compartidas.
Tanto la lectura como la escritura deben estar protegidas. Muchos
threads leyendo la misma variable no es un problema. Cuando se
tienen varios threads escribiendo en la misma variable el orden de
ejecucin determina el valor final de la variable. Esto puede ser un
problema si el algoritmo originalmente era serial y luego se lo
paralelizo.

4 Condiciones requeridas para permitir Deadlock


-

Exclusin Mutua

Mantener y esperar

Sin expropiacin
29

Espera Circular

Algoritmos de Dekker
Para resolver el problema de la seccin critica
Solo est definido para 2 threads.
Hay mejores algoritmos como el de Lamport.
Mecanismos de sincronizacin
Hay recursos que solo permiten un nico acceso concurrente, o un
nmero limitado de accesos concurrentes, en estos casos es
necesario proteger el acceso a estos recursos, los mecanismos ms
conocidos son:
o Semaforos
o Readwrite locks
o Monitores
Estrategias para el uso de Thread
La estrategia determina la forma en que se va a emplear threading en
una aplicacin.
Modelo de Delegacin
En este modo un thread llamada jefe, crea a otros threads, llamados
trabajadores y le asigna una tarea a cada uno. El jefe debe esperar
hasta q todos los trabajadores completen su tarea para poder
continuar.
El propsito de un jefe es:
1. Crear todos los threads
2. Poner trabajo en la cola
3. Despertar a los trabajadores cuando exista trabajo para procesar
Los trabajadores:
1. Controlar los pedidos en la cola
2. Ejecutar la tarea asignada
3. Suspenderse si no hay mas tareas disponibles
Modelo Peer - to Peer
En este modelo todos los thread tienen las mismas responsabilidades,
un thread inicia al resto pero luego este se transforma en un
trabajador mas.

30

Modelo Productor Consumidor


Ac, existe un thread conocido como productor que genera datos,
para que sean procesador por los consumidores.
Concurrencia y Paralelismo
Concurrent programming is still more art than science.
Los trminos paralelo y concurrente empezaron a hacerse cada vez
ms conocidos gracias a la masificacin de los procesadores Multicore
en el mbito hogareo.
Siempre hubo confusin con estos trminos en otras reas de la
computacin. Cual es la diferencia? Hay diferencia? Son trminos
intercambiables?
Un sistema se dice concurrente si puede soportar 2 o mas acciones
en progreso al mismo tiempo. Un sistema se dice paralelo si puede
soportar 2 o ms acciones ejecutndose simultneamente.
El concepto clave y diferencia entre las definiciones es la frase en
progreso.
Una aplicacin concurrente tendr 2 o mas threads en progreso en
algn momento, esto quiere decir que una aplicacin tiene 2 threads
que van a ser intercambiados por el sistema operativo en un maquina
con un solo procesador. Estos threads van a estar en progreso en
medio de su ejecucin, al mismo tiempo.
En la ejecucin paralela debe haber mltiples procesadores
disponibles, en este caso 2 o ms threads pueden ser asignados a
procesadores diferentes y pueden correr simultneamente.
Paralelo es un subset de concurrente, se puede crear una aplicacin
concurrente que use mltiples hilos o procesos, pero si no se tienen
mltiples procesadores no se puede correr cdigo en paralelo.
El termino paralelo siempre se lo relaciono con el paso de mensajes o
memoria distribuida, con muchos nodos conectados va alguna red,
cada nodo con 1 o ms procesadores.
Hay tcnicas especficas de programacin para dividir el trabajo en y
compartir los datos.
La programacin utilizando threads es conocida como programacin
concurrente, ya que los threads con parte de el modelo de memoria
compartida, que encaja bien en maquinas con un solo procesador.

4.4

Modelos Tericos

Caractersticas nicas de memoria compartida


Declaraciones locales y thread local storage
31

Mientras que todo es compartido en memoria, a veces es necesario


tener variables o datos privados que son accedidos por un thread. El
thread local storage es un mecanismo para que cada thread pueda
tener un lugar privado donde guardar datos.
Modelo de diseo para algoritmos concurrentes
Descomposicin por Tareas
Todo algoritmo concurrente est compuesto por una coleccin de
tareas concurrentes. La idea es identificar partes del cdigo que son
independientes de otras. Generalmente existen dependencias entre
las tareas que deben respetarse.
La descomposicin se puede hacer con diferente granularidad.

Figura 5. Descomposicion de tareas

Hay 3 elementos clave que se deben considerar en toda


descomposicin por tareas:
Cules son las tareas y como estn definidas?
Cules son las dependencias entre las tareas y como puedo
satisfacerlas?
Cmo voy a asignar las tareas con los threads?
Descomposicin por Datos
En este caso tengo una gran cantidad de datos que debo procesarlos
con la misma secuencia de tareas, entonces divido los datos en
porciones y cada tarea realiza todos los procesos sobre cada porcin
de los datos.
Depende de la estructura de datos como se realiza la divisin, el caso
ms bsico el arreglo donde puedo asignar una parte a cada threads.
Otras estructuras pueden ser matrices, arboles, etc.
32

En el caso que las tareas requieran acceso a los vecinos se debern


manejar dependencias y coordinacin entre los threads.
Las 3 cosas a considerar para cada descomposicin por datos son:
Cmo debera dividir los datos en porciones?
Cmo puedo asegurar que cada tarea tiene acceso completo a los
datos?
Cmo asigno las porciones a los threads?

Figura 6. Descomposicion por datos

Amdahls Law
Antes de hacer un algoritmo paralelo generalmente se estima cual va
a ser la mejora en eficiencia.

Figura 7. Escalabilidad de Algoritmos

33

Concluye que la eficiencia de un algoritmo depende de la porcin de


cdigo que se ejecuta en forma serial. Por eso es esencial paralelizar
la mayor cantidad de cdigo posible.

Figura 8. Ley de Amdahls

Gustafson-Barsiss Law
Una de las crticas al Amdahls Law es que a medida que el numero
de cores aumenta, tambin aumente la cantidad de datos manejados,
Amdahls Law asume una cantidad fija de datos que todos los cores
son usados.
Gustafson-Barsis Law tiene en cuenta un incremento en el tamao de
los datos en proporcin al incremento en el numero de cores.
Mientras que Amdahls Law es una herramienta para predecir la
cantidad de incremento de velocidad que se puede lograr
paralelizando un cdigo serial, Gustafson-Barsis Law es usada para
calcular el incremento de velocidad de un cdigo paralelo existente.
La formula es Speedup p + (1 p) s
Reglas para Generar algoritmos paralelos
34

1 Identificar las partes realmente independientes


2 Implementar la concurrencia al mayor nivel posible
3 Planear la escalabilidad para tomar ventaja al aumento de numero
de cores
4 Hacer uso de libreras Thread-safe cuando sea posible
5 Usar el modelo de Thread correcto
6 Nunca asumir un orden particular de ejecucin
7 Usar Thread local storage cuando sea posible
8 Pensar en cambiar el algoritmo para tener una mejor chance de
paralelizar
Librerias de Threading
Existen muchas liberaras, que intentan abstraer la complejidad de las
estructuras paralelas, ofreciendo interfaces de alto nivel. Podemos
nombrar entre las ms conocidas a:
OpenMP, Intel Threading Building Blocks, Parallel Task, etc.
4.5

Patrones de programacin paralela en .Net Framework 4

Los patrones estn por todas partes, dando las mejores prcticas de
desarrollo de software y ayudando a sembrar nuevas generaciones de
desarrolladores con el conocimiento inmediato de direcciones
establecidas en una amplia gama de problemticas. Los patrones
representan repetidas soluciones comunes y exitosas (o en el caso
de anti-patrones, sin xito) que los desarrolladores han aplicado
varias veces en dominios particulares de arquitectura y
programacin. Con el tiempo, stas probadas prcticas los han
ayudado con nombres, altura y variaciones a proliferar en sus
aplicaciones e impulsar proyectos de muchos.
Los patrones no slo se manifiestan a nivel macro. Considerando que
los patrones de diseo cubren comnmente la estructura
arquitectnica o metodologas, la codificacin de patrones y la
construccin de mdulos tambin se manifiestan, en representacin
de formas tpicas de implementacin de un mecanismo
especfico. Estos patrones se han arraigado de forma tal que su uso a
diario en la codificacin se realiza con naturalidad sin siquiera pensar
en ello. Estos patrones representan soluciones a tareas comunes que
se encuentran en varias ocasiones.
Por supuesto, la bsqueda de buenos patrones bien puede ocurrir slo
despus de muchos intentos exitosos y fallidos de soluciones.
As, para nuevos espacios de problemas, puede tomar algn tiempo
para que stos ganen cierta reputacin. Ese es el lugar en donde hoy
se encuentra esta industria en lo que respecta a los patrones para la
programacin paralela. Si bien los desarrolladores en informtica de
35

alto rendimiento han tenido que desarrollar soluciones para


supercomputadoras y clusters durante dcadas, la necesidad de tales
experiencias apenas ha encontrado recientemente su camino a la
computacin personal, como las mquinas multincleo que se han
convertido en la norma para todos los usuarios. A medida que se
avanza con mltiples ncleos en la era de varios ncleos, asegurar
que todo el software sea escrito teniendo en mente el paralelismo y la
escalabilidad es crucial para el futuro de la industria de la
computacin. Esto hace que los patrones tengan un lugar crtico hacia
ese futuro en el espacio de la computacin paralela.
"En general, un 'chip multincleo' se refiere a ocho o menos ncleos
homogneos en el paquete de un mismo microprocesador, mientras
que un 'chip de varios ncleos' tiene ms de ocho posibles ncleos
heterogneos en un microprocesador. En un sistema de varios
ncleos, todos los ncleos comparten los recursos y servicios,
incluyendo la memoria y el acceso a disco, suministrado por el
sistema operativo. "-El Cambio de Varios Ncleos, (Microsoft Corp.,
2007).
En el. NET Framework 4, se ha aadido una gran cantidad de soporte
para manejar las necesidades comunes en la programacin paralela,
para ayudar a los desarrolladores hacer frente al difcil problema que
es la programacin para multincleos y de varios ncleos. La
programacin en paralelo es difcil por muchas razones y est
plagada de peligros que la mayora de los desarrolladores no han
experimentado. Las condiciones de carrera, estancamiento, inanicin,
inversiones de prioridad, bailes en dos fases, y bloqueo de convoyes
normalmente no tienen cabida en un mundo secuencial, y evitar
cuestiones como estas hace que los patrones de calidad sean lo ms
importante. Este nuevo soporte en el. NET Framework 4 ofrece
soporte para patrones paralelos claves a lo largo de la construccin
mdulos para ayudar a permitir implementaciones de otros nuevos
que surgen.
Fork - Join
Los patrones utilizados para bucles paralelos son en realidad un
subconjunto de un conjunto ms amplio de patrones centrados en
"fork / join". En patrones fork/join, el trabajo se bifurca de tal manera
que varias piezas de trabajo son puestas en marcha de forma
asincrnica. Ese mismo trabajo bifurcado ms tarde se une con el
fin de garantizar que todo el procesamiento se ha completado, y
potencialmente para recuperar los resultados de ese procesamiento si
no fue utilizado exclusivamente para comportamiento lateral. Los
bucles son un buen ejemplo de esto: se bifurca el proceso de las
iteraciones de los bucles y luego se unen de tal manera que el bucle
paralelo slo se completa cuando todo el procesamiento concurrente
se ha realizado. El nuevo espacio de nombres en el
System.Threading.Tasks del .NET Framework 4 contiene una cantidad
36

significativa de soporte para patrones fork/join. Adems de los


estructuras Parallel.For y Parallel.ForEach, el.NET Framework
proporciona el mtodo Parallel.Invoke, as como Task y los tipos Task
<TResult>. El nuevo tipo System.Threading.CountdownEvent tambin
proporciona ayuda a patrones fork/join , en particular, para cuando se
trata de modelos de programacin concurrente que no proporcionan
soporte integrado para las joins.
MapReduce
Es un algoritmo, similar al Divide y vencers. Se pueden encontrar en
Lisp y otros lenguajes funcionales.
Google popularizo el algoritmo utilizndolo para distribuir el trabajo
en miles de servidores.
La idea detrs de Map es tomar una coleccin de tem y asociarles un
valor para cada uno, para producir una coleccin de pares ClaveValor. El nmero de resultados de la operacin Map debe ser igual al
nmero de elementos de entrada.
En trminos de concurrencia, la operacin de armar los pares debe
ser completamente independiente para cada elemento de la
coleccin.
La operacin Reduce toma todos los pares resultado de la operacin
Map y realiza una reduccin de la coleccin, el propsito es tomar una
coleccin de datos y devolver un valor derivado de los tems.
Procesamiento Especulativo
La especulacin es el patrn de hacer algo que puede no ser
necesario cuando en realidad se necesita. Esto es cada vez ms
relevante para la computacin paralela, donde se puede tomar
ventaja de mltiples ncleos para hacer ms cosas de las que
realmente son necesarias. La especulacin va en prdida de
rendimiento a cambio de latencia reducida, mediante la utilizacin de
recursos para hacer ms trabajo de lo que del trabajo extra podra
obtenerse.
Hay muchos escenarios en donde mltiples mecanismos pueden
utilizarse para calcular un resultado, pero cunto tiempo tomar cada
mecanismo no se puede predecir de antemano. Con la computacin
en serie, se est obligado a escoger una y se espera que sea el ms
rpido. En cambio con la computacin paralela tericamente se
puede ejecutar todos en paralelo: una vez que se tenga un ganador,
se puede detener la ejecucin del resto de las operaciones.
La otra gran clasificacin del procesamiento especulativo gira en en
torno a la anticipacin: una aplicacin puede anticipar una necesidad
y hacer algn clculo sobre la base de esa suposicin. Prefetching,
conocida en hardware y sistemas operativos, es un ejemplo de
ello. Basndose en la experiencia y la heurstica, el sistema se
anticipa a que el programa va a necesitar un recurso en particular y
37

por lo tanto precarga ese recurso de manera que est disponible para
el momento en que sea necesario. Si el sistema adivina
correctamente, el resultado final es la mejora percibida en la
perfomance.
Task<TResult> en el. NET Framework 4 hace que sea muy sencillo de
implementar este tipo de lgica. Cuando el sistema anticipa que el
resultado de un clculo particular puede ser necesario, pone en
marcha un Task<TResult> para calcular el resultado.
4.7

Implementacin de Algoritmos paralelos

Para mostrar si realmente los algoritmos paralelos son mas eficientes


en maquinas con mas de un ncleo, se eligieron 3 casos con
diferentes caractersticas algortmicas.
Los 3 algoritmos se corrern en forma paralela y secuencial para
comprar como afecta la velocidad de ejecucin.
Primero, se evaluara el calculo del numero PI, este es un procesos que
requiere poder de computo y no depende de IO.
Luego se probara un correcto ortogrfico, que buscara dentro de un
diccionario de casi 200000 palabras, las 25 palabras ms parecidas
usando el algoritmo de distancia de Levenshtein14.
Y por ultimo, vamos a trabajar con una de las reas donde mayor
aplicacin tienen los algoritmos paralelos, el tratamiento de
imgenes. Vamos a realizar un fundido o blend de 2 imgenes, para
generar una tercera imagen con la combinacin de las anteriores.
Los ejemplos sern implementados utilizando Visual Studio 2010 y
Framework 4.0 en c#, ya que incluye un excelente soporte para el
desarrollo y prueba de algoritmos paralelos.
Calculo de PI
En este ejemplo, vamos a generar el numero PI utilizando operaciones
sucesivas.
La corrida para 100000000 de iteraciones muestra los siguientes
resultados:

14

http://es.wikipedia.org/wiki/Distancia_de_Levenshtein

38

Figura 9. Calculo de PI
00:00:02.7953053: 3,14159265359043 - SerialPi - 0x
00:00:02.1307372: 3,14159265358999 - ParallelPi - 1,3118958546366x
00:00:01.1064297: 3,14159265358982 - ParallelPartitionerPi 1,92577729972361x

Se demuestra que el algoritmo paralelo sin optimizaciones es mas


rpido que el secuencial, y el algoritmo optimizado es el doble de
rpido que la versin sin optimizar.
Correcto Ortogrfico
En este caso vamos a buscar las similitudes de una palabra contra un
diccionario, y mostrar las 10 mas parecidas o que tenga la menos
distancia entre ellas.

Figura 10. Corrector ortogrfico

39

Secuencial - Elapsed: Sec: 00:00:00.3904439


1. hel
2. hela
3. helco
4. heo
5. ohelo
6. velo
7. allo
8. alo
9. atelo
10. bela
Paralelo - Elapsed: Sec: 00:00:00.5267606
1. hel
2. hela
3. helco
4. velo
5. ohelo
6. heo
7. allo
8. alo
9. nevo
10. yeo

En este caso se observa que la versin secuencial es ligeramente mas


eficiente que su contraparte paralela, el motivo principal es la
sobrecarga generada por el particionamiento paralelo y la
sincronizacin entre los thread, pero tiene como ventaja la posibilidad
de cancelarse en cualquier momento.
Blend de Imgenes
Esta prueba se realizara con 2 imgenes de 300dpi, una de
2500x1876 pixeles y la otra de 2400 x 1800.
El algoritmo recorre todos los pixeles de las 2 imgenes y realiza una
operacin matemtica, para generar el valor del pxel resultante.
Este es el resultado de la versin secuencial, donde se observa que
tardo 00:00:00.1280938 milsimas de segundo en completar la
operacin.

Figura 11. Blend de imagenes

40

A continuacin el resultado de la versin paralela, fue de


00:00:00.0356584 milisegundos, siendo 3.59 veces mas rpida que la
anterior.

Figura 12. Blend de imagenes

5.

Conclusiones

Segn hemos visto, es indudable que la computacin paralela ofrece


grandes ventajas en cuanto a performance para algunos problemas.
Pese a la complejidad extra que significa disear un algoritmo para
que se ejecute en forma paralela, los incrementos de performance
obtenidos lo justifican. Pero no todos los algoritmos se ven
beneficiados por este nuevo enfoque. Aquellos algoritmos que no
tengan tareas que puedan ser realmente ejecutadas en paralelo,
sufrirn un desempeo menor que al ejecutarse en una computadora
convencional.
La escalabilidad es otra caracterstica que puede llevarnos a pensar
que este paradigma ser el estndar en los prximos aos. Los
sistemas paralelos se pueden escalar mucho ms fcilmente que los
tradicionales, ya que en muchos casos el solo hecho de agregar ms
elementos de procesamiento permite incrementar la performance sin
embarcarse en un cambio de tecnologa.
Sin lugar a dudas, las industrias del Software y el Hardware, ya sean
del mbito cientfico, comercial, o de entretenimiento, estn
centrando sus esfuerzos en desarrollar este nuevo paradigma que ya
es considerado por muchos como el futuro a seguir.

41

6.

Referencias

[1] K. Hwang, F. A. Briggs, Computer Architecture and Parallel


Processing, McGraw-Hill,
New York, 1984.
[2] H. Narang, R. Flanery, J. Drake, Design of a Simulation Interface for
a Parallel Computing
Environment, Proc. ACM Southeastern Regional Conference, April
1990, to appear.
[3] G. A. Geist, M. T. Heath, B. W. Peyton, P. H. Worley, A Machine
Independent Communication
Library, Proc. Hypercube Concurrent Computers Conference 1989, J.
Gustafson ed.,
to appear.
[4] T. J. Gardner, et. al., DPUP : A Distributed Processing Utilities
Package, Computer Science
Technical Report, University of Colorado, Boulder, 1986.
[5] T. H. Dunigan, Hypercube Simulation on a Local Area Network, Oak
Ridge National
Laboratory Report ORNL/TM-10685, November 1988.
[6] C. Seitz, J. Seizovic, W. K. Su, The C programmers Abbreviated
Guide to Multicomputer
Programming, Caltech Computer Science Report, CS-TR-88-1, January
1988.
[7] M. Sullivan, D. Anderson, Marionette: A System for Parallel
Distributed Programming
Using a Master/Slave Model, Proc. 9th ICDCS, June 1989, pp. 181-188.
[8] G. Riccardi, B. Traversat, U. Chandra, A Master-Slaves Parallel
Computation Model,
Supercomputer Research Institute Report, Florida State University,
June 1989.
[9] J. S. Chase et. al., The Amber System: Parallel Programming on a
Network of Multiprocessors,
to appear in 12th SOSP, Litchfield Park, November 1989.
[10] D. W. Lozier, R. G. Rehm, Some Performance Comparisons for a
Fluid Dynamics Code,
Parallel Computing, Vol. 11, pp. 305-320, 1989.

42

[11] G. C. Fox, S. W. Otto, Matrix Algorithms on a Hypercube I: Matrix


Multiplication, Parallel
Computing, Vol. 4, pp. 17-31, 1987.
[12] Professional Multicore
0470289624 - 2008

Programming

Wrox

ISBN:978-

[13] The Art of Concurrency - O'Reilly Media - ISBN:978-0596521530 2009


[14] PVM : A Framework for Parallel Distributed Computing - V. S.
Sunderam - Department of Math and Computer Science Emory
University, Atlanta, GA 30322
[15] Patterns of Parallel Programming Understanding and Applying
Parallel Patterns with the .NET Framework 4 and Visual C# (Stephen
Toub, Parallel Computing Platform, Microsoft Corporation).
[16] https://computing.llnl.gov/tutorials/parallel_comp/
[17] http://en.wikipedia.org/wiki/Parallel_computing
[18] http://es.wikipedia.org/wiki/Computaci%C3%B3n_paralela

43

Anexo
Codigo Fuente de los Ejemplos
Calculo de PI
using
using
using
using
using

System;
System.Collections.Concurrent;
System.Diagnostics;
System.Linq;
System.Threading.Tasks;

class Program
{
const int num_steps = 100000000;
static TimeSpan oldElapsed = TimeSpan.MaxValue;
/// <summary>Main method to time various implementations of computing
PI.</summary>
static void Main(string[] args)
{
while (true)
{
Time(() => SerialPi(), "SerialPi");
Time(() => ParallelPi(), "ParallelPi");
Time(() => ParallelPartitionerPi(), "ParallelPartitionerPi");
Console.WriteLine("----");
Console.ReadLine();
}

/// <summary>Times the execution of a function and outputs both the elapsed time
and the function's result.</summary>
static void Time<T>(Func<T> work, string name)
{
var sw = Stopwatch.StartNew();
var result = work();
TimeSpan elapsed =sw.Elapsed;
string speed = oldElapsed == TimeSpan.MaxValue ? "0x" :
oldElapsed.TotalSeconds / elapsed.TotalSeconds+ "x";
Console.WriteLine(elapsed + ": " + result + " - " + name + " - " + speed);
oldElapsed = elapsed;
}
/// <summary>Estimates the value of PI using a for loop.</summary>
static double SerialPi()
{
double sum = 0.0;
double step = 1.0 / (double)num_steps;
for (int i = 0; i < num_steps; i++)
{
double x = (i + 0.5) * step;
sum = sum + 4.0 / (1.0 + x * x);
}
return step * sum;
}
/// <summary>Estimates the value of PI using a Parallel.For.</summary>
static double ParallelPi()

44

double sum = 0.0;


double step = 1.0 / (double)num_steps;
object monitor = new object();
Parallel.For(0, num_steps, () => 0.0, (i, state, local) =>
{
double x = (i + 0.5) * step;
return local + 4.0 / (1.0 + x * x);
}, local => { lock (monitor) sum += local; });
return step * sum;

/// <summary>Estimates the value of PI using a Parallel.ForEach and a range


partitioner.</summary>
static double ParallelPartitionerPi()
{
double sum = 0.0;
double step = 1.0 / (double)num_steps;
object monitor = new object();
Parallel.ForEach(Partitioner.Create(0, num_steps), () => 0.0, (range, state, local)
=>
{
for (int i = range.Item1; i < range.Item2; i++)
{
double x = (i + 0.5) * step;
local += 4.0 / (1.0 + x * x);
}
return local;
}, local => { lock (monitor) sum += local; });
return step * sum;
}
}

Corrector Ortogrfico
using
using
using
using
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
System.Text;
System.IO;
System.Threading;
System.Diagnostics;
System.Threading.Tasks;

namespace SpellChecker
{
class Program
{
const int NUM_SUGGESTIONS = 10;
static List<string> _words = new List<string>(200000);
static int _maxWordLength;
static void Main(string[] args)
{
using (StreamReader reader = new StreamReader("english-words.95"))
{
string line;
while ((line = reader.ReadLine()) != null)
{
string word = line.Trim().ToLower();
if (!String.IsNullOrEmpty(word))
{

45

}
}

_words.Add(word);
if (word.Length > _maxWordLength) _maxWordLength = word.Length;

MakeSuggestions("helo", true);
MakeSuggestions("helo", false);
Console.ReadLine();
}
private static void MakeSuggestions(string text, bool sequential)
{
if (String.IsNullOrEmpty(text))
{
return;
}
// Time the operation and kick it of
Stopwatch sw = Stopwatch.StartNew();
Task.Factory.StartNew(() =>
{
List<string> results = null;
if (sequential)
{
var distanceMatrix = new int[_maxWordLength + 1, _maxWordLength + 1];
results = _words
.Select(word => new { Word = word, Distance =
LevenshteinDistance(word, text, distanceMatrix) })
.OrderBy(p => p.Distance)
.Take(NUM_SUGGESTIONS)
.Select(p => p.Word)
.ToList();
}
else
{
using (var distanceMatrix = new ThreadLocal<int[,]>(() => new
int[_maxWordLength + 1, _maxWordLength + 1]))
{
results = _words
.AsParallel()
.Select(word => new { Word = word, Distance =
LevenshteinDistance(word, text, distanceMatrix.Value) })
.TakeTop(p => p.Distance, NUM_SUGGESTIONS) // Or .OrderBy(p =>
p.Distance).Take(NUM_SUGGESTIONS)
.Select(p => p.Word)
.ToList();
}
}
sw.Stop();
return new { Results = results, Time = sw.Elapsed }; // Return both the
spelling suggestions and the elapsed time
}).ContinueWith(t =>
{
// Display the results
DisplayResult(sequential,t.Result.Results.Select((str, i) =>
string.Format("{0,2}. {1}", i + 1, str)),"Sec: " + t.Result.Time);
},TaskContinuationOptions.OnlyOnRanToCompletion);
}

46

private static void DisplayResult(bool sequential, IEnumerable<string> results,


string elapsed)
{
Console.WriteLine((sequential ? "Secuencial" : "Paralelo") + " - Elapsed:" +
elapsed);
foreach (var item in results)
{
Console.WriteLine(item);
}
}
/// <summary>Computes the Levenshtein Edit Distance between two
enumerables.</summary>
/// <param name="str1">The first string.</param>
/// <param name="str2">The second string.</param>
/// <param name="scratchDistanceMatrix">Scratch space to use for the
computation.</param>
/// <returns>The computed edit distance.</returns>
private static int LevenshteinDistance(string str1, string str2, int[,]
scratchDistanceMatrix)
{
// distance matrix contains one extra row and column for the seed values
for (int i = 0; i <= str1.Length; i++) scratchDistanceMatrix[i, 0] = i;
for (int j = 0; j <= str2.Length; j++) scratchDistanceMatrix[0, j] = j;
for (int i = 1; i <= str1.Length; i++)
{
int str1Index = i - 1;
for (int j = 1; j <= str2.Length; j++)
{
int str2Index = j - 1;
var cost = (str1[str1Index] == str2[str2Index]) ? 0 : 1;

+ cost;

int deletion = (i == 0) ? 1 : scratchDistanceMatrix[i - 1, j] + 1;


int insertion = (j == 0) ? 1 : scratchDistanceMatrix[i, j - 1] + 1;
int substitution = (i == 0 || j == 0) ? cost : scratchDistanceMatrix[i - 1, j - 1]
scratchDistanceMatrix[i, j] = Math.Min(Math.Min(deletion, insertion),

substitution);
// Check for Transposition
if (i > 1 && j > 1 && (str1[str1Index] == str2[str2Index - 1]) &&
(str1[str1Index - 1] == str2[str2Index]))
{
scratchDistanceMatrix[i, j] = Math.Min(scratchDistanceMatrix[i, j],
scratchDistanceMatrix[i - 2, j - 2] + cost);
}
}
}
// Levenshtein distance is the bottom right element
return scratchDistanceMatrix[str1.Length, str2.Length];
}

Blend de Imgenes
partial class MainForm
{

47

/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed;
otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.btnSequential = new System.Windows.Forms.Button();
this.btnParallel = new System.Windows.Forms.Button();
this.lblTime = new System.Windows.Forms.Label();
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.pbInput1 = new System.Windows.Forms.PictureBox();
this.splitContainer2 = new System.Windows.Forms.SplitContainer();
this.pbInput2 = new System.Windows.Forms.PictureBox();
this.pbOutput = new System.Windows.Forms.PictureBox();
this.lblSpeedup = new System.Windows.Forms.Label();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout();
this.splitContainer1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pbInput1)).BeginInit();
this.splitContainer2.Panel1.SuspendLayout();
this.splitContainer2.Panel2.SuspendLayout();
this.splitContainer2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pbInput2)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pbOutput)).BeginInit();
this.SuspendLayout();
//
// btnSequential
//
this.btnSequential.Enabled = false;
this.btnSequential.Location = new System.Drawing.Point(12, 12);
this.btnSequential.Name = "btnSequential";
this.btnSequential.Size = new System.Drawing.Size(75, 23);
this.btnSequential.TabIndex = 0;
this.btnSequential.Text = "Sequential";
this.btnSequential.UseVisualStyleBackColor = true;
this.btnSequential.Click
+=
System.EventHandler(this.btnBlendImages_Click);
//
// btnParallel
//

48

new

this.btnParallel.Enabled = false;
this.btnParallel.Location = new System.Drawing.Point(93, 12);
this.btnParallel.Name = "btnParallel";
this.btnParallel.Size = new System.Drawing.Size(75, 23);
this.btnParallel.TabIndex = 1;
this.btnParallel.Text = "Parallel";
this.btnParallel.UseVisualStyleBackColor = true;
this.btnParallel.Click += new System.EventHandler(this.btnBlendImages_Click);
//
// lblTime
//
this.lblTime.AutoSize = true;
this.lblTime.Location = new System.Drawing.Point(174, 17);
this.lblTime.Name = "lblTime";
this.lblTime.Size = new System.Drawing.Size(0, 13);
this.lblTime.TabIndex = 2;
//
// splitContainer1
//
this.splitContainer1.Anchor = ((System.Windows.Forms.AnchorStyles)
((((System.Windows.Forms.AnchorStyles.Top
|
System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.splitContainer1.Location = new System.Drawing.Point(12, 41);
this.splitContainer1.Name = "splitContainer1";
//
// splitContainer1.Panel1
//
this.splitContainer1.Panel1.Controls.Add(this.pbInput1);
//
// splitContainer1.Panel2
//
this.splitContainer1.Panel2.Controls.Add(this.splitContainer2);
this.splitContainer1.Size = new System.Drawing.Size(860, 269);
this.splitContainer1.SplitterDistance = 286;
this.splitContainer1.TabIndex = 3;
//
// pbInput1
//
this.pbInput1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.pbInput1.Cursor = System.Windows.Forms.Cursors.Hand;
this.pbInput1.Dock = System.Windows.Forms.DockStyle.Fill;
this.pbInput1.Location = new System.Drawing.Point(0, 0);
this.pbInput1.Name = "pbInput1";
this.pbInput1.Size = new System.Drawing.Size(286, 269);
this.pbInput1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pbInput1.TabIndex = 0;
this.pbInput1.TabStop = false;
this.toolTip1.SetToolTip(this.pbInput1, "Double-click to load new image");
this.pbInput1.DoubleClick
+=
new
System.EventHandler(this.pbInput_DoubleClick);
//
// splitContainer2
//
this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainer2.Location = new System.Drawing.Point(0, 0);
this.splitContainer2.Name = "splitContainer2";
//
// splitContainer2.Panel1
//
this.splitContainer2.Panel1.Controls.Add(this.pbInput2);
//

49

// splitContainer2.Panel2
//
this.splitContainer2.Panel2.Controls.Add(this.pbOutput);
this.splitContainer2.Size = new System.Drawing.Size(570, 269);
this.splitContainer2.SplitterDistance = 285;
this.splitContainer2.TabIndex = 0;
//
// pbInput2
//
this.pbInput2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.pbInput2.Cursor = System.Windows.Forms.Cursors.Hand;
this.pbInput2.Dock = System.Windows.Forms.DockStyle.Fill;
this.pbInput2.Location = new System.Drawing.Point(0, 0);
this.pbInput2.Name = "pbInput2";
this.pbInput2.Size = new System.Drawing.Size(285, 269);
this.pbInput2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pbInput2.TabIndex = 1;
this.pbInput2.TabStop = false;
this.toolTip1.SetToolTip(this.pbInput2, "Double-click to load new image");
this.pbInput2.DoubleClick
+=
new
System.EventHandler(this.pbInput_DoubleClick);
//
// pbOutput
//
this.pbOutput.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.pbOutput.Dock = System.Windows.Forms.DockStyle.Fill;
this.pbOutput.Location = new System.Drawing.Point(0, 0);
this.pbOutput.Name = "pbOutput";
this.pbOutput.Size = new System.Drawing.Size(281, 269);
this.pbOutput.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pbOutput.TabIndex = 1;
this.pbOutput.TabStop = false;
this.pbOutput.DoubleClick
+=
new
System.EventHandler(this.pbOutput_DoubleClick);
//
// lblSpeedup
//
this.lblSpeedup.Anchor = ((System.Windows.Forms.AnchorStyles)
((System.Windows.Forms.AnchorStyles.Top
|
System.Windows.Forms.AnchorStyles.Right)));
this.lblSpeedup.AutoSize = true;
this.lblSpeedup.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F,
System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblSpeedup.ForeColor = System.Drawing.Color.Green;
this.lblSpeedup.Location = new System.Drawing.Point(869, 17);
this.lblSpeedup.Name = "lblSpeedup";
this.lblSpeedup.Size = new System.Drawing.Size(0, 13);
this.lblSpeedup.TabIndex = 4;
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(884, 322);
this.Controls.Add(this.lblSpeedup);
this.Controls.Add(this.splitContainer1);
this.Controls.Add(this.lblTime);
this.Controls.Add(this.btnParallel);
this.Controls.Add(this.btnSequential);
this.Name = "MainForm";
this.Text = "Blend Images";
this.splitContainer1.Panel1.ResumeLayout(false);
this.splitContainer1.Panel2.ResumeLayout(false);

50

this.splitContainer1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.pbInput1)).EndInit();
this.splitContainer2.Panel1.ResumeLayout(false);
this.splitContainer2.Panel2.ResumeLayout(false);
this.splitContainer2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.pbInput2)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pbOutput)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion

private
private
private
private
private
private
private
private
private
private

using
using
using
using
using
using
using
using

System.Windows.Forms.Button btnSequential;
System.Windows.Forms.Button btnParallel;
System.Windows.Forms.Label lblTime;
System.Windows.Forms.SplitContainer splitContainer1;
System.Windows.Forms.PictureBox pbInput1;
System.Windows.Forms.SplitContainer splitContainer2;
System.Windows.Forms.PictureBox pbInput2;
System.Windows.Forms.PictureBox pbOutput;
System.Windows.Forms.Label lblSpeedup;
System.Windows.Forms.ToolTip toolTip1;

System;
System.Collections.Concurrent;
System.Diagnostics;
System.Drawing;
System.Drawing.Imaging;
System.Threading.Tasks;
System.Windows.Forms;
Microsoft.Drawing;

namespace Microsoft.ParallelComputingPlatform.ParallelExtensions.Samples
{
public partial class MainForm : Form
{
private TimeSpan? _lastSequentialTime, _lastParallelTime;
public MainForm() { InitializeComponent(); }
private void pbInput_DoubleClick(object sender, EventArgs e)
{
// Get the PictureBox that caused this event
PictureBox pb = sender as PictureBox;
if (pb == null) return;
// Open a dialog to let the user select an image
using (var ofd = new OpenFileDialog())
{
if (ofd.ShowDialog() == DialogResult.OK)
{
// Store the new image into the PictureBox
Image newImage = new Bitmap(ofd.FileName);
Image oldImage = pb.Image;
pb.Image = newImage;
if (oldImage != null) oldImage.Dispose();
}
}
// Make sure the btns are enabled if they should be

51

_lastSequentialTime = _lastParallelTime = null;


btnSequential.Enabled = btnParallel.Enabled = (pbInput1.Image != null &&
pbInput2.Image != null);
}
private void pbOutput_DoubleClick(object sender, EventArgs e)
{
if (pbOutput.Image != null)
{
// Open a dialog to let the user select an output path
using (var sfd = new SaveFileDialog())
{
sfd.Filter = "Bitmap Images|*.bmp";
if (sfd.ShowDialog(this) == DialogResult.OK)
{
// Save the image as a bitmap to the selected location
pbOutput.Image.Save(sfd.FileName, ImageFormat.Bmp);
}
}
}
}
private void btnBlendImages_Click(object sender, EventArgs e)
{
// Determine whether to run sequentially or in parallel based on the
// button click that got us here
bool isParallel = sender == btnParallel;
// Get the images
Bitmap bmp1 = (Bitmap)pbInput1.Image;
Bitmap bmp2 = (Bitmap)pbInput2.Image;
if (bmp1 == null || bmp2 == null) return;
// Clear the output image
Image oldOutput = pbOutput.Image;
pbOutput.Image = null;
if (oldOutput != null) oldOutput.Dispose();
// Resize the second image's size to match that of the first
if (bmp1.Size != bmp2.Size)
{
Bitmap newBmp2 = new Bitmap(bmp1.Width, bmp1.Height);
using (var g = Graphics.FromImage(newBmp2)) g.DrawImage(bmp2, 0, 0,
newBmp2.Width, newBmp2.Height);
pbInput2.Image = newBmp2;
bmp2.Dispose();
bmp2 = newBmp2;
}
// Disable the form to prevent user interaction while merging
EnableOrDisableFormControls(false);
lblSpeedup.Text = string.Empty;
lblTime.Text = string.Empty;
// Do the work in the background
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(delegate
{
// Blend the images (and time the operation)
TimeSpan time;
Bitmap output = BlendImages(bmp1, bmp2, .5, isParallel, out time);
// Update our stats

52

if (isParallel) _lastParallelTime = time;


else _lastSequentialTime = time;
string speedup = (_lastSequentialTime != null && _lastParallelTime != null) ?
string.Format("Speedup: {0:F2}", _lastSequentialTime.Value.TotalSeconds /
_lastParallelTime.Value.TotalSeconds) + "x" :
string.Empty;
// Pass results to the UI
return new { output, time, speedup };
}).ContinueWith(t =>
{
EnableOrDisableFormControls(true);
pbOutput.Image = t.Result.output;
lblTime.Text = "Time: " + t.Result.time.ToString();
lblSpeedup.Text = t.Result.speedup;
lblSpeedup.Location = new Point(splitContainer1.Right - lblSpeedup.Width,
lblSpeedup.Location.Y);
}, uiScheduler);
}
internal unsafe static Bitmap BlendImages(Bitmap start, Bitmap end, double blend,
bool parallel, out TimeSpan time)
{
// Validate parameters
if (start.Width != end.Width || start.Height != end.Height)
throw new ArgumentException("The sizes of images do not match.");
if (blend < 0 || blend > 1)
throw new ArgumentOutOfRangeException("blend", blend, "Must be in the
range [0.0,1.1].");
// Create the output image
int width = start.Width, height = start.Height;
Bitmap output = new Bitmap(width, height);
var sw = new Stopwatch();
// Blend the input images into the output
using (FastBitmap fastOut = new FastBitmap(output))
using (FastBitmap fastStart = new FastBitmap(start))
using (FastBitmap fastEnd = new FastBitmap(end))
{
if (parallel)
{
// Blend the images in parallel
sw.Restart();
Parallel.For(0, height, j =>
{
PixelData* outPixel = fastOut.GetInitialPixelForRow(j);
PixelData* startPixel = fastStart.GetInitialPixelForRow(j);
PixelData* endPixel = fastEnd.GetInitialPixelForRow(j);
for (int i = 0; i < width; i++)
{
// Blend the input pixels into the output pixel
outPixel->R = (byte)((startPixel->R * blend) + .5 + (endPixel->R * (1 blend))); // .5 for rounding
outPixel->G = (byte)((startPixel->G * blend) + .5 + (endPixel->G * (1 blend)));
outPixel->B = (byte)((startPixel->B * blend) + .5 + (endPixel->B * (1 blend)));
outPixel++;
startPixel++;
endPixel++;

53

}
});
sw.Stop();
}
else
{
// Blend the images sequentially
sw.Restart();
for(int j=0; j<height; j++)
{
PixelData* outPixel = fastOut.GetInitialPixelForRow(j);
PixelData* startPixel = fastStart.GetInitialPixelForRow(j);
PixelData* endPixel = fastEnd.GetInitialPixelForRow(j);
for (int i = 0; i < width; i++)
{
// Blend the input pixels into the output pixel
outPixel->R = (byte)((startPixel->R * blend) + .5 + (endPixel->R * (1 blend))); // .5 for rounding
outPixel->G = (byte)((startPixel->G * blend) + .5 + (endPixel->G * (1 blend)));
outPixel->B = (byte)((startPixel->B * blend) + .5 + (endPixel->B * (1 blend)));
outPixel++;
startPixel++;
endPixel++;

}
}
sw.Stop();

// Return the new image


time = sw.Elapsed;
return output;

private void EnableOrDisableFormControls(bool enable)


{
btnParallel.Enabled = enable;
btnSequential.Enabled = enable;
splitContainer1.Enabled = enable;
}

54