530 likes | 741 Views
Qué vimos en la clase pasada??. Las arquitecturas de memoria distribuida son cada vez más habituales. Esto implica procesadores + memoria local + red de comunicaciones + otro mecanismo de comunicación/sincronización mensajes.
E N D
Qué vimos en la clase pasada?? Las arquitecturas de memoria distribuida son cada vez más habituales. Esto implica procesadores + memoria local + red de comunicaciones + otro mecanismo de comunicación/sincronización mensajes. Los programas concurrentes que se comunican por mensajes se denominan programas distribuidos. Esto supone la ejecución sobre una arquitectura de memoria distribuída, aunque puedan ejecutarse sobre una arquitectura de memoria compartida ( o híbrida). Programación Concurrente 2004 - Clase 8
Qué vimos en la clase pasada?? En un programa distribuido los canales son el único objeto que los procesos comparten no hay acceso concurrente a variables y la exclusión mutua no requiere ningún mecanismo especial. Los canales pueden proveer comunicaciones half-duplex o full-duplex. A su vez estas comunicaciones pueden ser asincrónicas (no bloqueantes) o sincrónicas (bloqueantes). Programación Concurrente 2004 - Clase 8
Qué vimos la clase pasada?? Si bien se pueden obtener soluciones equivalentes, AMP y SMP son mejores para modelos tipo productor-consumidor o pares interactivos, mientras RPC y Rendezvous serán más útiles para esquemas C-S. El pasaje de mensajes (AMP o SMP) puede verse como una extensión de semáforos con datos. En RPC y Rendezvous se combina la interfaz procedural de los monitores con pasaje de mensajes implícito. Programación Concurrente 2004 - Clase 8
Qué vimos la clase pasada?? El grado de concurrencia en SMP se reduce respecto de la sincronización por mensajes asincrónicos. Como contrapartida los casos de falla y recuperación de errores son más fáciles de manejar. Si bien send y sync_send son similares (en algunos casos intercambiables) la semántica es diferente y las posibilidades de deadlock mayores en comunicación sincrónica. Programación Concurrente 2004 - Clase 8
Qué vimos la clase anterior? : El lenguaje CSP de Hoare. CSP (Hoare 1978) fue uno de los desarrollos fundamentales en Programación Concurrente. Muchos lenguajes reales (OCCAM, ADA, SR) se basan en CSP. La idea básica de Hoare fue la de comunicación guardada: es decir pasaje de mensajes con waiting selectivo. Canal: link directo entre dos procesos en lugar de mailbox global. Son half-duplex y nominados. Sentencias de Entrada y Salida ( ? ! ) : único medio por el cual los procesos se comunican. Efecto de la comunicación sentencia de asignación distribuida. Programación Concurrente 2004 - Clase 8
El lenguaje CSP de Hoare. • Formas generales de sentencias de comunicación: • Destino ! port(e1, ..., en); • Fuente ? port(x1, ..., xn); • Destino y Fuente nombran un proceso. port es un canal de comunicación simple en el proceso destino o un elemento de un arreglo de ports en el proceso destino. Los ports son usados (declarados) para distinguir entre distintas clases de mensajes que un proceso podría recibir. • Dos procesos se comunican cuando ejecutan sentencias de comunicación que hacen matching. • A! canaluno(dato); #el proceso A envia por canaluno • B? canaluno(resultado); #el proceso B recibe por canaluno Programación Concurrente 2004 - Clase 8
El lenguaje CSP de Hoare. Primeros ejemplos. Server que calcula el Máximo Común Divisor de dos enteros con algoritmo de Euclides: GCD espera recibir entrada en su port args desde un único cliente. Envía la respuesta al port result del cliente. • Process GCD { • INT Id, x, y; • do true Client[*] ? args(Id, x,y); • #Lo que sigue se repite hasta que x==y • do x > y x := x - y; • x < y y := y - x; • od • Client[Id] ! result(x); • od • } • Client se comunica con GCD ejecutando: • ... GCD ! args(v1, v2); GCD ? result(r) ... Programación Concurrente 2004 - Clase 8
CSP: comunicación guardada. Un proceso puede tener que realizar una comunicación sólo si se da una condición: IF B1; comunicación1----> S1; B2; comunicación2----> S2; FI Process Copy { CHAR buffer[80]; INT front = 0, rear = 0, count = 0 do count < 80; West ? buffer[rear] • count = count + 1; • rear = (rear + 1)MOD 80; • count > 0; East ! buffer[front] • count := count - 1; • front := (front + 1) MOD 80; • od • } Programación Concurrente 2004 - Clase 8
Intercambio de valores entre dos procesos en CSP. Supongamos dos procesos que intercambian valores: Process P1 { INT value1 = 1, value2; IF P2 ! value1 ---> P2 ? value2; P2 ? value2 ---> P2 ! value1; FI } Process P2 { INT value1 , value2=2; IF P1 ! value2 ---> P1 ? value1; P1 ? value1 ---> P1 ! value2; FI } Esta solución simétrica NO tiene deadlock porque el no determinismo en ambos procesos hace que se acoplen las comunicaciones correctamente. Programación Concurrente 2004 - Clase 8
CSP: Generación de números primos: la criba de Eratóstenes. Idea: generar todos los primos entre 2 y n • 2 3 4 5 6 7 ... n • Comenzando con el primer número, 2, recorremos la lista y borramos los múltiplos de ese número. Si n es impar: • 2 3 5 7 ... n Pasamos al próximo número, 3, y borramos sus múltiplos. Si seguimos hasta que todo número fue considerado, los que quedan son todos los primos entre 2 y n. Programación Concurrente 2004 - Clase 8
La criba de Eratóstenes: solución paralela en CSP. Process Sieve[i = 2 TO L] { INT p, next; Sieve[i-1] ? p # p es primo DO Sieve[i-1] ? Next ---> #recibe el proximo candidato IF (next MOD p) <> 0 ---> #podría ser primo Sieve[i+1] ! Next; #entonces lo pasa FI OD } El número total L de procesos Sieve debe ser lo suficientemente grande para garantizar que todos los primos hasta n se generan. Programación Concurrente 2004 - Clase 8
El lenguaje de programación OCCAM Hoare introdujo CSP como lenguaje formal que sigue el modelo de pasaje de mensajes sincrónicos, pero nunca fue implementado. OCCAM es un lenguaje real, que implementa lo esencial de CSP sobre una arquitectura “modelo” que físicamente se ha desarrollado y que son los trasputers. Trasputers + OCCAM constituyen una combinación que permite hablar de “sistema multiprocesador para procesamiento concurrente”, donde tanto la arquitectura como el lenguaje son simples y perfectamente adecuadas a la programación concurrente con mensajes sincrónicos. Programación Concurrente 2004 - Clase 8
El lenguaje de programación OCCAM. • OCCAM es un lenguaje simple con una sintaxis rígida: • Cada proceso primitivo, constructor o declaración ocupa una • línea. • Se usa : al final de una declaración. • Hay una rígida indentación. • Los procesos y los caminos de comunicación entre ellos son estáticos (definidos al momento de la compilación). Un programa en OCCAM tiene un número fijo de procesos . • El modelo de comunicación es sincrónico por canales half duplex. • Las sentencias básicas (asignación y comunicación) son vistas como procesos primitivos. Programación Concurrente 2004 - Clase 8
Conceptos del lenguaje de programación OCCAM • Occam no soporta recursión o cualquier forma de creación o nombrado dinámico. Esto hace que muchos algoritmos sean difíciles de programar. • Sin embargo, asegura que un compilador Occam puede determinar exactamente cuántos procesos contiene un programa y cómo se comunican uno con otro. • Esto, y el hecho de que distintos constructores no pueden compartir variables, hace posible para un compilador asignar procesos y datos a procesadores en una máquina de memoria distribuida tal como un transputer. Programación Concurrente 2004 - Clase 8
El lenguaje de programación OCCAM Las unidades básicas de un programa Occam son declaraciones y tres "procesos" primitivos: asignación, input(receive),output (sync_send). Los canales son declarados globales a los procesos . Sin embargo, cada canal debe tener exactamente un emisor y un receptor. Los procesos primitivos se combinan en procesos convencionales usando constructores (sentencias estructuradas). Estos incluyen un constructor secuencial SEQ, un constructor paralelo PAR similar a la sentencia co, y una sentencia de comunicación guardada. Un constructor puede ser precedido por declaraciones de variables y canales; el alcance de estos ítems es el constructor. Programación Concurrente 2004 - Clase 8
El lenguaje OCCAM: constructores SEQ y PAR En la mayoría de los lenguajes, el default es ejecutar sentencias secuencialmente; el programador tiene que decir explícitamente cuándo ejecutar sentencias concurrentemente. Occam toma una aproximación distinta: no hay default. • En lugar de esto, contiene dos constructores básicos: SEQ para ejecución secuencial y PAR para ejecución paralela. Por ejemplo, el siguiente programa incrementa x, luego y: • INT x,y : • SEQ • x := x + 1 • y := y + 1 Programación Concurrente 2004 - Clase 8
El lenguaje OCCAM: constructores SEQ y PAR • En el ejemplo anterior, dado que las dos sentencias acceden variables distintas, pueden ser ejecutadas concurrentemente. Esto se expresa por: • INT x,y : • PAR • x := x + 1 • y := y + 1 Lo que cambia es el nombre del constructor, para indicarle al compilador y el monitor de ejecución si puede haber concurrencia. PAR no es tan poderoso como la sentencia co pues los procesos Occam no pueden compartir variables. Programación Concurrente 2004 - Clase 8
Comentarios sobre el constructor PAR en OCCAM • Los procesos especificados usando PAR ejecutan con igual prioridad y sobre cualquier procesador. • El constructor PRI PAR puede usarse para especificar que el primer proceso tiene la prioridad más alta, el segundo la siguiente, etc. • El constructor PLACED PAR puede usarse para especificar explícitamente dónde es ubicado y por lo tanto ejecutado cada proceso Programación Concurrente 2004 - Clase 8
El lenguaje de programación OCCAM: otros constructores El constructor IF se usa para alternativas: es similar a la sentencia IF guardada que conocemos, pero hay dos diferencias: las guardas son evaluadas en el orden en que están listadas, y al menos una guarda debe ser TRUE. El constructor CASE es una variante de IF que puede ser usada para alternativas múltiples. Programación Concurrente 2004 - Clase 8
El lenguaje de programación OCCAM: otros constructores El constructor WHILE es uno de los mecanismos de iteración; es como la sentencia while de Pascal. El constructor ALT soporta comunicación guardada. Cada guarda consta de un input process, una expresión booleana y un input process, o una expresión booleana y un SKIP (lo cual se reduce esencialmente a una expresión booleana pura). Programación Concurrente 2004 - Clase 8
Replicadores en OCCAM. Occam también contiene un mecanismo interesante llamado replicador. Es similar a un cuantificador y se usa del mismo modo. Por ejemplo, lo siguiente declara un arreglo pepe de 21 elementos e iterativamente asigna un valor a cada elemento: • [20] INT pepe : • SEQ i = 0 FOR 10 • pepe[i] := i • Como vemos, solo el límite superior del arreglo se declara; el límite inferior es implícitamente 0 para todos los arreglos. Las matrices se declaran como arreglos de arreglos. • Un replicador no agrega nueva funcionalidad al lenguaje, solo es una abreviación para un conjunto de componentes. Occam requiere que el límite superior sea una constante, y por lo tanto un replicador siempre puede ser expandido para dar un programa equivalente pero más largo. Programación Concurrente 2004 - Clase 8
Comunicación y sincronización en OCCAM • Como dijimos, las sentencias en los distintos constructores de Occam no pueden compartir variables. Para comunicarse y sincronizar, deben usar canales. Una declaración de canal tiene la forma: • CHAN OF protocol name : El protocolo define el tipo de valores que son transmitidos por el canal. Pueden ser tipos básicos, arreglos de longitud fija o variable, o registros fijos o variantes. Programación Concurrente 2004 - Clase 8
Comunicación y sincronización en OCCAM Los procesos pueden ser creados con el constructor PAR. Los canales son accedidos por los procesos primitivos input (?) y output (!). A lo sumo un proceso puede emitir por un canal, y a lo sumo uno puede recibir por un canal. Dado que el nombrado es estático, un compilador Occam puede forzar este requerimiento. Programación Concurrente 2004 - Clase 8
Comunicación y sincronización en OCCAM. Un ejemplo. WHILE TRUE • BYTE ch : • SEQ • keyboard ? ch • ch ! screen • Aquí, keyboard y screen son canales que se asume que están conectados a dispositivos periféricos. • Aunque Occam no define mecanismos de E/S como parte del lenguaje, provee mecanismos para ligar canales de E/S a dispositivos. • El sistema de desarrollo en transputer, por ejemplo, contiene una librería de procedures de E/S de modo de vincular canales lógicos y dispositivos físicos. Programación Concurrente 2004 - Clase 8
Comunicación y sincronización en OCCAM. Un ejemplo. El programa anterior usa un buffer simple, ch. • Puede convertirse en un programa concurrente que use doble buffering empleando dos procesos, uno para leer desde el teclado y uno para escribir en la pantalla. El proceso se comunica usando un canal adicional comm; cada uno tiene un carácter local ch: • CHAN OF BYTE comm : • PAR • WHILE TRUE • BYTE ch : • SEQ • keyboard ? ch • comm ! ch • WHILE TRUE • BYTE ch : • SEQ • comm ? ch • keyboard ! ch Programación Concurrente 2004 - Clase 8
Uso del constructor ALT en OCCAM El constructor ALT soporta comunicación guardada. Cada guarda consta de un input process, una expresión booleana y un input process. Puede usarse un replicador como abreviatura, por ejemplo, para esperar recibir entrada de uno de un arreglo de canales. Por ejemplo, lo siguiente implementa un alocador de recursos simple: • ALT i = 0 FOR n • avail > 0 & acquire[i] ? unitid • SEQ • avail := avail - 1 -- and select unit to allocate • reply[i] ! Unitid • release[i] ? unitid • avail := avail + 1 -- and return unit Programación Concurrente 2004 - Clase 8
Uso del constructor ALT en OCCAM. Comentarios. Acquire, reply y release son arreglos de canales, con un elemento para cada cliente i. Se necesitan arreglos pues un canal puede ser usado por solo dos procesos. Occam no permite mensajes nulos (señales) de modo que se debe enviar algún valor por el canal acquire aunque no se use este valor. Programación Concurrente 2004 - Clase 8
Uso del constructor ALT en OCCAM. Comentarios. No se permiten output processes en guardas de un constructor ALT. Esto hace que algunos algoritmos sean duros de programar, pero simplifica la implementación. Esto último es especialmente importante pues Occam es el lenguaje de máquina del transputer. Las guardas en un ALT son evaluadas en orden indefinido(no determinístico). El constructor PRI ALT puede usarse para forzar que las guardas sean evaluadas en el orden deseado. Programación Concurrente 2004 - Clase 8
Proceso reloj en OCCAM. Occam también contiene una facilidad de timer. Un timer es una clase especial de canal. Un proceso hardware está siempre listo para enviar hacia algún canal timer declarado en un programa. Si un proceso declara el canal timer myclock, puede leer la hora ejecutando: • myclock ? time • El proceso también puede demorarse hasta que el reloj alcance un cierto valor ejecutando: • myclock ? time AFTER value • Aquí, value es un tiempo absoluto, no un intervalo. • Un timer también puede usarse en una guarda en un constructor ALT; esto sirve para programar un interval timer. Programación Concurrente 2004 - Clase 8
La extensión de lenguajes secuenciales c/bibliotecas específicas Una técnica muy utilizada es el desarrollo de bibliotecas de funciones que permiten comunicar/sincronizar procesos, NO dependientes de un lenguaje de programación determinado. Las soluciones basadas en bibliotecas (tales como LINDA, MPI, PVM) tienden a ser menos eficientes que los lenguajes “reales”de programación concurrente, aunque tienen la facilidad de “agregarse”al código secuencial con bajo costo de desarrollo. Las arquitecturas distribuidas han potenciado las soluciones basadas en PVM o MPI (que son básicamente bibliotecas de comunicaciones). Un esquema anterior (y original) es el de LINDA que veremos más adelante. Programación Concurrente 2004 - Clase 8
Programación Paralela con el concepto de “bag of tasks” Se parte del concepto de tener una “bolsa”de tareas que pueden ser compartidas por procesos “worker”. Cada worker ejecuta un código básico: WHILE (true) { obtener un task de la bolsa IF (no hay más tareas) BREAK; # exit del WHILE ejecutar la tarea, incluyendo la creación de otras tareas; } Este enfoque puede usarse para resolver problemas con un número fijo de tareas y también para soluciones recursivas con nuevas tareas creadas dinámicamente. El paradigma del bag of tasks es sencillo, escalable y favorece el balance de carga entre los procesos. Programación Concurrente 2004 - Clase 8
Concepto de “bag of tasks”. Ejemplo. Consideraremos la multiplicación de 2 matrices a y b de nxn. El ejemplo requiere n2 productos internos entre filas de a y columnas de b. Cada producto interno es independiente y se puede realizar en paralelo. Suponemos que se dispone de una máquina multiprocesador con PR procesadores físicos, PR < n. Tratando de balancear la carga, puede pensarse en n tareas en la bolsa, una por fila y que cada PR haga uso de un número de tareas de modo de distribuir la carga. Podemos representar la bolsa, simplemente contando filas: INT nextrow = 0; Un worker saca una tarea de la bolsa ejecutando una acción atómica: < row = nextrow; nextrow++; > donde row es una variable local. Notar que lo podemos implementar con un FETCH and ADD. Programación Concurrente 2004 - Clase 8
Multiplicación de matrices con el “bag of tasks”. INT nextrow =0 # la bolsa de tareas DOUBLE a[n,n], b[n,n], c[n,n]; PROCESS Worker [w=1 TO PR] { INT row; DOUBLE sum; WHILE (true) { # obtener una tarea < row = nextrow; nextrow++; > IF (row >= n) BREAK; Calcular los productos internos para c[row, *] ; } } Para terminar el proceso se pueden contar los BREAK, al llegar a n se tiene la matriz c completa y se puede finalizar el cálculo. Programación Concurrente 2004 - Clase 8
LINDA---> Primitivas para Programación Concurrente. LINDA ofrece una aproximación distintiva al procesamiento concurrente: NO es un lenguaje de programación, sino un conjunto de seis primitivas que operan sobre una memoria compartida donde hay “tuplas nombradas” (tagged tuples) que pueden ser pasivas (datos) o activas (tasks). En el enfoque de LINDA (que puede agregarse como biblioteca a cualquier lenguaje secuencial) se combinan aspectos de memoria compartida con pasaje de mensajes asincrónicos. Fue concebido en 1983 en la Tesis Doctoral de D. Gelernter (Univ. New York) y sus implementaciones sobre distintos lenguajes se desarrollaron entre esa fecha y 1989. Programación Concurrente 2004 - Clase 8
LINDA---> Primitivas para Programación Concurrente. El núcleo de la idea de LINDA es el espacio de tuplas compartidas (TS) que puede verse como un único canal de comunicaciones compartido en el que no existe orden: Depositar una tupla (OUT) funciona como un SEND. Extraer una tupla (IN) funciona como un RECEIVE. RD es la primitiva que permite “leer”como un RECEIVE pero sin extraer la tupla de TS. EVAL permite la creación de procesos (tuplas activas) dentro de TS. Por último IPD y RDP permiten hacer IN y RD no bloqueantes. Si bien hablamos de memoria compartida, TS puede estar físicamente distribuida en una arquitectura multiprocesador (con todas las complejidades asociadas). Programación Concurrente 2004 - Clase 8
LINDA---> Primitivas para Programación Concurrente. El TS consta de una colección no ordenada de tuplas pasivas y activas. Las tuplas de datos (pasivas) son registros tagged que contienen el estado compartido de un cómputo. Las tuplas activas (de proceso) son rutinas que ejecutan asincrónicamente. La interacción se da leyendo, escribiendo y generando tuplas de datos. Cuando una tupla proceso termina, se convierte en una tupla de datos. • Cada tupla de datos en TS tiene la forma: • ("tag", value1, ..., valuen) • El tag es un string literal que se usa para distinguir entre tuplas que representan distintas estructuras de datos. Programación Concurrente 2004 - Clase 8
LINDA---> Primitivas para depositar y extraer de TS. • Un proceso deposita una tupla en TS ejecutando: • out("tag", expr1, ..., exprn) • La ejecución de out termina una vez que las expresiones fueron evaluadas y la tupla de datos resultante fue depositada en TS. La operación out es similar a una sentencia send, excepto que la tupla se almacena en un TS no ordenado en lugar de ser agregada a un canal específico. • Un proceso extrae una tupla de datos de TS ejecutando: • in("tag", field1, ..., fieldn) • Cada fieldi o es una expresión o un parámetro formal de la forma ? var donde var es una variable local en el proceso ejecutante. Los argumentos para in son llamados template. El proceso que ejecuta in se demora hasta que TS contenga al menos una tupla que matchee el template, y luego remueve una de TS. Programación Concurrente 2004 - Clase 8
LINDA---> Primitivas para examinar tuplas de datos. La tercera primitiva básica de LINDA es rd, que se usa para examinar tuplas de datos. Si t es un template, la ejecución de rd(t) demora al proceso hasta que TS contiene una tupla de datos que haga matching. Como con in, las variables en t luego son asignadas con los valores correspondientes de los campos de la tupla de datos. Sin embargo, la tupla permanece en TS. Hay variantes no bloqueantes de in y rd. Las operaciones inp y rdp son predicados que retornan true si hay una tupla matching en TS, y false en otro caso. Si retornan true, tienen el mismo efecto que in y rd respectivamente. Inp y rdp proveen una manera de que un proceso haga polling sobre TS. Programación Concurrente 2004 - Clase 8
LINDA---> Primitivas para crear procesos. La sexta y última primitiva Linda es eval, que crea tuplas proceso. Esta operación tiene la misma forma que out y también produce una nueva tupla: eval("tag", expr1, ..., exprn) Al menos una expresión es un call a una función o procedimiento. Todos los campos de EVAL pueden ser tratados concurrentemente por procesos diferentes y el proceso que escribe el EVAL no espera. Cuando todos los campos son tratados (incluída la ejecución del o los procedimientos/funciones) la tupla se convierte en pasiva (quedan sólo datos) y se agrega a TS. La primitiva eval provee el medio por el cual la concurrencia se puede incorporar en un programa Linda. Programación Concurrente 2004 - Clase 8
LINDA---> Primitivas para crear procesos.Concurrencia con EVAL. • Como ejemplo, consideremos la siguiente sentencia concurrente: • co [i := 1 to n] • a[i] := (i); • oc • Esto evalúa n llamados de en paralelo y asigna los resultados al arreglo compartido a. • El código C-Linda correspondiente es: • for ( i = 1; i n; i++ ) • EVAL("a", i, f(i)); • Esto dispara (forks) n tuplas proceso; cada una evalúa un llamado de f(i). Cuando una tupla proceso termina, se convierte en una tupla de datos que contiene el nombre del arreglo, un índice y el valor de ese elemento del arregloa. Programación Concurrente 2004 - Clase 8
Generación de nros. primos con C y LINDA. (paradigma bag of tasks) Los workers comparten TS (bag of tasks). Aquí estarán los números candidatos a primos. Un proceso manager debe depositarlos y recoger los que sean confirmados como primos. Los workers buscan un candidato y deciden si es primo por el método habitual de dividirlo por los primos menores ya existentes. Si lo fuera, lo agrega a la lista (compartida) de primos. La rutina principal hace de manager. Lee los argumentos para saber cuantos primos generar, usa EVAL para crear los workers, tiene una tabla inicial con los primos 2 y 3, envía el primer candidato a primo(5) usando OUT y espera con IN recibir los primos que se vayan generando. Cada primo que recibe lo agrega a TS. Cuando la cuenta de recibidos llega a limit, imprime y termina. Programación Concurrente 2004 - Clase 8
Tareas para la próxima clase Estudiar el resto de la clase. En particular la solución de generación de números primos con LINDA y C. Estudiar las primitivas básicas de MPI y PVM. Analizar soluciones de algunos problemas clásicos con mensajes sincrónicos: Filósofos centralizados. Broadcast de un servidor a N clientes. Broadcast de cualquier proceso a N pares. Analice los problemas de la molécula de agua y el puente de una vía con mensajes sincrónicos. Plantee una solución para cada uno con un esquema C-S y suponiendo cualquier herramienta de programación de las vistas: OCCAM, C+LINDA, XX+MPI XX+PVM. Programación Concurrente 2004 - Clase 8
Ejercicio para la promoción 1- Escriba muy sintéticamente las ventajas/desventajes de mensajes sincrónicos respecto de los mensajes asincrónicos. 2- Ud. tiene una red (por ejemplo móvil) conectada sin cables. Debe hacer un análisis para que todos sepan quienes están conectados en la red. Usaría mensajes sincrónicos o asincrónicos? Por qué? 3- Si se tratara de hacer un broadcast en una red conectada en anillo, qué diferencias ve entre SMP y AMP? 4- De lo visto de OCCAM, qué utilidad le ve a la instrucción ALT? Por qué utilizaría guardas en un ALT? Con qué estructura de ADA la asimilaría? Indique alguna característica en sincronización que tenga ADA y no OCCAM. Programación Concurrente 2004 - Clase 8
Números primos con C y LINDA. El Main Real_main(INT argc, CHAR *argv[ ] ) { INT primes[ limit] = {2,3}; /*tabla de primos*/ INT limit, numworkers, i, isprime; INT numprimes=2, value=5; limit = atoi (argv[ 1]) ; /*se lee cuantos generar */ numworkers= atoi (argv[ 2] ); /* Crear los workers y poner el primer primo en TS */ FOR (i=1; i <= numworkers; i++ ) EVAL (“worker”, worker() ); OUT(“candidate”, value); /* Obtener los resultados de los workers en orden creciente */ WHILE (numprimes < limit) { IN (“result”, value, ?isprime); IF (isprime) { /*poner el valor en la tabla y en TS*/ primes[numprimes] = value; OUT (“prime”, numprimes, value); numprimes++; } value=value + 2; } OUT (“stop”); /* avisa a los workers que terminen */ IMPRIMIR; } Programación Concurrente 2004 - Clase 8
Generación de nros. primos con C y LINDA. (paradigma bag of tasks) Cada worker tiene una tabla local de factores primos. Esta tabla la va extendiendo cuando necesita nuevos primos para testear un número candidato. Este nuevo primo lo obtiene de TS en orden creciente (estricto para evitar deadlock). En cada iteración un worker usa RDP para saber si tiene que parar. Qué busca? La tupla “stop”. Notar que como los workers NO manejan limit, es posible que hagan más trabajo del necesario antes de que el manager se dé cuenta y envíe el STOP. La solución para los workers no es óptima y requiere 2 accesos a TS para un número primo (como candidato y como resultado). En general los accesos a TS serán mucho menos eficientes que aquéllos a memoria local. Programación Concurrente 2004 - Clase 8
Los procesos WORKER Void worker ( ) { INT primes[ limit] = {2,3}; /*tabla de primos*/ INT numprimes=1, i, candidate, isprime; /* Obtener repetidamente un candidato a primo y chequearlo */ WHILE (true) { IF ( RDP (“stop”) ) RETURN; IN (“candidate”, ?candidate); /*obtiene un candidato */ OUT (“candidate”, candidate +2); /* pone el siguiente candidato */ i=0; isprime=1; WHILE (primes[i] * primes[i] <= candidate { IF (candidate % primes[i] == 0) { /*NO es primo */ isprime=0; break; } i++; IF (i > numprimes ) { /* necesito otro primo */ numprimes++; RD ( “prime” , numprimes, ?primes[numprimes]); } } OUT (“result”, candidate, isprime); /*se envia el resultado al manager */ } Programación Concurrente 2004 - Clase 8
Comunicación y Sincronización en arquitecturas distribuidas: MPI. MPI (message passing interfase) es una biblioteca de rutinas de pasaje de mensajes, que permite comunicar y sincronizar procesos secuenciales escritos en diferentes lenguajes, que se ejecutan sobre una arquitectura distribuida. MPI fue definido en 1996 como una evolución de PVM y se ha constituido en un standard de hecho. El estilo de programación en MPI es SPMD (múltiples copias del mismo proceso se ejecutan en diferentes procesadores sobre diferentes datos). Cuando un proceso tiene que sincronizar o ejecutar acciones diferentes a los demás, puede utilizar primitivas de MPI (incluso para autoidentificarse). Programación Concurrente 2004 - Clase 8
La biblioteca MPI. Un ejemplo simple. Supongamos dos procesos que deben intercambiar valores (14 y 25). La solución empleando MPI tendría la siguiente forma: # include <mpi.h> main (INT argc, CHAR *argv [ ] ) { INT myid, otherid, size; INT length=1, tag=1; INT myvalue, othervalue; MPI_status status; MPI_Init (&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &size); MPI_Comm_Rank (MPI_COMM_WORLD, &myid); IF (myid == 0) { otherid = 1; myvalue=14; } ELSE { otherid=0; myvalue=25; } MPI_send (&myvalue, length, MPI_INT, otherid, tag,MPI_COMM_WORLD); MPI_recv (&othervalue, length, MPI_INT, MPI_any_source, tag, MPI_COMM_WORLD, &status); printf (“process %d received a %d\n”, myid, othervalue); MPI_Finalize ( ); } Programación Concurrente 2004 - Clase 8
La biblioteca MPI MPI_Init inicializa la biblioteca MPI y obtiene una copia de los comandos pasados al programa. La variable MPI_COMM_WORLD es inicializada con el conjunto de procesos que se arrancan. MPI_COMM_Size determina el número de procesos arrancados (2) MPI_COMM_Rank determina la identificación del proceso (0 a size-1) MPI_Finalize Termina este proceso y libera la bilioteca MPI. MPI_Send envía un mensaje a otro proceso. Los argumentos son: el buffer que contiene el mensaje, el número de elementos a enviar, el tipo de datos del mensaje, la identidad del proceso destino, un tag del usuario para identificar el tipo de mensaje y la variable MPI_COMM_WORLD. MPI_Recv recibe un mensaje de otro proceso. Los argumentos son: el buffer en el cual poner el mensaje, el número de elementos del mensaje, el tipo de datos del mensaje, la identidad del proceso que envía o “no importa”= MPI_any_source, un tag del usuario para identificar el tipo de mensaje, el grupo de comunicación y el status de retorno. Programación Concurrente 2004 - Clase 8
Algunos comentarios bibliográficos WWW.hensa.ac.uk/parallel tiene buena información sobre herramientas en OCCAM, comparación de OCCAM con ADA y las ideas de OCCAM3 (aún no implementado) WWW.comlab.ox.ac.uk/oucl/publications/books/concurrency/ tiene la info del libro de ROSCOE del 98 en el que se da la última versión de CSP. Las publicaciones de Glernter sobre su Tesis y demás y la página WWW.sca.com tienen datos de LINDA. Hay varios sitios para lo de MPI o PVM. Entre ellos: WWW.mpi.nd.edu/lam/ WWW-unix.mcs.anl.gov/mpi/mpich/ WWW.epm.ornl.gov/pvm/pvm_home.html Hartley en el 98 dio un enfoque diferente de JAVA en programación distribuída. Su página es: WWW.mcs.drexel.edu/~shartley/concProgJava/ Programación Concurrente 2004 - Clase 8