0% encontró este documento útil (0 votos)
109 vistas11 páginas

Final Concurrencia

Este documento compara la concurrencia y el paralelismo. La concurrencia permite procesar múltiples tareas al mismo tiempo, mientras que el paralelismo resuelve una sola tarea de manera más eficiente utilizando múltiples procesos. A continuación, se describen varios métodos para lograr la exclusión mutua entre procesos concurrentes, como alternancia estricta, la solución de Peterson, semáforos, mutex y monitores.

Cargado por

Fernando López
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
109 vistas11 páginas

Final Concurrencia

Este documento compara la concurrencia y el paralelismo. La concurrencia permite procesar múltiples tareas al mismo tiempo, mientras que el paralelismo resuelve una sola tarea de manera más eficiente utilizando múltiples procesos. A continuación, se describen varios métodos para lograr la exclusión mutua entre procesos concurrentes, como alternancia estricta, la solución de Peterson, semáforos, mutex y monitores.

Cargado por

Fernando López
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 11

CONCURRENCIA VS PARALELISMO

La concurrencia ayuda a procesar varias tareas al mismo tiempo, mientras


que el paralelismo resuelve una única tarea de una forma mucho más
eficiente.
 

CONDICION DE CARRERA:
Ocurre cuando dos o más procesos que están trabajando juntos comparten
algún dato modificable que cada proceso puede leer o escribir y el resultado
final depende del orden de ejecución. (Nota: Este problema no sucede en
monoprogramación).

EXCLUSION MUTUA CON ESPERA OCUPADA:

DESHABILITACION DE INTERRUPCIONES:
En un sistema monoprocesador la solución mas simple seria que cada
proceso deshabilite las interrupciones después de entrar a la SC y las
rehabilite después de salir de la SC. Entonces, el proceso puede examinar y
actualizar la memoria compartida sin temor que intervenga otro proceso.
Por lo pronto no es bueno dar a los procesos de usuario el poder de
deshabilitar las interrupciones, si uno de los procesos lo hiciera y nunca
lo volviera a activar seria el fin del sistema. Si el sistema es
multiprocesador se vería afectada la CPU donde se ejecutó la
Deshabilitación.
Se dice que es conveniente que el mismo kernel deshabilite las
interrupciones, es una técnica útil dentro del S.O pero no como
mecanismo para la exclusión mutua.

ALTERNANCIA ESTRICTA:
Se cuenta con un variable turno (que al principio es 0) que lleva la cuenta
de a qué proceso le toca entrar a su sección critica.
Esta solución genera espera ocupada, lo cual debe evitarse, ya que
desperdicia tiempo de la CPU.
La espera ocupada solo se utiliza cuando hay expectativa razonable de que
la espera será corta; esto nos quiere decir, que no es bueno tomar turnos
cuando uno de los procesos es más lento que el otro.
Esta situación viola la condición 3: el proceso esta siendo bloqueado por un
porceso que no está en su sección critica.
Esta solución requiere que los dos procesos alternen de manera estricta al
entrar en sus regiones criticas.
Este algoritmo evita las condiciones de carrera, pero no es buena solución al
violar la condición 3.

SOLUCIÓN DE PETERSON:
Cuando un proceso quiere entrar a la sección critica llama a una función
entrar_seccion con su propio número de proceso como parámetro, indica
su interés estableciendo su elemento del arreglo y fija turno a 0.
Cuando otro proceso quiere hacer uso de su región critica llama a
entrar_seccion y se quedara esperando hasta que interesado[0] sea
Falso, evento que solo ocurre cuando el proceso que esta en la sección
critica llama a salir_seccion.
Si en el caso que ambos proceso llaman a entrar_seccion casi en
simultaneo, ambos almacenaran su número de proceso en turno, cualquier
almacenamiento que se haya hecho último es el que cuenta, el primero se
sobreescribe y se pierde.

SEMAFOROS:

Un semáforo es una variable entera que cuenta el número de señales de


despertar.
Un semáforo es una variable, que puede tomar el valor 0 si no se guardaron
señales de despertar o algún valor positivo si hay pendiente una o más
señales de despertar.
El semáforo tiene dos operaciones, down y up.
El semáforo se inicializa de acuerdo a la cantidad de recursos compartidos
haya.
Las acciones de comprobar, modificarlo y mandar a dormir se realizan en
conjunto como una acción atómica indivisible. Se garantiza que, una vez
que empieza una operación de semáforo, ningún otro proceso podrá
acceder al semáforo. Esta atomicidad resuelve el problema de la
sincronización y evita las condiciones de carrera.

Un tipo simple de semáforo es el binario, que puede tomar solamente los


valores 0 y 1.
Se inicializan en 1 y son usados cuando sólo un proceso puede acceder a un
recurso a la vez.
Cuando el recurso está disponible, un proceso accede y decrementa el valor
del semáforo con la operación down.
El valor queda entonces en 0, lo que hace que si otro proceso intenta
decrementarlo tenga que esperar.
Cuando el proceso que decrementó el semáforo realiza una operación up,
algún proceso que estaba esperando comienza a utilizar el recurso.
Los semaforos da lugar a interbloqueo.

MUTEX:

Es una versión simplificada cuando no se necesita contar.


Son útiles en hilos implementados a nivel de usuario.
Un mutex es una variable entera que puede estar en uno de 2 estados:
abierto (desbloqueado) o cerrado (bloqueado). 0 indica que esta
abierto y todos los demás valores indican que está cerrado.
Se usan dos procedimientos mutex_lock y mutex_unlock.
Cuando un proceso o hilo desea entrar a su sección critica llama a
mutex_lock, si el mutex está abierto la llamada tiene éxito y el hilo entra,
sino, si el mutex está cerrado, el hilo llamador se bloquea hasta que el hilo
que está dentro de la sección critica termine y llame a mutex_unlock.
Si se bloquean muchos hilos por el mutex, se selecciona uno al azar.
MONITORES:

Un monitor es una coleccion de procedimientos, variables y estructuras


datos que se agrupan en un mismo módulo o paquete,
las regiones críticas relacionadas con un determinado recurso, haciendo que
toda región crítica se encuentre asociada a un procedimiento del monitor,
el que podrá ser llamado por los procesos.

Los monitores tienen una propiedad importante para lograr la exclusión


mutua, solo puede haber un proceso activo en un monitor en cualquier
instante.

Tiene cuatro componentes: inicialización, datos privados, métodos del


monitor y cola de entrada.
Inicialización: contiene el código a ser ejecutado cuando el monitor es
creado
Datos privados: contiene los procedimientos privados, que sólo pueden ser
usados desde dentro del monitor
y no son visibles desde fuera
Métodos del monitor: son los procedimientos que pueden ser llamados
desde fuera del monitor.
Cola de entrada: contiene a los hilos que han llamado a algún método del
monitor pero no han podido adquirir permiso para ejecutarlos aún.

FILMINA 6

ACCIONES ATOMICAS Y SINCRONIZACIÓN

Hablando siempre de procesos concurrentes o paraleo.

Accion atómica: Accion indivisible, típicamente es una instrucción del set de


instrucción, con atomicidad de grano fino.

Atomicidad de grano fino: Es la implementada por el hardware que ejecuta


procesos concurrentes

Propiedad A lo Sumo una Vez (ASV):

Sabiendo que:

Referencia crítica: Referencia a una variable que es modificada por otro


proceso.

Asumiendo que toda referencia crítica es a una variable simple leída y


escrita atómicamente, decimos que:

Una sentencia de asignación x = e satisface la propiedad de ASV si:


1) e tiene a lo sumo una referencia crítica y x no es referenciada por otro
proceso
ó
2) e no tiene referencias críticas y x puede ser leída por otro proceso

Para expresiones que no están en sentencias de asignación:


- Satisface ASV, si tiene a lo sumo una referencia crítica

Especificación de la sincronización

Si una expresión o asignación no satisface ASV, en general, es necesario


ejecutar secuencias de sentencias como una única acción atómica.

Sentencia await:

 〈 e 〉 (indica que la expresión e se evalúa atómicamente)


 〈 await (B) S; 〉 (se utiliza para especificar sincronización)

Variantes

〈 S 〉 Solo exclusión mutua


〈 await (B) 〉 Solo sincronización por condición

Si B satisface ASV puede implementarse como busy waiting o spinning

INTERFERENCIA:
Un proceso interfiere con otro, si se ejecuta una asignación que invalida una
aserción en el otro proceso.

Una acción de asignación es una sentencia de asignación o una sentencia


await que contiene una o más asignaciones.

Una aserción crítica es una precondición o una postcondición que no está


dentro de una sentencia await.

Tecnicas para evitar interferencia

Recordar conjunto de escritura y conjunto de lectura de un proceso.

Una prueba de un proceso es un análisis donde se ubica una aserción


antes y después de cada sentencia.

El conjunto de referencia de un proceso es el conjunto de variables que


aparecen en las aserciones de una prueba del proceso.

• Variables disjuntas

Si el conjunto de escritura de un proceso es disjunto del conjunto de


referencia de otro y viceversa, entonces los procesos no pueden
interferirse.

Ejemplo
co x = x+1; // y = y+1; oc
Las pruebas correspondientes
{x == 0} x = x+1; {x == 1}
{y == 0} y = y+1; {y == 1}

• Aserciones debilitadas

Si los conjuntos anteriores se superponen podemos debilitar aserciones


para tener en cuenta la concurrencia.

Una aserción debilitada contempla más estados que una aserción que
puede ser cierta para el mismo proceso aislado.

Ejemplo (volvemos a ver este código):


{x == 0} // Esta aserción
co {x == 0 v x == 2} // Se debilita y queda como esta
<x = x+1;>
{x == 1 v x == 3}
// {x == 0 v x == 1} // Y como esta (en este proceso)
<x=x+2;>
{x == 2 v x == 3}
oc
{x == 3}

• Invariantes globales:

Supongamos que I es un predicado que hace referencia a variables


globales, por lo que podemos decir que I es invariante global a todos los
procesos si:
1) I es verdadero en la ejecución de todos los procesos
2) I se preserva luego en toda acción de asignación

• Sincronización:

La exclusión mutua garantiza que todas las asignaciones contenidas dentro


del bloque se vean como una única acción atómica

PROPIEDADES DE SEGURIDAD Y DE VIDA:

Propiedad de seguridad: asegura que el programa nunca entre en un


estado indeseable o malo. Ej.: ausencia de deadlock y ausencia de
interferencia (exclusión mutua) entre procesos.

Propiedad de vida: asegura que el programa eventualmente entre en un


estado deseado o bueno. Ej.: Terminación, asegurar que un pedido de
servicio será atendido, que un mensaje llega a destino.
• Eventualmente entrar a una región crítica
• Eventualmente recibir un servicio solicitado
• Eventualmente recibir un mensaje
Prueba de propiedades
 Testing o debugging: "tome el programa y vea qué sucede". No
demuestra la ausencia de historias "malas".
 Razonamiento operacional: análisis exhaustivo de casos.
 Razonamiento asercional: análisis abstracto. para este analisis se usa
predicados (logica proposicional).

Politicas de planificación y justicia:

Afectan a las propiedades de vida

Accion condicional: Depende de si la condición da verdadero, la acción se va


a ejecutar.

Justicia incondicional: si toda acción atómica incondicional es


eventualmente ejecutada.

Justicia débil: (ej: Round Robin)


(1) es justa incondicional, y
(2) toda acción atómica condicional elegible es eventualmente ejecutada,
asumiendo que su condición se torna verdadera y que se mantiene
verdadera hasta que es vista por el proceso que quiere ejecutar la acción
atómica condicional.

A los algoritmos débilmente justo se les garantiza toda acción incondicional


pero las condicionales no siempre.

Justicia fuerte:
(1) es justa incondicional, y
(2) toda acción atómica condicional elegible es eventualmente ejecutada,
asumiendo que su condición se torna verdadera con “infinita” frecuencia

Si una condición se torna verdadero, el proceso la va a encontrar


verdadera.

Estos planificadores son teóricos, son muy caros de implementarlo

FILMINA 8

Problema de la sección critica

Condiciones necesarias:
- Exclusión mutua: A lo sumo un proceso a la vez está ejecutando su
sección crítica
- Ausencia de deadlock (Bloqueo mutuo o Interbloqueo): Si dos o más
procesos tratan de entrar a sus secciones críticas, al menos uno
tendrá éxito.
- Ausencia de retardo innecesario: Si un proceso está tratando de
entrar a su SC y los otros están ejecutando sus SNC o terminaron, el
primero no está impedido de entrar a su SC.
- Eventual ingreso: Un proceso que está intentando entrar a su SC
eventualmente lo hará
Las primeras 3 son para la propiedad de seguridad y la ultima es de vida.

SPIN LOCKS: (ESPERA ACTIVA) bloqueo de giro


(SOLUCION DE GRANO FINO)
Es cuando un hilo (o thread) simplemente espera en un bucle ("spins")
repetidamente hasta que se cumple una condición, como por ejemplo la
llegada de un paquete por la red, un semáforo que se haga disponible o
esperar una entrada de teclado.

Test and Set:

Esta solución tiene como objetivo hacer átomico el await de grano grueso,
para esto se usa alguna instrucción especial test-and-set (TS).
La instrucción TS toma 2 argumento booleano: lock (compartido) y un
código de condición local initial. TS setea initial al valor de lock, luego
setea lock a verdadero(true).
Al utilizarse variable de lockeo de este modo, se lo llama spin locks pues los
procesos “dan vueltas” (spin) mientras esperan que se libere el lock.
Requieren de un planificador fuertemente justo para cumplir las 4
propiedades.  Una política débilmente justo es aceptable (rara vez todos los
procesos están simultáneamente tratando de entrar a su SC).
Aunque la última solución es correcta, puede llevar a baja performance si
varios procesos están compitiendo por el acceso a una SC. Esto es porque
lock es una variable compartida y todo proceso demorado continuamente la
referencia. Esto causa “memory contention”
Spin locks no controla el orden de los procesos demorados entonces es
posible que alguno no entre nunca si el planificador no es fuertemente justo
(condición de competencia).

Memory contention: 2 programas diferentes o 2 partes de un programa


tratan de leer un recurso en el mismo bloque de memoria al mismo tiempo.

SOLUCIONES JUSTAS:

Algoritmo TIE-BREAKER:

El tie-breaker es un protocolo de SC que requiere planificador justo


incondicional para satisfacer la propiedad de eventual ingreso.
No requiere instrucciones especiales del tipo Test and Set.
Usa una variable para desempatar, indicando qué proceso fue el último en
ejecutar su SC.
Si hay n procesos, el protocolo de entrada en cada proceso consiste de un
loop que itera a través de n-1 etapas. En cada etapa, se usa instancias del
tie-breaker para 2 procesos, que determina cuáles procesos avanzan a la
siguiente etapa.
El tie-breaker de n-proceso es costoso en tiempo, es complejo y difícil de
entender.

Algoritmo Ticket:
Es una solución para N-procesos más fácil de entender que el N procesos
del Tie-Breaker. Se usan contadores enteros para ordenar procesos. Acá se
reparten números y se espera turno: Los clientes toman un número mayor
a cualquier otro que espera ser atendido; luego esperan hasta que todos los
clientes con un número más chico sean atendidos. La ausencia de deadlock
y de demora innecesaria resultan de que los valores de turno son únicos.
Con planificador débilmente justo se asegura eventual ingreso.
Desventajas: Contadores crecientes, overflow (desbordamiento).

Algoritmo Bakery:

Bakery es del tipo de ticket que es justo y no requiere instrucciones


especiales. El algoritmo es más complejo que el ticket, pero tiene una
manera de desempatar cuando dos procesos obtienen el mismo número.
No requiere de un contador global. Los procesos se chequean entre ellos no
contra una varible global, es decir, cada proceso que ingresa, recorre los
números de los demás y se autoasigna uno mayor. Luego espera a que su
número sea el menor de los que esperan.
El algoritmo asegura eventual ingreso si el planificador es débilmente
justo, pues una vez que una condición de demora se convierte en
verdadero, permanece verdadero.

SINCRONIZACION POR BARRERAS

Barrier synchronization: es un protocolo de sincronización donde se


demoran al final de cada iteración a todos los procesos representando una
barrera a la que todos los procesos deben arribar antes de que se les
permita pasar.

Contador compartido:

Utiliza una variable entera compartida, count, el cual es inicialmente 0.


Cuando un proceso llega a la barrera, incrementa count. Por lo tanto,
cuando count es N, todos los procesos pueden continuar.
El problema de count, es que debe ser 0 al comienzo de cada iteración y
más aún, tiene que ser reseteada antes de que cualquier proceso trate
nuevamente de incrementar count.
Se necesita de 2 contadores para resolver el problema de "reset", uno que
cuenta hasta N y otro que cuenta hacia abajo hasta 0.
El uso de contadores compartidos, trae problemas. Primero, tienen que ser
incrementados y/o decrementados como acciones atómicas. Segundo,
un proceso puede estar demorado examinando continuamente count, lo
cual demora a los demás procesos, generando memory contention.

Banderas y Coordinadores (con un arreglo)

Distribuiye la implementación de count usando n variables que sumen el


mismo valor.
En lugar de que cada Worker testee el valor de count, se hace que cada
Worker espere que un único valor se convierta en verdadero. Hay un
proceso coordinador que espera a que todos los elementos de llegada (es
un arreglo con n procesos worker, una posición para cada worker) se
vuelvan 1, luego setea todos los elementos de continue (es un arreglo, una
posición para cada worker) en 1.
Desventaja: Reintroduce memory contention y mucho trabajo para el
coordinador.

Arboles:

Se distribuye el trabajo del coordinador, cada worker también es


coordinador.
Ej., workers en forma de árbol: las señales de llegada van hacia arriba en el
árbol, y las de continuar hacia abajo.
Problema: Requiere un proceso y un procesador extra.

Barreras Simétricas:

Una barrera simétrica para n procesos se construye a partir de pares de


barreras simples para 2 procesos.
Para construir una barrera de 2 procesos, se construye una barrera
simétrica en donde, cada proceso tiene una bandera que setea cuando
llega a la barrera y luego espera a que el otro proceso setee su bandera y
finalmente limpia la bandera del otro.
Regla general: El proceso que testea una bandera es el que la resetea.

Butterfly Barrier (barrera mariposa):

Sean Worker los n procesos. Si n es potencia de 2, podemos usar butterfly


barrier. 
Una butterfly barrier tiene log2 n etapas. Cada Worker sincroniza con un
Worker distinto en cada etapa. Cada worker se puede implementar como:
cada proceso tiene una bandera que setea cuando llega a la barrera y luego
espera a que el otro proceso setee su bandera y finalmente limpia la
bandera del otro.
Cuando cada Worker pasó a través de log2 n etapas, todos los Workers
deben haber arribado a la barrera y por lo tanto todos pueden seguir. Esto
es porque cada Worker ha sincronizado directa o indirectamente con cada
uno de los otros.

FILMINA 9: programación paralela, computación científica

Programación Concurrente:
- múltiples procesos cooperantes: con memoria compartida y con
pasaje de mensajes.

Programación Paralela: el objetivo es calcular en menos tiempo o abarcar


un problema más grande en el mismo tiempo. Puede usar ambas técnicas,
memoria compartida o pasaje de mensajes.

Uso de la programación paralela.


- problemas científicos: calculo en grid, cálculo de partículas, cálculo de
matrices
- problemas de ingeniería
* en general es necesario y se ve beneficiado en cálculos grandes, que
requieras muchos hardware.

1 - Speedup: es la ganancia en tiempo de ejecución. Aceleración que logro


en comparación con el algoritmo secuencial.

Siendo T1 el tiempo de un proceso SECUENCIAL en un solo procesador, y


Tp el tiempo para resolver el mismo problema con un programa paralelo en
p procesadores. Entonces: speedup = T1 / Tp

Tipos de Speedup:
- Lineal o perfecto (speedup = p)
- Sublineal (Speedup < p) caso tipico, algo gano de velocidad
- Superlineal (speedup > p) caso raro.

2 – Eficiencia: mide que tan bien un programa paralelo utiliza los


procesadores de más.

eficiencia = speedup / p = T1 / (p* Tp)

Tanto la eficiencia como speedup son medidas relativas que dependen


de:
- cantidad de procesadores
- tamaño del problema (complejidad)
- algoritmos utilizados.

Otra forma de analizarlos: en cualquier programa hay partes NO


paralelizables:
- entrada: 10% del tiempo (secuencial)
- calculo: 80% del tiempo (paralelizable)
- salida: 10% del tiempo (secuencial)

LEY DE AMDAHL: tiene en cuentas los aspectos antes mencionados.

Hay 2 formas de calcular el Speedup total:

Speedup total = TiempoEjecucion old / TiempoEjecucion new

Speedup total = 1 / (1 - Fraccion par + Fraccion par / Speedup )


par

Ejemplo:

Suponiendo que la parte paralelizable de un problema es el 80% y que


contamos con 10 procesadores y con un speedup lineal o perfecto.
Entonces, el Speedup total logrado será:

Speedup total = 1/ (0.2 + 0.8 / 10) = 3.57

"afortunadamente para la mayoría de las aplicaciones reales, la parte de


entrada/salida es pequeña comparada con la parte de cálculo. Además, las
máquinas de altas performances ofrecen hardware especial para
entrada/salida en paralelo y a altas velocidades"
3 y 4 – Overheads y Desafíos

cosas a tener en cuenta a la hora de paralelizar un programa secuencial:


- cuántos procesos usar?
- que hará cada uno?
- como se comunicarán y sincronizarán?
- el programa paralelo debe ser correcto
- libre de errores como condiciones de competencia y deadlocks.
- obtener el mejor rendimiento posible, que valga la pena paralelizar.
- cargas de trabajo balanceadas.

DIFERENCIAS ENTRE OPENMP Y MPI:

- La arquitectura: MPI se utiliza en sistemas de memoria distribuida y


OPENMP se utiliza en sistemas de memoria compartida
- La comunicación de procesos: MPI es a través del paso de mensajes
y en OPENMP todos los hilos comparten la memoria
- La forma de paralelizar un programa: MPI el programador se encarga
de paralelizar el programa con el uso de las funciones y OPENMP lo
hace por medio de directivas que son variables de entorno que se
establecen en tiempo de compilación.

También podría gustarte