Documentos de Académico
Documentos de Profesional
Documentos de Cultura
INTRODUCCION ................................................................................................................................... 3
1. Antecedentes .............................................................................................................................. 4
1.1. Evolución de los sistemas .................................................................................................... 4
Punto de vista de los Sistemas Operativos ................................................................................. 4
Punto de vista de la arquitectura ................................................................................................ 5
2. Vision general .............................................................................................................................. 6
2.1. ¿Qué es? .............................................................................................................................. 6
2.2. ¿Por qué usar la computación paralela? ........................................................................... 12
3. Conceptos básicos ..................................................................................................................... 15
3.1. Ley de Amdhal y ley de Gustafson .................................................................................... 15
3.2. Dependencias .................................................................................................................... 16
3.3. Condiciones de carrera, exclusión mutua, sincronización y desaceleración paralela ...... 17
3.4. Paralelismo de grano fino, grano grueso y paralelismo vergonzoso ................................ 19
3.5. Límites y costos de la programación paralela ................................................................... 19
Complejidad .............................................................................................................................. 19
Portabilidad ............................................................................................................................... 20
Requerimientos de recursos ..................................................................................................... 20
Escalabilidad .............................................................................................................................. 20
3.6. Tipos de paralelismo ......................................................................................................... 21
Paralelismo a nivel de BIT ......................................................................................................... 21
Paralelismo a nivel de Instrucción ....................................................................................... 22
Paralelismo de datos ................................................................................................................. 23
Paralelismo de tareas ................................................................................................................ 24
3.7. Arquitectura de la computadora de von Neumann .......................................................... 24
3.8. La taxonomia de Flynn ...................................................................................................... 25
3.8.1. SISD( Single Instruction, Single Data ) ....................................................................... 26
3.8.2. SIMD (Single Instruction, Multiple Data)................................................................... 27
3.8.3. MISD (Multiple Instruction, Single Data)................................................................... 29
3.8.4. MISD (Multiple Instruction, Multiple Data)............................................................... 29
3.9. Arquitecturas paralelas de memoria de computadora ..................................................... 34
3.9.1. Memoria compartida ................................................................................................ 34
3.9.2. Memoria distribuida .................................................................................................. 36
3.9.3. Memoria hibrida distribuida-compartida.................................................................. 37
4. Aplicaciones............................................................................................................................... 39
5. Terminologia ................................................................................ ¡Error! Marcador no definido.
6. Referencias ................................................................................................................................ 45
INTRODUCCION
Cada vez se está exigiendo mayor potencia de cálculo en las computadoras a nivel
científico, industrial, comercial. Cabe esperar que esta demanda se irá
incrementando en el futuro sobre todo en aplicaciones de simulación y tiempo real,
por tanto, existe una tendencia actual para alcanzar grandes capacidades de
elaboración de datos. Pero la velocidad en la computación tiene limitaciones
tecnológicas y lógicas.
La eficiencia de un computador depende directamente del tiempo requerido para
ejecutar una instrucción y del número de instrucciones que pueden ser ejecutadas
concurrentemente. Esta eficiencia puede ser incrementada por avances en la
arquitectura y por avances tecnológicos. Una vez incorporados estos avances,
mejorar la eficiencia de un procesador implica reducir el tiempo de los ciclos:
avances tecnológicos.
Las soluciones planteadas para esta demanda se pueden concretar en 2 líneas
importantes que son el Software y Hardware.
La solución de software consiste en la mejora de los algoritmos, para que estos se
ejecuten requiriendo el menor tiempo posible. Aunque los algoritmos poseen una
complejidad y necesidad de recursos que los limitan.
Las soluciones de Hardware consisten en mejoras en las tecnologías de las
computadoras para una mayor rapidez en la ejecución de instrucciones.
La solución que une el uso del Software y Hardware es el paralelismo, que por el
lado del hardware abarca la réplica de unidades de tratamiento de información con
el objetivo de repartir tareas entre las mismas y por el lado del software la
adaptación de los algoritmos a estas arquitecturas paralelas.
Todo esto impulsa al desarrollo de computadoras cada vez más potentes en las
que se disponen procesadores en paralelo, actuando simultáneamente. Las
ventajas de estos sistemas son notables por cuanto hacen uso de procesadores
estándar para alcanzar enormes velocidades de cálculo, del orden de Tera
instrucciones por segundo (1012 instrucciones) por segundo.
La necesidad de resolver problemas de manera eficiente y en el menor tiempo
posible ha hecho que se tengan que realizar mejoras en el poder computacional de
los computadores.
1. Antecedentes
En el año 1936 Alan Turing demostró que, al menos teóricamente, era posible
diseñar una maquina secuencial de propósito general capaz de llevar a cabo
eficientemente cualquier calculo que pudiese realizar una maquina secuencial de
propósito específico, diseñada por tanto para resolver de forma muy eficiente un
determinado tipo de cálculo.
Años más tarde Von Neumann realiza su propuesta de computador secuencial de
propósito general que refleja el trabajo de Turing en un modelo practico, conocido
como el nombre de “Computador de von Neumann”. En este modelo se han
basado la mayoría de computadores secuenciales construidos desde finales de los
años cuarenta hasta la actualidad.
EL modelo de von Neumann ha permitido y estimulado el desarrollo de lenguajes
de alto nivel, aplicaciones portables, ejecutables en cualquier computadora
secuencial con un buen rendimiento.
La búsqueda de un mayor rendimiento en las aplicaciones, que no eran
satisfechas por computadoras secuenciales, ha impulsado el desarrollo y
construcción de computadores paralelos, más aun en los años 80 estos
computadores paralelas tenían un rendimiento aceptable explotando los detalles
de la arquitectura de la maquina ya que muchas de las aplicaciones paralelas
producidas en ese entonces no podían adaptarse a todas las máquinas de la
época.
La diversidad de arquitecturas paralelas impidió el crecimiento de la computación
en paralelo, lo cual ha mejorado sustancialmente desde ese entonces. Desde los
noventa las diferentes clases de computadores paralelos están convergiendo a
una estructura cada vez más parecida y se ha ido evolucionando a un modelo
arquitectónico estándar, en un conjunto de pares procesador-memoria
interconectadas mediante una red de comunicación que permite el empleo de un
espacio de direcciones global.
Computación Paralela
La computación paralela es una técnica en la que muchas instrucciones se
ejecutan simultáneamente, operando sobre el principio de que problemas grandes,
se pueden dividir en unos más pequeños, que luego son resueltos
simultáneamente (paralelo), tiene las siguientes características:
Un problema se divide en partes discretas que pueden resolverse
simultáneamente
Cada parte se divide en una serie de instrucciones.
Las instrucciones de cada parte se ejecutan simultáneamente en diferentes
procesadores.
Se emplea un mecanismo general de control / coordinación.
El paralelismo es posible en sistemas multinúcleo, multiprocesador o distribuidos.
1
https://www.top500.org/statistics/list/
2.2. ¿Por qué usar la computación paralela?
El mundo real es masivamente paralelo
En el mundo natural, muchos eventos complejos e interrelacionados están ocurriendo al
mismo tiempo, pero dentro de una secuencia temporal.
En comparación con la computación en serie, la computación en paralelo es mucho más
adecuada para modelar, simular y comprender fenómenos complejos del mundo real.
Imaginemos modelar estos en serie:
Principales razones:
Ahorra tiempo y/o dinero:
En teoría, dedicar más recursos a una tarea acortará su tiempo hasta su
finalización, con posibles ahorros de costos.
Las computadoras paralelas se pueden construir a partir de componentes
baratos y básicos.
RESOLVER MÁS GRANDE / MÁS COMPLEJOS PROBLEMAS:
PROPORCIONAR CONCURRENCIA:
Un solo recurso de cómputo solo puede hacer una cosa a la vez. Múltiples
recursos de cómputo pueden hacer muchas cosas simultáneamente.
Ejemplo: las redes de colaboración proporcionan un lugar global donde
personas de todo el mundo pueden reunirse y realizar el trabajo
"virtualmente".
Ley relacionada a la de Amdahl, señala que el aumento de la velocidad con P procesadores es de:
Ambas leyes asumen que el tiempo de funcionamiento de la parte secuencial del programa es
independiente del número de procesadores. La ley de Amdahl supone que todo el problema es de
tamaño fijo, por lo que la cantidad total de trabajo que se hará en paralelo también es
independiente del número de procesadores, mientras que la ley de Gustafson supone que la
cantidad total de trabajo que se hará en paralelo varía linealmente con el número de
procesadores.
Ejemplo:
Supongamos que una tarea tiene dos partes independientes, A y B. B tarda aproximadamente 25%
del tiempo total. Con esfuerzo adicional, un programador puede hacer esta parte cinco veces más
rápida, pero esto reduce el tiempo de cálculo global por muy poco. Por otro lado, puede que sea
necesario poco trabajo para hacer que la parte A sea doble de rápida. Esto haría el cálculo mucho
más rápido que mediante la optimización de la parte B, a pesar de que B tiene una mayor
aceleración (5x frente a 2×).
3.2. Dependencias
Entender la dependencia de datos es fundamental en la implementación de algoritmos
paralelos. Ningún programa puede ejecutar más rápidamente que la cadena más larga de
cálculos dependientes (conocida como la ruta crítica), ya que los cálculos que dependen
de cálculos previos en la cadena deben ejecutarse en orden. Sin embargo, la mayoría de
los algoritmos no consisten sólo de una larga cadena de cálculos dependientes;
generalmente hay oportunidades para ejecutar cálculos independientes en paralelo.
Ejemplo:
Con dependencia:
1: función OperacionDep(a, b)
2: c: = a · b
3: d: = 3 · c
4: fin función
Sin dependencia:
1: función OperacionNoDep (a, b)
2: c: = a · b
3: d: b = 3 ·
4: e: = a + b
5: fin función
En este ejemplo, no existen dependencias entre las instrucciones, por lo que todos ellos
se pueden ejecutar en paralelo.
Hilo A Hilo B
Hilo A Hilo B
Un hilo bloqueará con éxito la variable V, mientras que el otro hilo no podrá
continuar hasta que V se desbloquee. Esto garantiza la correcta ejecución del
programa. Si bien los bloqueos son necesarios para asegurar la ejecución correcta
del programa, pueden ralentizar en gran medida un programa.
Bloquear múltiples variables utilizando cerraduras no atómicas introduce la
posibilidad de que el programa alcance un bloqueo mutuo (deadlock). Un bloqueo
atómico bloquea múltiples variables a la vez, si no puede bloquearlas todas, no se
bloquea ninguna de ellas. Si hay dos hilos y cada uno necesita bloquear las
mismas dos variables utilizando cerraduras no atómicas, es posible que un hilo
bloquee uno de ellas y el otro bloquee la segunda variable. En tal caso se produce
un bloqueo mutuo donde ningún hilo puede completar la ejecución.
Muchos programas paralelos requieren que sus subtareas actúen en sincronía.
Esto requiere el uso de una barrera. Las barreras se implementan normalmente
mediante un bloqueo. Una clase de algoritmos, conocida como algoritmos libres
de bloqueo y libres de espera, evitan el uso de bloqueos y barreras. Sin embargo,
este enfoque es generalmente difícil de implementar y requiere estructuras de
datos correctamente diseñadas.
No todas las paralelizaciones conllevan una aceleración. Por lo general, mientras
una tarea se divida en cada vez más hilos, estos hilos pasan una porción cada vez
mayor de su tiempo comunicándose entre sí. Eventualmente, la sobrecarga de
comunicación domina el tiempo empleado para resolver el problema, y la
paralelización adicional —dividir la carga de trabajo entre incluso más hilos—
aumenta la cantidad de tiempo requerido para terminar. Esto se conoce
como desaceleración paralela.
o Diseño
o Codificación
o Depuración
o Mantenimiento
Todos los problemas de portabilidad habituales asociados con los programas serie se
aplican a los programas paralelos. Por ejemplo, si utiliza las "mejoras" de los proveedores
en Fortran, C o C ++, la portabilidad será un problema.
A pesar de que existen estándares para varias API, las implementaciones diferirán en una
serie de detalles, a veces hasta el punto de requerir modificaciones de código para
efectuar la portabilidad.
Los sistemas operativos pueden jugar un papel clave en los problemas de portabilidad de
código.
Requerimientos de recursos
El objetivo principal de la programación en paralelo es disminuir el tiempo de reloj de la
pared de ejecución, sin embargo, para lograr esto, se requiere más tiempo de CPU.
La cantidad de memoria requerida puede ser mayor para los códigos paralelos que para
los códigos seriales, debido a la necesidad de replicar los datos y para los gastos generales
asociados con las bibliotecas y subsistemas de soporte paralelos.
Para los programas paralelos de ejecución corta, en realidad puede haber una disminución
en el rendimiento en comparación con una implementación en serie similar. Los costos
generales asociados con la configuración del entorno paralelo, la creación de tareas, las
comunicaciones y la terminación de tareas pueden representar una parte significativa del
tiempo total de ejecución para ejecuciones cortas.
Escalabilidad
Dos tipos de escalamiento basados en el tiempo para la solución: escala fuerte y escala débil.
Escala fuerte
o El tamaño total del problema permanece fijo a medida que se agregan más
procesadores.
Escalamiento débil
o El tamaño del problema por procesador se mantiene fijo a medida que se agregan
más procesadores. El tamaño total del problema es proporcional al número de
procesadores utilizados.
El aumento del tamaño de la palabra reduce el número de instrucciones que el procesador debe
ejecutar para realizar una operación en variables cuyos tamaños son mayores que la longitud de la
palabra.
Por ejemplo:
Cuando un procesador de 8 bits debe sumar dos enteros de 16 bits, el procesador primero
debe adicionar los 8 bits de orden inferior de cada número entero con la instrucción de
adición, a continuación, añadir los 8 bits de orden superior utilizando la instrucción de
adición con acarreo que tiene en cuenta el bit de acarreo de la adición de orden inferior,
en este caso un procesador de 8 bits requiere dos instrucciones para completar una sola
operación, en donde un procesador de 16 bits necesita una sola instrucción para poder
completarla.
Los procesadores modernos tienen “pipeline” de instrucciones de varias etapas. Cada etapa en
el pipeline corresponde a una acción diferente que el procesador realiza en la instrucción
correspondiente a la etapa; un procesador con un pipeline de N etapas puede tener hasta n
instrucciones diferentes en diferentes etapas de finalización.
El ejemplo canónico de un procesador segmentado es un procesador RISC, con cinco etapas: pedir
instrucción, decodificar, ejecutar, acceso a la memoria y escritura. El procesador Pentium 4tenía
un pipeline de 35 etapas.
Además del paralelismo a nivel de instrucción del pipelining, algunos procesadores pueden
ejecutar más de una instrucción a la vez. Estos son conocidos como procesadores superes calares.
Las instrucciones pueden agruparse juntas sólo si no hay dependencia de datos entre ellas.
Pipeline
• Técnica de implementación
• Persigue aumentar las prestaciones.
• Divide la ejecución de una instrucción en etapas.
• Cada etapa utiliza diferentes recursos.
• Permite solapar la ejecución de distintas instrucciones en diferentes etapas.
• Permite comenzar una instrucción en cada ciclo de reloj.
Conceptos Importantes:
Paralelismo de datos
El paralelismo de datos es el paralelismo inherente en programas con ciclos, que se centra en la
distribución de los datos entre los diferentes nodos computacionales que deben tratarse en
paralelo.
Paralelismo de tareas
El paralelismo de tareas es la característica de un programa paralelo en la que cálculos
completamente diferentes se pueden realizar en cualquier conjunto igual o diferente de datos.
Esto contrasta con el paralelismo de datos, donde se realiza el mismo cálculo en distintos o
mismos grupos de datos. El paralelismo de tareas por lo general no escala con el tamaño de un
problema.
Los ordenadores paralelos se pueden clasificar según el nivel de paralelismo que admite su
hardware: los ordenadores multinúcleo y multiproceso tienen varios elementos de procesamiento
en una sola máquina, mientras que los clusters, los MPP y los grids emplean varios ordenadores
para trabajar en la misma tarea.
Los programas de ordenador paralelos son más difíciles de escribir que los secuenciales porque la
concurrencia introduce nuevos tipos de errores de software, siendo las condiciones de carrera los
más comunes.
La comunicación y la sincronización entre las diferentes subtareas son típicamente las grandes
barreras para conseguir un buen rendimiento de los programas paralelos.
También conocida como "computadora de programa almacenado", tanto las instrucciones del
programa como los datos se guardan en la memoria electrónica. Difiere de las computadoras
anteriores que fueron programadas a través de "cableado".
Desde entonces, prácticamente todas las computadoras han seguido este diseño básico:
Consta de cuatro componentes principales:
o Memoria
o Unidad de control
o De entrada y salida
La memoria de acceso aleatorio de lectura / escritura se utiliza para almacenar tanto las
instrucciones del programa como los datos.
o Los datos son simplemente información para ser utilizada por el programa.
Una de las clasificaciones más utilizadas, en uso desde 1966, se llama Taxonomía de Flynn.
La taxonomía de Flynn distingue las arquitecturas de computadora multiprocesador según cómo
pueden clasificarse a lo largo de las dos dimensiones independientes de Instruction Stream y Data
Stream. Cada una de estas dimensiones puede tener solo uno de dos estados
posibles: Único o Múltiple.
Descripción Estructural
Una única instrucción máquina controla paso a paso la ejecución simultánea de un cierto
número de elementos de proceso.
Cada elemento de proceso tiene una memoria asociada.
Cada instrucción es ejecutada por cada procesador, con un conjunto de datos diferentes.
Más adecuado para problemas especializados caracterizados por un alto grado de regularidad,
como el procesamiento de gráficos e imágenes.
Ejemplos:
Tuberías de vectores: IBM 9000, Cray X-MP, Y-MP y C90, Fujitsu VP, NEC SX-2, Hitachi
S820, ETA10
Pocos (si alguno) ejemplos reales de esta clase de computadora paralela han
existido alguna vez.
En resumen:
Un conjunto de procesadores ejecuta simultáneamente secuencias de
instrucciones diferentes.
Ejemplo: SMP, los Clusters y los sistemas NUMA son ejemplos de esta
categoría.
En general se denotan 2 modelos de multiprocesadores MIMD:
Caso: CLUSTERS
Un clúster es un tipo de computador paralelo o distribuido que consiste en un
conjunto de computadores independientes pero interconectados entre sí que
trabajan conjuntamente como un único recurso para resolver un problema común.
Multiprocesador “casero”: utiliza componentes comerciales, baratos y potentes:
Commodity of the shelf (COTS)
Según la aplicación.
- Clusters de alto rendimiento: diseñados para la implementación de
aplicaciones de alto coste computacional.
- Clusters de alta fiabilidad: diseñado para aplicaciones críticas, en las que lo
importante es la disponibilidad.
Los cambios en una ubicación de memoria efectuados por un procesador son visibles para
todos los otros procesadores.
Procesadores idénticos.
A veces se llama CC-UMA - Caché UMA coherente. Caché coherente significa que si un
procesador actualiza una ubicación en la memoria compartida, todos los demás
procesadores conocen la actualización. La coherencia de caché se logra a nivel de
hardware.
No todos los procesadores tienen el mismo tiempo de acceso a todas las memorias
Desventajas:
La principal desventaja es la falta de escalabilidad entre la memoria y las CPU. Agregar más
CPU puede aumentar el tráfico geométricamente en la ruta de la CPU y la memoria
compartida, y para los sistemas coherentes de caché, aumentar el tráfico asociado con la
administración de memoria / caché.
Al igual que los sistemas de memoria compartida, los sistemas de memoria distribuida
varían ampliamente pero comparten una característica común. Los sistemas de memoria
distribuida requieren una red de comunicación para conectar la memoria entre
procesadores.
Debido a que cada procesador tiene su propia memoria local, opera de manera
independiente. Los cambios que realiza en su memoria local no tienen efecto en la
memoria de otros procesadores. Por lo tanto, el concepto de coherencia de caché no se
aplica.
Cuando un procesador necesita acceder a los datos en otro procesador, generalmente es
tarea del programador definir explícitamente cómo y cuándo se comunican los datos. La
sincronización entre tareas es responsabilidad del programador.
Ventajas:
Cada procesador puede acceder rápidamente a su propia memoria sin interferencias y sin
los gastos generales incurridos al tratar de mantener la coherencia de caché global.
Desventajas:
Puede ser difícil asignar las estructuras de datos existentes, basadas en la memoria global,
a esta organización de memoria.
Tiempos de acceso a la memoria no uniformes: los datos que residen en un nodo remoto
tardan más en acceder a los datos locales del nodo.
Las computadoras más grandes y rápidas del mundo hoy en día emplean arquitecturas de
memoria compartida y distribuida.
Las tendencias actuales parecen indicar que este tipo de arquitectura de memoria
continuará prevaleciendo y aumentará en el extremo superior de la computación en el
futuro inmediato.
Ventajas y Desventajas:
Industrial y Comercial:
Hoy en día, las aplicaciones comerciales proporcionan una fuerza motriz
igual o mayor en el desarrollo de computadoras más rápidas. Estas
aplicaciones requieren el procesamiento de grandes cantidades de datos de
manera sofisticada. Por ejemplo:
o "Big Data", bases de datos, minería de datos o
o Inteligencia Artificial (IA)
o Buscadores web, servicios empresariales basados en web.
o Imagen médica y diagnóstico.
o Diseño farmaceutico
o Modelización financiera y económica.
o Gestión de empresas nacionales y multinacionales.
o Gráficos avanzados y realidad virtual, particularmente en la
industria del entretenimiento.
o Video en red y tecnologías multimedia.
o Exploración de aceite
5. Terminología
Como todo lo demás, la computación paralela tiene su propia "jerga". A continuación se
enumeran algunos de los términos más comúnmente asociados con la computación
paralela.
Usando las computadoras más grandes y rápidas del mundo para resolver grandes problemas.
Nodo
Esto varía, dependiendo de con quién hables. En el pasado, una CPU (Unidad central de
procesamiento) era un componente de ejecución singular para una computadora. Luego, se
incorporaron múltiples CPU a un nodo. Luego, las CPU individuales se subdividieron en múltiples
"núcleos", cada uno de los cuales es una unidad de ejecución única. Las CPU con múltiples núcleos
a veces se denominan "sockets", depende del proveedor. El resultado es un nodo con varias CPU,
cada una con múltiples núcleos. La nomenclatura se confunde a veces. ¿Preguntarse por qué?
Tarea
Una sección lógicamente discreta del trabajo computacional. Una tarea es típicamente un
programa o conjunto de instrucciones similar a un programa que es ejecutado por un
procesador. Un programa paralelo consiste en múltiples tareas que se ejecutan en múltiples
procesadores.
Tubería
Dividir una tarea en pasos realizados por diferentes unidades de procesador, con entradas que se
transmiten a través de, como una línea de ensamblaje; Un tipo de computación paralela.
Memoria compartida
Memoria distribuida
En hardware, se refiere al acceso a la memoria basado en la red para la memoria física que no es
común. Como modelo de programación, las tareas solo pueden "ver" lógicamente la memoria de
la máquina local y deben usar comunicaciones para acceder a la memoria en otras máquinas
donde se ejecutan otras tareas.
Comunicaciones
Las tareas paralelas normalmente necesitan intercambiar datos. Hay varias formas en que esto se
puede lograr, por ejemplo, a través de un bus de memoria compartida o a través de una red, sin
embargo, el evento real de intercambio de datos se conoce comúnmente como comunicaciones,
independientemente del método empleado.
Sincronización
La sincronización generalmente implica esperar por al menos una tarea y, por lo tanto, puede
hacer que aumente el tiempo de ejecución del reloj de pared de una aplicación paralela.
Granularidad
En la computación en paralelo, la granularidad es una medida cualitativa de la relación entre
computación y comunicación.
Aceleración observada
-----------------------------------
Uno de los indicadores más simples y más utilizados para el desempeño de un programa paralelo.
Sobrecarga paralela
La cantidad de tiempo requerido para coordinar tareas paralelas, en lugar de hacer un trabajo
útil. La sobrecarga paralela puede incluir factores tales como:
o Sincronizaciones
o Transmisión de datos
Masivamente paralelo
Se refiere al hardware que comprende un sistema paralelo dado, que tiene muchos elementos de
procesamiento. El significado de "muchos" sigue aumentando, pero en la actualidad, las
computadoras paralelas más grandes están compuestas por elementos de procesamiento que
suman cientos de miles a millones.
Avergonzadamente paralelo
Escalabilidad
Se refiere a la capacidad de un sistema paralelo (hardware y / o software) para demostrar un
aumento proporcional en la aceleración paralela con la adición de más recursos. Los factores que
contribuyen a la escalabilidad incluyen:
o Algoritmo de aplicación
"Introducción a la computación paralela". Ananth Grama, Anshul Gupta, George Karypis, Vipin
Kumar.
https://computing.llnl.gov/tutorials/parallel_comp/?fbclid=IwAR0ASc6jLwAXCt_eOhMU5fj-
ry5mKn44BOTwUKOydA34jD-YiO-e4s1pwEE#Neumann
https://es.wikipedia.org/wiki/Computaci%C3%B3n_paralela#Paralelismo_de_grano_fino,_grano_g
rueso_y_paralelismo_vergonzoso