UNIDAD 2 ESPECIFICACIÓN FORMAL DE SISTEMAS CONCURRENTES
Sentencias Concurrentes Ahora es necesario, dado un programa concurrente, saber que secciones del código son concurrentes y cuáles no, además es indispensable especificarlo en un lenguaje de programación. No todas las sentencias son concurrentes, consideremos el siguiente fragmento del programa: S1: S2: x:=x+1 y:=x+2 En este caso las instrucciones no pueden ejecutarse de forma independiente.
Sentencias Concurrentes Consideremos ahora: x:=1 y:=2 z:=3 Cada una de las sentencias se pueden ejecutar concurrentemente puesto que el orden en que se ejecuten no afecta el resultado final. Si se tuvieran 3 procesadores en cada uno se colocaría cada instrucción. Aunque la intuición nos indique cuando ejecutar concurrentemente Bernstein definió condiciones para garantizar la concurrencia.
Condiciones de Bernstein Para determinar si dos conjuntos de instrucciones se pueden ejecutar de forma concurrente se definen: L(S k )={a 1,a 2,,a n } conjunto de lectura del conjunto de instrucciones S k, formado por todas las variables cuyos valores son leídos (referenciados) durante la ejecución de las instrucciones en S k. E(S k ) ={b 1,b 2,,b n } conjunto de escritura del conjunto de instrucciones S k, formado por todas las variables cuyos valores son actualizados (se escriben) durante la ejecución de las instrucciones en S k.
Condiciones de Bernstein Para que dos conjuntos de instrucciones S i y S j, i j, i<j se puedan ejecutar concurrentemente se tiene que cumplir que: 1. L(S i ) E(S j )= 2. E(S i ) L(S j )= 3. E(S i ) E(S j )=
Ejemplo de Condiciones de Bernstein Sean: S 1 a:=x+y; S 2 b:=z-1; S 3 c:=a-b; S 4 w:=c+1; Se calculan los conjuntos de lectura y escritura L(S 1 )={x,y} E(S 1 )={a} L(S 2 )={z} E(S 2 )={b} L(S 3 )={a,b} E(S 3 )={c} L(S 4 )={c} E(S 4 )={w}
Ejemplo de Condiciones de Bernstein Sean: L(S 1 )={x,y} 2.Aplicando las condiciones de Bernstein Entre S 1 y S 2 E(S 1 )={a} 1. L(S 1 ) E(S 2 )= 2. E(S L(S 2 )={z} 1 ) L(S 2 )= 3. E(S E(S 2 )={b} 1 ) E(S 2 )= L(S 3 )={a,b} E(S 3 )={c} L(S 4 )={c} E(S 4 )={w} Entre S 1 y S 3 1. L(S 1 ) E(S 3 )= 2. E(S 1 ) L(S 3 )={ a } 3. E(S 1 ) E(S 3 )= Entre S 1 y S 4 1. L(S 1 ) E(S 4 )= 2. E(S 1 ) L(S 4 )= 3. E(S 1 ) E(S 4 )=
Ejemplo de Condiciones de Bernstein Sean: L(S 1 )={x,y} E(S 1 )={a} L(S 2 )={z} E(S 2 )={b} L(S 3 )={a,b} E(S 3 )={c} L(S 4 )={c} E(S 4 )={w} 2.Aplicando las condiciones de Bernstein Entre S 2 y S 3 1. L(S 2 ) E(S 3 )= 2. E(S 2 ) L(S 3 )={ b } 3. E(S 2 ) E(S 3 )= Entre S 2 y S 4 1. L(S 2 ) E(S 4 )= 2. E(S 2 ) L(S 4 )= 3. E(S 2 ) E(S 4 )= Entre S 3 y S 4 1. L(S 3 ) E(S 4 )= 2. E(S 3 ) L(S 4 )={ c } 3. E(S 3 ) E(S 4 )=
Tabla resultante al aplicar las condiciones de Bernstein En este caso se indica que sentencias se pueden ejecutar concurrentemente y cuales no S 1 S 2 S 3 S 4 S 1 ---- Si No Si S 2 ---- ---- No Si S 3 ---- ---- ---- No S 4 ---- ---- ---- ----
Especificación concurrente Existen dos formas de realizar la especificación concurrente: Grafo de precedencia Sentencias cobegin-coend
Grafos de precedencia Es una notación gráfica. Se representa como un grafo dirigido acíclico. Cada nodo representa una parte del sistema (conjunto de instrucciones). Una flecha desde A hasta B representa que B sólo se puede ejecutar cuando A haya finalizado. Si aparecen dos nodos en paralelo, significa que se pueden ejecutar concurrentemente.
Ejemplo de grafo de precedencia S1 S2 S3 S4 S1 ---- Si No Si S2 ---- ---- No Si S1 S2 S3 ---- ---- ---- No S3 S4 ---- ---- ---- ---- S1a:=x+y; S2b:=z-1; S3c:=a-b; S4w:=c+1; S3 S4
Sentencias COBEGIN-COEND Aquellas instrucciones que puedan ejecutarse concurrentemente se introducen entre el par cobegin/coend. Las instrucciones en el bloque pueden ejecutarse en cualquier orden, el resto de manera secuencial. Ejemplo: S 1 a:=x+y; S 2 b:=z-1; S 3 c:=a-b; S 4 w:=c+1; Begin cobegin a:=x+y b:=z-1 coend c:=a-b; w:=c+1; end
Ejercicios 1. Construir un programa concurrente, utilizando el par cobegin / coend, del siguiente grafo de precedencia.
Solución S1; Cobegin S3 begin S2; S4 Cobegin S5; S6; Coend; end; Coend; S7;
Ejercicio Dato el siguiente código obtener el grafo de precedencia S0; Cobegin S1; Begin S2; Cobegin S3; S4 Coend; S5 End; S6 Coend; S7
Solución S0; Cobegin S1; Begin S2; Cobegin S3; S4 Coend; S5 End; S6 Coend; S7
Paralelo Cobegin P1 P2 P3 P4 Coend
Serie/Paralelo Begin End P1 Cobegin P6 Begin End Coend P7 Cobegin P2 P3 Coend P4
Ejercicio Construir dos programas concurrentes, usando cobegin/coend, que correspondan con los siguientes grafos de precedencia.
Ejercicio Usando las condiciones de Bernstein, construir el grafo de precedencia del siguiente código y el programa concurrente correspondiente usando el par cobegin/coend. S1: cuad:= x*x; S2: m1:= a*cuad; S3: m2:= b*x; S4: z:= m1 + m2; S5: y:= z + c;
Fork y Join Fork y Join tienen dos funciones Fork(label L), y join(int x) Fork(label L) produce dos ejecuciones concurrentes. Una inicia inmediatamente despues de la instrucción fork, y la otra en la label L. Esto tiene los efectos de dividir una ejecución de un proceso en dos procesos concurrentes. Join(int x) combina x procesos en 1.
Ejercicio Modele el siguiente grafo usando fork-join
Solución
Ejercicio