PROGRAMACIÓN PARALELA Tema 2: Lenguajes y modelos de programación paralela

download PROGRAMACIÓN PARALELA Tema 2: Lenguajes y modelos de programación paralela

If you can't read please download the document

  • date post

    06-Jan-2016
  • Category

    Documents

  • view

    55
  • download

    3

Embed Size (px)

description

PROGRAMACIÓN PARALELA Tema 2: Lenguajes y modelos de programación paralela. Programación con THREADS David R. Butenhof: Programming with POSIX Threads. Addison-Wesley. 1996. Cap 1, 2, 3, 4 Ejemplos en: www.awl.com/cseng/titles/0-201-63392-2. Threads/Procesos. Thread tiene: - PowerPoint PPT Presentation

Transcript of PROGRAMACIÓN PARALELA Tema 2: Lenguajes y modelos de programación paralela

  • PROGRAMACIN PARALELA

    Tema 2: Lenguajes y modelos de programacin paralela

    Programacin con THREADS David R. Butenhof: Programming with POSIX Threads. Addison-Wesley. 1996.Cap 1, 2, 3, 4Ejemplos en:www.awl.com/cseng/titles/0-201-63392-2

  • Threads/ProcesosThread tiene:Direccin de instruccinPilaRegistro de datosProceso tiene:Lo del thread +Espacio de direccionesDescriptores de ficherosThreads en un proceso comparten:Espacio de direccionesDescriptores de ficheros

  • Elementos de programacin con ThreadsThread:Entidad capaz de actividad independiente

    Elementos compartidos:MemoriaObjetos para sincronizacin (mutex)

    Mecanismos de comunicacin:Indicar cambios en datos compartidos (variables condicin)Los threads esperan a que se cumpla una condicinSe pueden sealar o hacer broadcast

  • Control de concurrenciaContexto de ejecucin:Debe mantenerse independiente

    Poltica de Scheduling:Determina qu contexto se ejecuta en cada instante y el paso de uno a otro

    Sincronizacin:Mecanismos para coordinar el uso de recursos compartidos: mutex, variables de condicin, semforos, eventos, mensajes, ...

  • Uso de ThreadsBeneficios:Explotacin del paralelismoExplotacin de concurrencia (I/O)Estilo de programacinInconvenientes:Overhead por creacin de threadsSincronizacin: ms bloqueos al haber ms threadsColisiones en el acceso a memoriaMs difcil la depuracin: debuggers, trazadores, puntos de ruptura, repreduccin de la ejecucin, ...Uso de programacin con threads:Computacin intensivaVarios procesadoresSolapamiento computacin y I/OAplicaciones servidor distribuidas

  • Ejemplo alarm secuencialPrograma:Un nico proceso que procesa comandos simples en los que se dice que recuerde una alarma despus de un intervalo de tiempo.

    Inconveniente:Slo se puede procesar una alarma detrs de otra.

  • int main (int argc, char *argv[]){ int seconds; char line[128]; char message[64];

    while (1) { printf ("Alarm> "); if (fgets (line, sizeof (line), stdin) == NULL) exit (0); if (strlen (line)

  • Ejemplo alarm_fork, procesosPrograma:

    el proceso principal lee peticiones de alarma,

    pone en marcha un proceso hijo por cada peticin de alarma,

    cada proceso hijo espera el tiempo correspondiente y escribe el mensaje de alarma.

  • #include #include

    int main (int argc, char *argv[]){ int status; char line[128]; int seconds; pid_t pid; char message[64]; ... else { pid = fork (); if (pid == (pid_t)-1) errno_abort ("Fork"); if (pid == (pid_t)0) { /*If we're in the child, wait and then print a message*/ sleep (seconds); printf ("(%d) %s\n", seconds, message); exit (0); } else {/*In the parent, call waitpid() to collect any children that have already terminated*/ do { pid = waitpid ((pid_t)-1, NULL, WNOHANG); if (pid == (pid_t)-1) errno_abort ("Wait for child"); } while (pid != (pid_t)0); } } } }

  • Ejemplo alarm_thread, threadsPrograma:Como el de procesos pero usando threads.

    Usa: pthread_create, para crear un thread e indicar la rutina que tiene que ejecutar, pthread_detach, para retomar los recursos una vez acaba el thread, pthread_exit, para acabar el thread

  • #include

    typedef struct alarm_tag { int seconds; char message[64];} alarm_t;

    /*Rutina que usan los threads*/void *alarm_thread (void *arg){ alarm_t *alarm = (alarm_t*)arg; int status;

    status = pthread_detach (pthread_self ()); if (status != 0) err_abort (status, "Detach thread"); sleep (alarm->seconds); printf ("(%d) %s\n", alarm->seconds, alarm->message); free (alarm); return NULL;}

  • int status;char line[128];alarm_t *alarm;pthread_t thread;

    while (1) {... alarm = (alarm_t*)malloc (sizeof (alarm_t)); if (alarm == NULL) errno_abort ("Allocate alarm"); if (sscanf (line, "%d %64[^\n]", &alarm->seconds, alarm->message) < 2) { fprintf (stderr, "Bad command\n"); free (alarm); } else { status = pthread_create (&thread, NULL, alarm_thread, alarm); if (status != 0) err_abort (status, "Create alarm thread"); } }

  • Uso de threadspthread_t thread;

    int pthread_equal (pthread_t t1,pthread_t t2);

    int pthread_create (pthread_t *thread,const pthread_attr_t *attr,void *(*start)(void *),void *arg);

    Int sched_yield (void);

    pthread_t pthread_self (void);

    int pthread_exit (void *value_ptr);

    int pthread_detach (pthread_t thread);

    int pthread_join (pthread_t thread,void **value_ptr);

  • Uso de threadsUn thread se representa por un identificador, de tipo pthread_tUn thread se pone en marcha llamando a la funcin cuya direccin se pasa como tercer parmetro de pthread_create. Esta funcin recibe un argumento de tipo void * y devuelve lo mismo. Devuelve un identificador de thread.pthread_self lo puede usar un thread para conocer su identificador.pthread_equal se usa para comprobar si dos indentificadores de thread se refieren al mismo thread.pthread_detach se usa para decir al sistema que puede utilizar los recursos que se asignaron al thread. El detach lo puede hacer cualquier thread que sepa su identificador de thread. En la creacin se puede especificar con un atributo que no se quiere tener control sobre el thread.pthread_join se usa para bloquear hasta que acaba el thread. Libera los recursos del thread.

  • Sincronizacin

    Se puede sincronizar asegurando el acceso en exclusin mutua a variables. Se usan mutex.

    O usando variables condicin, que comunican informacin sobre el estado de datos compartidos

  • Creacin y destruccin de mutexpthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;Un mutex se representa por una variable de tipo pthread_mutex_t.No se debe hacer copias de mutex, pero s se pueden copiar punteros a mutex, para usarlos varios threads.Para crear un mutex esttico con atributos por defecto se usa la macro PTHREAD_MUTEX_INITIALIZER.int pthread_mutex_init (pthread_mutex_t *mutex,pthread_mutexattr_t *attr);Se usa para inicializar un mutex dinmicamente o con atributos que no son los de defecto.Cada mutex se debe inicializar una nica vez antes de usarse.int pthread_mutex_destroy (pthread_mutex_t *mutex);Para destruir un mutex.Lo normal es asociar el mutex con los datos que protege, y destruir el mutex antes de liberar la memoria de esos datos.

  • Bloqueo y desbloqueo de mutexint pthread_mutex_lock (pthread_mutex_t *mutex);Bloquea un mutex.No se puede bloquear un mutex cuando el thread ya lo tiene bloqueado. Esto devuelve un cdigo de error, o se bloquea el thread.int pthread_mutex_unlock (pthread_mutex_t *mutex);Para desbloquear mutex.No se puede desbloquear un mutex desbloqueado, ni un mutex bloqueado por otro thread, pues los mutex pertenecen a los threads que los bloquean.int pthread_mutex_trylock (pthread_mutex_t *mutex);Bloquea un mutex si no est bloqueado.

  • Ejemplo alarm_mutexSe utiliza una lista de alarmas, ordenadas por tiempo de expiracin.

    typedef struct alarm_tag { struct alarm_tag *link; int seconds; time_t time; /* seconds from EPOCH */ char message[64];} alarm_t;

    pthread_mutex_t alarm_mutex=PTHREAD_MUTEX_INITIALIZER;alarm_t *alarm_list = NULL;

  • Ejemplo alarm_mutexSe usa un nico thread para tratar las alarmas.

    Acaba cuando acaba el thread principal.Se podra modificar usando una variable que indique que se ha acabado el trabajo. Cuando el thread encuentra la lista vaca y esa variable a fin puede acabar con pthread_exit.

    Con sched_yield se cede el procesador a otro thread, y si no hay ninguno esperando vuelve el control al que llama.

  • void *alarm_thread (void *arg){ alarm_t *alarm; int sleep_time; time_t now; int status;/*Bucle infinito para procesar los comandos*/ while (1) { status = pthread_mutex_lock (&alarm_mutex); if (status != 0) err_abort (status, "Lock mutex"); alarm = alarm_list; if (alarm == NULL) sleep_time = 1; /*Si vaca esperar un segundo*/ else { alarm_list = alarm->link; now = time (NULL); /*Si no tomar el primero*/ if (alarm->time time - now; } status = pthread_mutex_unlock (&alarm_mutex); if (status != 0) err_abort (status, "Unlock mutex"); if (sleep_time > 0) sleep (sleep_time); else sched_yield (); /*If a timer expired, print the message and free the structure.*/ if (alarm != NULL) { printf ("(%d) %s\n", alarm->seconds, alarm->message); free (alarm); } } }

  • int main (int argc, char *argv[]){ int status; char line[128]; alarm_t *alarm,**last,*next; pthread_t thread; status = pthread_create (&thread, NULL, alarm_thread, NULL); if (status != 0) err_abort (status, "Create alarm thread"); while (1) { printf ("alarm> "); if (fgets (line, sizeof (line), stdin) == NULL) exit (0); if (strlen (line) seconds,alarm->message)time = time (NULL) + alarm->seconds; last = &alarm_list; /*Insertar la nueva alarma*/ next = *last; while (next != NULL) { if (next->time >= alarm->time) { alarm->link = next; *last = alarm; break; } last = &next->link; next = next->link; } if (next == NULL) { *last = alarm; alarm->link = NULL; } status = pthread_mutex_unlock (&alarm_mutex); if (status != 0) err_abort (status, "Unlock mutex"); } } }

  • Ejemplo alarm_mutexProblemas:Una vez se toma una alarma de la cola se espera hasta que expira.Cuando no hay alarmas que atender espera un segundo. Durante este tiempo puede venir otra alarma que haya que atender.

    Solucin:Usar variables condicin.

  • Creacin y destruccin de variables condicinpthread_cond_t cond=PTHREAD_COND_INITIALIZER;Una variable condicin se representa por una variable de tipo pthread_cond_t.No se debe hacer copias de variables condicin, pero s se pueden copiar punteros a ellas, para usarlas varios threads.Para crear una variable condicin esttica con atributos por defecto se usa la macro PTHREAD_COND_INITIALIZER.int pthread_cond_init (pthread_cond_t *cond,pthread_condattr_t *attr);Se usa para inicializar una variable condicin dinmicamente o con atributos que no son los de defecto.Cada variable condicin se debe inicializar una nica vez antes de usarse.int pthread_cond_destroy (pthread_cond_t *cond);Para destruir una variable condicin.Lo normal es asociar el mutex y la variable condicin con los datos que protegen.

  • Espera en variables condicinint pthread_cond_wait (pthread_cond_t *cond,pthread_mutex_t *mutex);Cada variable condicin se asocia a un mutex.Cuando un thead espera en una variable condicin el mutex debe estar bloqueado.La operacin wait desbloquea el mutex antes de bloquear el thread, y lo bloquea antes de volver a la ejecucin.El predicado se debe testear despus de bloquear el mutex y antes de esperar en la varaible condicin.El predicado se debe testear al ser activado.int pthread_cond_timedwait (pthread_cond_t *cond,pthread_mutex_t *mutex,struct timespec *expiration);Espera como mucho el tiempo que se indica.

  • Activacin de variables condicin

    Int pthread_cond_signal (pthread_cond_t *cond);Activa un thread que espera en la variable condicin.

    Int pthread_cond_broadcast (pthread_cond_t *cond);Activa todos los threads que esperan en la variable condicin.Cuando los threads se activan tendrn que volver a evaluar el predicado y algunos de ellos posiblemente se volvern a bloquear.

  • Ejemplo alarm_condEl thread est en una variable condicin mientras espera para dar la alarma.

    Si el main procesa una nueva alarma activa al threads para que compare la alarma que est esperando a procesar con la nueva alarma.

    Se usa una funcin para insertar en la lista de alarmas. Ser llamada por el main y el thread.

  • Ejemplo alarm_condtypedef struct alarm_tag { struct alarm_tag *link; int seconds; time_t time; /* seconds from EPOCH */ char message[64];} alarm_t;

    pthread_mutex_t alarm_mutex=PTHREAD_MUTEX_INITIALIZER;pthread_cond_t alarm_cond=PTHREAD_COND_INITIALIZER;alarm_t *alarm_list = NULL;time_t current_alarm = 0;

  • void alarm_insert (alarm_t *alarm){ int status; alarm_t **last, *next;/*Es necesario que el thread que llama haya bloqueado el mutex*/ last = &alarm_list; next = *last; while (next != NULL) { if (next->time >= alarm->time) { alarm->link = next; *last = alarm; break; } last = &next->link; next = next->link; } if (next == NULL) { *last = alarm; alarm->link = NULL; }/*Activar el thread si no est ocupado o la nueva alarma es la primera*/if (current_alarm == 0 || alarm->time < current_alarm) { current_alarm = alarm->time; status = pthread_cond_signal (&alarm_cond); if (status != 0) err_abort (status, "Signal cond"); } }

  • void *alarm_thread (void *arg){ alarm_t *alarm; struct timespec cond_time; time_t now; int status, expired; status = pthread_mutex_lock (&alarm_mutex); if (status != 0) err_abort (status, "Lock mutex"); while (1) { current_alarm = 0; while (alarm_list == NULL) { status = pthread_cond_wait (&alarm_cond, &alarm_mutex); if (status != 0) err_abort (status, "Wait on cond"); } alarm = alarm_list; alarm_list = alarm->link; now = time (NULL); expired = 0; if (alarm->time > now) { cond_time.tv_sec = alarm->time; cond_time.tv_nsec = 0; current_alarm = alarm->time; while (current_alarm == alarm->time) { status = pthread_cond_timedwait (&alarm_cond, &alarm_mutex, &cond_time); if (status == ETIMEDOUT) { expired = 1; break; } if (status != 0) err_abort (status, "Cond timedwait"); } if (!expired) alarm_insert (alarm); } else expired = 1; if (expired) { printf ("(%d) %s\n", alarm->seconds, alarm->message); free (alarm); } } }

  • int main (int argc, char *argv[]){ int status; char line[128]; alarm_t *alarm; pthread_t thread; status = pthread_create (&thread, NULL, alarm_thread, NULL); if (status != 0) err_abort (status, "Create alarm thread"); while (1) { printf ("Alarm> "); if (fgets (line, sizeof (line), stdin) == NULL) exit (0); if (strlen (line) seconds, alarm->message) < 2) { fprintf (stderr, "Bad command\n"); free (alarm); } else { status = pthread_mutex_lock (&alarm_mutex); if (status != 0) err_abort (status, "Lock mutex"); alarm->time = time (NULL) + alarm->seconds; alarm_insert (alarm); status = pthread_mutex_unlock (&alarm_mutex); if (status != 0) err_abort (status, "Unlock mutex"); } }}

  • Modelos de programacinEn el captulo 4, con ejemplos.Utilizar el que se crea conveniente para programar en threads la primera prctica.

    Pipeline:Cada thread ejecuta la misma operacin sobre secuencia de datos de entrada, y pasa el resultado a otro thread.Granja de trabajadores:Los threads trabajan independientemente sobre datos distintos.Cliente/servidor:Un cliente pide a un servidor que haga un trabajo.Puede ser una peticin annima que se manda a una cola de trabajos.