Trabajo de introducción a la programación paralela. Este pequeño trabajo ha sido realizado para la asignatura de programación paralela del curso de adaptación universitario desde Ciclo Formativo de Grado Superior a la UCAM.
2. PROGRAMACIÓN PARALELA Autor: Francisco Mayorgas Siles
Página 1 de 12
ÍNDICE
1. Introducción .............................................................................................................................. 2
2. Antecedentes ............................................................................................................................ 2
3. Desarrollo.................................................................................................................................. 3
3.1. Tipos de paralelismo .......................................................................................................... 3
3.2. Diseño de programas paralelos.......................................................................................... 4
3.2.1. Descomposición (Particionamiento)........................................................................... 5
3.2.2. Asignación (Aglomeración): ........................................................................................ 6
3.2.3. Orquestación (Comunicación):.................................................................................... 6
3.2.4. Mapeo ......................................................................................................................... 7
3.3. Metodologías de programación paralela........................................................................... 8
3.3.1. Modelo de paralelismo de datos................................................................................. 8
3.3.2. Modelo de paso de mensajes...................................................................................... 9
3.3.3. Modelo de memoria compartida................................................................................ 9
3.4. Estrategias de programación paralela (compilación)......................................................... 9
4. Ventajas e inconvenientes ...................................................................................................... 10
5. Conclusiones............................................................................................................................ 10
Bibliografía .................................................................................................................................. 11
Créditos y licencia ....................................................................................................................... 12
3. PROGRAMACIÓN PARALELA Autor: Francisco Mayorgas Siles
Página 2 de 12
1. Introducción
Sin duda alguna si algo caracteriza al ser humano es la evolución; y como parte de dicha
evolución, la ciencia aplicada a la tecnología ha propulsado que hoy en día tengamos
máquinas potentes y complejas donde la multitarea es una realidad y que han hecho
posible la paralelización real que debía ser emulada en los procesadores de un solo
núcleo.
Así, tras los primeros paradigmas de la programación paralela, desde hace años
disponemos realmente de las herramientas para realizar la misma de manera real, y no
emulada, aprovechando al máximo los recursos de la máquina para la ejecución de
nuestros programas y minimizar los tiempos de ejecución.
Realmente la definición de programación paralela podemos localizarla en muchos libros
y sitios de internet, pero básicamente siempre es la misma y si la observamos podemos
asimilar el concepto al “Divide y Vencerás”, algoritmo muy empleado en Informática. Tal
y como citan los autores de la página http://ferestrepoca.github.io/paradigmas-de-
programacion:
"Divida un gran problema en varios pequeños y resuélvalos al mismo tiempo" (Bernal y
otros, 2021)
Además de la cita encontramos la siguiente definición y comparativa con la
programación tradicional o secuencial:
La computación paralela es el uso de múltiples recursos computacionales para resolver
un problema. Se distingue de la computación secuencial en que varias operaciones
pueden ocurrir simultáneamente. (Bernal y otros, 2021)
2. Antecedentes
Desde hace muchos años se han buscado formas de mejorar el rendimiento, en la
programación secuencial se confiaba en, la mejora de los lenguajes de programación y
la arquitectura de las máquinas, pero finalmente una variable importante para el
rendimiento es cómo el programador realizaba dicho programa.
En este aspecto cabe destacar la figura de Charles Babbage quien en 1837 describe
por primera vez su idea de la máquina analítica y en 1842 Luigi Federico Menabrea
realizará la primera publicación en Frances describiendo la misma. (Wikipedia, La
máquina analítica, 2021)
Así comenzaría el origen de la teoría de la paralelización, impulsada por máquinas como
el IBM 704 que era capaz de ejecutar aritmética en coma flotante mediante comandos
de manera automatizada (1954).
En 1958 Stanley Gil analiza la programación paralela e introduce los términos de
ramificación y espera. Este mismo año los investigadores de IBM, John Cocke y Daniel
Slotnick debaten, por primera vez, sobre el uso de la paralelización para cálculos
numéricos. (EcuRed, 2021) (Bernal y otros, 2021)
4. PROGRAMACIÓN PARALELA Autor: Francisco Mayorgas Siles
Página 3 de 12
En 1962 Burroughs Corporation crea un ordenador de 4 procesadores y con acceso a
un máximo de 16 módulos de memoria.
En 1967 Gene Amdahl y Daniel Slotnick debaten sobre la viabilidad del procesamiento
en paralelo, derivando en la Ley de Amdahl sobre límites de aceleración por el
paralelismo.
En 1968, tras varios años de estudio (desde 1965) sobre la sección crítica, Esdger W.
Dijkstra proporciona una solución elegante a la exclusión mutua, mediante los
semáforos binarios. Uno de los mayores problemas en la paralelización.
Durante el paso de los años se diseñaron y construyeron máquinas que pudiesen
manejar 4, 8, 256 o más procesadores, pero en la actualidad prácticamente todos los
ordenadores que manejamos en casa y puestos de trabajo se basan en la arquitectura
Von Neumann y con procesadores que incluyen varios núcleos, lo que ha hecho que la
programación paralela sea cada vez más utilizada, a pesar de su complejidad.
También hay que destacar que las grandes máquinas siguen aprovechando su
capacidad arquitectónica para disponer de N procesadores con un número de N cores,
lo que ha llevado al crecimiento en la potencia de proceso y trabajo paralelizado en
ámbitos de analítica de datos y científicos, sobre todo.
3. Desarrollo
Aunque hoy en día lo que más prolifera es la programación paralela basada en hilos
(threads), lo cierto es que no es la única forma de programación paralela que sigue
vigente y se usan distintas formas de programación dependiendo del tipo de problema
a resolver o inclusive de las máquinas en las que se va a ejecutar el programa.
3.1. Tipos de paralelismo
Dentro del paralelismo podemos encontrar diferentes tipos:
▪ A nivel de bit: Consiste en aprovechar al máximo la capacidad de ejecución de
instrucciones del procesador, es decir, el tamaño que puede manejar por
instrucción el procesador. De esta manera si queremos hacer la suma de dos
enteros en un procesador de 64 bits, podríamos realizar varias sumas a la vez,
pero sin embargo en procesadores antiguos el número de operaciones al mismo
tiempo se reduciría proporcionalmente al tamaño de instrucción que pueda
procesar.
▪ A nivel de instrucción: En este caso las sentencias del programa se agrupan y
ejecutan en paralelo teniendo en cuenta un orden coherente que no afecta al
resultado final. Los procesadores modernos utilizan para el control de las
instrucciones un pipeline que facilita la ejecución paralela de las mismas.
La siguiente ilustración representa gráficamente la diferencia entre el uso de
5. PROGRAMACIÓN PARALELA Autor: Francisco Mayorgas Siles
Página 4 de 12
pipeline o no en la ejecución de dos instrucciones que deben realizar varias
etapas.
Figura 1: Uso de Pipeline en paralelización de instrucciones (Bernal y otros,
2021)
▪ A nivel de tarea: Consiste en dividir el problema en tareas más pequeñas que
pueden ser ejecutadas en paralelo.
Ejemplo: Para obtener un informe se podrían hacer las siguientes tareas; calcular
la media aritmética de una serie de números, realizar el sumatorio de los
números o comprobar cuántos números son superiores a 10.
▪ A nivel de datos: Se divide un mismo dato en partes y se asigna cada parte a un
procesador, se realizarán las mismas operaciones en cada procesador con su
parte de los datos.
Ejemplo, en un número muy largo localizar cuantas veces aparece X número.
3.2. Diseño de programas paralelos
Cuando vamos a enfrentarnos al diseño de una aplicación paralela es conveniente
seguir una serie de etapas que nos ayudarán a identificar las tareas que debemos crear,
como manejar los datos, las comunicaciones entre procesos, etc.
Ian Foster describe las etapas que deben seguirse para el diseño de una aplicación
paralela en su libro “Designing and Building Parallel Progrmas”, donde ilustra con la
siguiente imagen las mismas.
6. PROGRAMACIÓN PARALELA Autor: Francisco Mayorgas Siles
Página 5 de 12
Figura 2: Etapas del proceso de paralelización (Foster, 2019)
3.2.1. Descomposición (Particionamiento)
La descomposición consiste en dividir el problema en tareas más pequeñas, las
tareas deben ser similares en tamaño y proceso para que cada procesador tenga la
misma carga de trabajo. Además, no deben hacer las mismas funciones de cómputo
o almacenamiento.
Es importante a la hora de realizar la división de tareas que se deben crear más
tareas que procesadores, ya que si no sería poco rentable.
El objetivo es que si el problema crece las tareas no crezcan en tamaño, si no en
número de tareas.
La descomposición puede dividirse en dos tipos:
▪ Del Dominio:
Primero se dividen los datos en grupos equitativos de menor tamaño y
posteriormente los cálculos con los que operan dichos datos.
Los datos no tienen por qué limitarse a la entrada, también pueden ser los de
salida o los que se manejan en la ejecución del programa.
▪ Funcional:
En este caso se centra en crear las tareas según los cálculos a realizar y
posteriormente los datos. Para que la descomposición sea completa tanto las
tareas como los datos deberían ser únicos, si los datos no son disjuntos será
necesario duplicarlos o comunicarlos entre tareas.
7. PROGRAMACIÓN PARALELA Autor: Francisco Mayorgas Siles
Página 6 de 12
3.2.2. Asignación (Aglomeración):
En esta etapa se trabaja a nivel de proceso, la idea es agrupar las tareas de manera
que se puedan asignar a los procesos concurrentes.
Para realizar la asignación habrá que fijarse en los siguientes factores:
▪ Balanceo de carga.
▪ Reducción de comunicaciones.
Además, será necesario revisar bien los datos y tareas para decidir qué tipo de
asignación emplear:
▪ Estática: La asignación se basa en la entrada y el problema a resolver, no varía
con la ejecución, por lo que es importante que los cálculos a realizar estén
predefinidos. No puede aplicarse en sistemas heterogéneos.
▪ Dinámica: En este caso la carga de trabajo se adapta en tiempo de ejecución,
ya que debido a las características del problema no es predecible.
3.2.3. Orquestación (Comunicación):
En esta etapa se toman decisiones para la comunicación y sincronización, para ello
es necesario saber qué modelo de programación y lenguaje se va a utilizar, ya que
dispondremos de diferentes herramientas.
Es importante centrarse en la estructura de los datos, los mensajes, sincronización
de procesos y comunicación de datos entre los mismos. En definitiva, el objetivo es
reducir los costes de comunicación y sincronización, así como la eficiencia en el
manejo de los datos.
3.2.3.1. Patrones de comunicación
▪ Local: Cada tarea se comunica con tareas vecinas (poco volumen).
▪ Global: Cada tarea se comunica no sólo con las vecinas, si no con muchas
tareas.
▪ Estructurada: Se definen patrones de comunicación entre las tareas.
▪ No Estructurada: Al no dispones de patrones necesitará de algoritmos de
asignación y aumentará el coste.
▪ Estática: Las tareas no varían, por lo que siempre se sigue el mismo patrón.
▪ Dinámica: Los patrones se calculan en tiempo de ejecución, ya que las
condiciones cambian según las operaciones realizadas.
▪ Síncrona: La comunicación se produce de manera ordenada esperando
confirmaciones del receptor.
8. PROGRAMACIÓN PARALELA Autor: Francisco Mayorgas Siles
Página 7 de 12
▪ Asíncrona: Se realizan peticiones, aunque no se haya recibido confirmación del
receptor.
3.2.3.2. Patrones de sincronización (semáforos)
Existen numerosas técnicas de sincronización y la mayoría se basan en la idea
general de los semáforos, así podemos encontrar los patrones Mutex,
Conmutador, Barrera, Torniquete, etc.
No vamos a describir cada uno de ellos, pero debido a que es la base nos
centraremos en los semáforos.
Los semáforos aparecieron como respuesta a la región crítica, el mecanismo es
simple, pero muy efectivo, ya que básicamente consiste en marcar si un recurso
está disponible o está siendo utilizado, es decir, si tenemos permiso o no para
acceder a él; de esta manera aplicando la técnica del semáforo los lenguajes de
programación dotan de mecanismos de sincronización sencillos de manejar, pero
más efectivos y seguros que los semáforos originales.
Figura 3: Semáforos (Diaz y otros, 2021)
3.2.4. Mapeo
El mapeo consiste en indicar qué proceso/hilo (grupos creados en la etapa de
asignación) será asignado a cada procesador, con algunas estrategias, como colocar
procesos concurrentes en distintos procesadores o procesos que se comunican
constantemente entre sí en el mismo procesador, se podrá reducir el tiempo de
ejecución.
El mapeo no será necesario en máquinas con un único procesador o memoria
compartida.
9. PROGRAMACIÓN PARALELA Autor: Francisco Mayorgas Siles
Página 8 de 12
3.2.4.1. Técnicas generales de mapeo
▪ Estático:
✓ Evaluar tamaño de tareas, de datos e iteraciones.
✓ Asignación de las tareas antes de la ejecución.
▪ Dinámico:
✓ Se usará cunado las tareas sean creadas dinámicamente, pero también
es aplicable a tareas estáticas.
✓ Asignación de las tareas dinámicamente en la ejecución.
✓ Son complejos y no conviene usarlos para un alto volumen de datos por
tarea.
3.3. Metodologías de programación paralela
Las etapas de descomposición y asignación, que hemos visto, son prácticamente
iguales para todos los modelos de programación que vamos a ver:
▪ Modelo de paralelismo de datos
▪ Modelo de compartición de memoria
▪ Modelo de paso de mensajes
Pero sin embargo la Orquestación tiene una alta dependencia del modelo de
programación a implementar.
3.3.1. Modelo de paralelismo de datos
Orientado a los datos, se obtiene la concurrencia aplicando la misma operación sobre
los datos, dichas operaciones se realizan sobre un conjunto de datos.
Se corresponde con la técnica de programación paralela SIMD (Single Instruction,
Multiple Data), es decir, cada procesador ejecuta la misma operación sobre distintos
datos.
Es posible utilizar programación concurrente:
▪ Explícita: El programador debe desarrollar el algoritmo y utilizar las directivas
correspondientes a la distribución de datos y paralelización. El entorno de
desarrollo aporta herramientas para aplicar las directivas y manejar la
comunicación.
▪ Implícita: Es el propio compilador el que se encarga de detectar y ejecutar
iteraciones que pueden ser concurrentes al no necesitar el resultado de la
iteración previa para realizar la siguiente.
10. PROGRAMACIÓN PARALELA Autor: Francisco Mayorgas Siles
Página 9 de 12
3.3.2. Modelo de paso de mensajes
Se basa en la creación de procesos y el paso de mensajes entre los mismos, para
ello se utilizan las instrucciones send (envío de mensajes) y receive (lectura del
mensaje). Los mensajes pueden ser síncronos o asíncronos.
Se corresponde con la técnica de programación paralela MIMD (Multiple Instruction,
Multiple Data), es decir, cualquier procesador de la máquina puede ejecutar
diferentes instrucciones sobre distintos datos.
Librerías para el paso de mensaje:
Aunque durante mucho tiempo se ha utilizado como estándar la librería PVM (Parallel
Virtual Machine), y actualmente sigue en uso, lo cierto es que el estándar MPI
(Message Passing Interface) se está imponiendo debido a la facilidad de portabilidad
de las aplicaciones que hacen uso de la misma.
La librería MPI se ha implementado para casi todas las arquitecturas de memoria
distribuida y además está optimizada para el hardware en el que ejecuta, de ahí que
los programas que la utilizan sean tan portables y rápidos. (Wikipedia, MPI, 2021)
3.3.3. Modelo de memoria compartida
Los procesos comparten las direcciones del mapa de memoria, por lo que se requiere
el uso de la exclusión mutua para evitar que dos procesos entren al mismo tiempo
en la sección/región crítica.
La comunicación se realiza mediante variables compartidas.
Aunque está diseñado para el uso en arquitecturas de memoria compartida, también
puede ser utilizado en arquitecturas de memoria compartida, pero siempre y cuando
tengan soporte vía software de la memoria compartida.
Este modelo de programación resulta en ocasiones más cómodo que el paso por
mensajes, por eso es bastante utilizado, sobre todo con Hilos y el API OpenMP.
Las pautas para la programación de este modelo se podrían dividir en los siguientes
puntos:
1. Decidir la división del problema.
2. Crear y destruir cada proceso.
3. Sincronización de acceso a datos.
3.4. Estrategias de programación paralela (compilación)
▪ Paralelismo implícito (Automático):
El programador no controla como debe paralelizarse el código, ya que es el
propio compilador el que analiza, estructura y toma decisiones, centrándose en
las iteraciones.
El código generado no es óptimo.
11. PROGRAMACIÓN PARALELA Autor: Francisco Mayorgas Siles
Página 10 de 12
▪ Paralelismo explícito (Manual):
En este caso es el programador el que aplica las directivas para decidir la
paralelización, se apoya en las librerías y herramientas del lenguaje, se dispone
de más control, pero mayor complejidad de programación.
4. Ventajas e inconvenientes
VENTAJAS
• Permiten resolver grandes problemas.
• Permite conseguir mayor velocidad de ejecución.
• Permite realizar aplicaciones más escalables.
• Permite aprovechar la potencia de todos los procesadores.
• Permite mejor rendimiento en el balanceo de carga.
INCONVENIENTES
• Mayor posibilidad de errores en los datos y resultados.
• Dificultad en la sincronización y comunicación.
• Mayor consumo.
• Mayor dificultad en la programación.
• Mayor complejidad en el diseño del programa.
5. Conclusiones
Anteriormente a este trabajo he realizado programas en UNIX y JAVA, para paralelizar
procesos de tratamiento de datos y carga en bases de datos MongoDB, también he
recurrido a la programación de hilos en JAVA para realizar tareas en paralelo en algunos
programas de tipo productor-consumidor, pero realmente realizando este trabajo es
cuando he podido ver lo que realmente abarca el Mundo de la programación paralela.
Es un campo muy amplio, lleno de teorías, leyes, algoritmos y diversos patrones de
diseño y programación, he tenido que centrar el trabajo en la base de la misma, ya que
según leía y aprendía me he dado cuenta de que el trabajo se podría alargar en exceso
y seguramente sin llegar a profundizar en ningún aspecto.
Obviamente no todo debe ser programación paralela, hay que distinguir cuándo es
realmente necesario aplicar la misma, ya que el coste en el diseño y programación de
la misma, es elevado.
Hay campos que sin la programación paralela no habrían avanzado, es indiscutible que
la potencia de poder dividir las tareas y ejecutarlas a la vez en distintos procesadores
12. PROGRAMACIÓN PARALELA Autor: Francisco Mayorgas Siles
Página 11 de 12
otorga una potencia de análisis y computo de datos que hoy en día, en la era del Big
Data es muy necesaria.
Otro uso en el que se utiliza la programación paralela y en el que seguirá siendo cada
vez más necesaria es en los Sistemas operativos.
Pero para la mayoría de aplicaciones de escritorio no será necesario este tipo de
programación, por lo que se deberá evaluar siempre el coste y rendimiento para
determinar si es realmente necesario utilizar la programación paralela.
Bibliografía
Bernal, F., Albarracín, C., Gaona, J., Giraldo, L., Mosquera, C., Peña, S., . . . Baquero, C. (18 de
09 de 2021). Paradigmas de programación. Obtenido de Programación paralela:
http://ferestrepoca.github.io/paradigmas-de-
programacion/paralela/paralela_teoria/index.html
Cecilia, J. M. (22 de 09 de 2021). Campus Ilerna. (UCAM, Ed.) Obtenido de Campus Ilerna:
https://campus.ilerna.es/courses/4528/files/737078?module_item_id=303299
Cecilia, J. M. (22 de 09 de 2021). Campus Ilerna. (UCAM, Ed.) Obtenido de Campus Ilerna:
https://campus.ilerna.es/courses/4528/files/737095?module_item_id=303303
Diaz, B., Marquez, S., Vaca, C., Mendez Paez, K., Guevara Rocha, D. A., Torres, J. E., . . . Rozo
Urbina, J. E. (24 de 09 de 2021). ferestrepoca. Obtenido de ferestrepoca:
http://ferestrepoca.github.io/paradigmas-de-
programacion/progconcurrente/concurrente_teoria/index.html
EcuRed. (19 de 09 de 2021). EcuRed. Obtenido de EcuRed:
https://www.ecured.cu/Programaci%C3%B3n_paralela
Expósito Singh, D., Isaila, F., Higuero Alonso-Mardones, D., García Blas, J., & Bergua Guerra, B.
(18 de 09 de 2021). uc3m. Obtenido de OPENCOURSEWARE:
http://ocw.uc3m.es/ingenieria-informatica/arquitectura-de-computadores-
ii/materiales-de-clasee/mc-f-002-ii
Foster, I. (2019). Design and Building Parallel Programs. Reading (Massachusetts): Addison-
Wesley. Obtenido de https://www.mcs.anl.gov/~itf/dbpp/text/book.html
Ortiz, J. (22 de 09 de 2021). Teldat. Obtenido de Teldat:
https://www.teldat.com/blog/es/computacion-paralela-capacidad-procesamiento/
Universitat de València. (21 de 09 de 2021). Obtenido de Algoritmos paralelos:
https://informatica.uv.es/iiguia/ALP/materiales.htm
Wikipedia. (25 de 09 de 2021). Wikipedia. Obtenido de Wikipedia:
https://es.wikipedia.org/wiki/Interfaz_de_Paso_de_Mensajes
Wikipedia. (18 de 09 de 2021). WIKIPEDIA. Obtenido de WIKIPEDIA:
https://es.wikipedia.org/wiki/M%C3%A1quina_anal%C3%ADtica