PDF de programación - Programación con Hilos

Imágen de pdf Programación con Hilos

Programación con Hilosgráfica de visualizaciones

Publicado el 22 de Marzo del 2020
1.020 visualizaciones desde el 22 de Marzo del 2020
285,2 KB
27 paginas
Creado hace 6a (29/01/2018)
Programación con Hilos



Contenido

• Conceptos generales de programación paralela
• Programación con hilos
• Pthreads
• Sincronización
• Exclusión mutua (Mutex)
• Variables condición (Var Condition)



Preliminares: Computación Paralela

• Paralelismo: Múltiples cálculos que se realizan

simultáneamente.
– A nivel de instrucción (pipelining)
– Paralelismo de datos (SIMD)
– Paralelismo de tareas (vergonzosamente paralelo)
• Concurrencia: Múltiples cálculos que pueden ser

realizados simultáneamente.
• Concurrencia vs. Paralelismo



Concurrencia y Paralelismo

do_another_thing()

do_one_thing()

do_wrap_up()

do_one_thing()

do_another_thing()

do_wrap_up()

do_one_thing()

do_wrap_up()

do_another_thing()

Tiempo



4

Procesos vs. Hilos

• Proceso (Process): Instancia de un programa que se
está ejecutando en su propio espacio de direcciones. En
sistemas POSIX, cada proceso mantiene su propio
heap, pila, registro, descriptores de ficheros, etc.
Comunicación:

• Memoria compartida
• Red
• Pipes, Colas

• Hilo (Thread): Una versión ligera del proceso que
comparte dirección con otros hilos. En sistemas POSIX,
cada hilo mantiene sus propios: registros, pila, señales.
Comunicación:

• Espacio de direcciones compartido



Concurrencia usando hilos

• Ejecución serializada:

– Hasta ahora… nuestros programas constan de un solo hilo.
– Un programa termina su ejecución cuando su hilo termina su

ejecución.

• Multi-hilos:

de ejecución

– Un programa es organizado como múltiples y concurrentes hilos

– El programa principal puede crear (spawns) muchos hilos
– El hilo puede comunicarse con otro(s) hilo(s).
– Ventajas potenciales:

• Mejora de rendimiento
• Mejores tiempos de respuesta
• Mejora en la utilización de recursos
• Menor cantidad de trabajo extra comparada con el uso de múltiples

procesos.



Programación Multihilos

Incluso en C, la programación multihilos puede ser
realizada de diversas formas:
– Pthreads: biblioteca POSIX C,
– OpenMP,
– Intel threading building blocks,
– Cilk (de CSAIL!),
– Grand central dispatch,
– CUDA (GPU) y
– OpenCL (GPU/CPU)







No todo el código es paralelizable

float params[10];

for (int i=0; i<10; i++)
do_something ( params[i] );

float params[10];
float prev = 0;

for (int i=0; i<10; i++)
prev = complicated ( params[i], prev);

Paralelizable

No paralelizable



No todo el código multi-hilos es seguro

int balance =500;
void deposit ( int sum ) {

int currbalance=balance ; /
...
currbalance+=sum ;
balance=currbalance ; /



}
void withdraw ( int sum ) {

int currbalance=balance ; /
if ( currbalance >0)
currbalance−=sum ;

balance=currbalance ; /

}

... deposit (100); /
thread 1 /
... withdraw (50); /* thread 2 /∗

thread 3 /
. .. withdraw(100); /





...



read balance


/

write balance


/



read balance


/

write balance


/

Escenario: T1(read),T2(read,write),T1(write) ,balance=600
Escenario: T2(read),T1(read,write),T2(write) ,balance=450



API del pthread

API:
• Gestión de Hilos: crear, unir, atributos

pthread__ 

• Exclusión mutua: crear, destruir exclusión mutua

pthread_mutex_ 

• Variables condición: crear, destruir, esperar y continuar

pthread_cond_

• Sincronización: lectura/escritura candados y barreras

pthread_rwlock_, pthread_barrier_ 

API:
#include <pthread.h> 
gcc −Wall −O0 −o <output> file.c −pthread (no −l prefix) 



Creación de hilos

int pthread_create( pthread_t *thread, 

   const pthread _attr _t  *attr, 

                void  (  start _routine )( 

              void *arg );

∗ ∗

void  ), ∗

• Crea un nuevo hilo que tiene los atributos especificados por attr.
• Utiliza las opciones de defecto de atributos cuando attr es NULL.
• Si no se producen errores en la creación, se almacena el hilo en thread
• Se invoca la función start_routine(arg) en un hilo de ejecución

diferente.

• Regresa cero si triunfa la creación, diferente de cero si se produce un error.

void pthread_exit(void  value_ptr); 
• Se invoca implícitamente cuando termina la función thread.
• Análogo con exit()





Ejemplo

#include <pthread . h>
#include <stdio.h>
#define NUM_THREADS 5



void





threadid )

void PrintHello (
{
long tid ;
tid = ( long ) threadid ;
printf( " Hello World ! It's me, thread #%ld ! \ n " , tid ) ;
pthread _exit(NULL ) ;
}
int main ( int argc , char argv [ ] )
{
pthread_t threads [NUM_THREADS] ;
int r c ;
long t ;
for ( t =0; t <NUM_THREADS; t ++) {
printf ( " In main : c reat ing thread %l d \ n " , t ) ;
rc = pthread_create (& threads [ t ] , NULL, PrintHello( void
if ( rc ) {
printf("ERROR; return code from pthread_create ( ) i s %d \ n ", rc ) ;
exit( −1);
}
}
pthread_exit(NULL ) ;
}

) t ) ;





Traza de salida



Sincronización: unión (joining)



"Joining" es una manera de lograr la sincronización entre hilos. Ejemplo:

int pthread_join(pthread_t thread, void


∗∗

value_ptr);

pthread_join() Bloquea el thread que hace la llamada hasta que el thread especificado como
atributo termina su ejecución.
Si value_ptr es distinto de null, contiene el estatus de finalización del thread invocado.



Otras formas de sincronización: exclusión mutua (mutex), variables de condición



Exclusión mutua

• Mutex (exclusión mutua) actúa como un “candado" para proteger el

• Solo un hilo a la vez “posee” el candado. Los hilos deben turnarse

acceso a un dato.

para acceder al dato.

int pthread_mutex_destroy ( pthread_mutex_t mutex ) ;
int pthread_mutex_init ( pthread_mutex_t *mutex ,
const pthread_mutexattr_t attr );
thread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;



– pthread_mutex_init() inicializa un “mutex”. Si los atributos valen

NULL, entonces se usan los valores de defecto de la librería.

– La macro PTHREAD_MUTEX_INITIALIZER puede usarse para

inicializar “mutexes” estáticos.

– pthread_mutex_destroy() destruye el “mutex”.
– Ambas funcionan regresan 0 si no hay error, y un valor distinto de cero

si se produce algún error.



Exclusión mutua

int pthread_mutex_lock ( pthread_mutex_t mutex ) ;
int pthread_mutex_trylock ( pthread_mutex_t mutex ) ;
int pthread_mutex_unlock ( pthread_mutex_t mutex ) ;





• pthread_mutex_lock() bloquea (cierra) la variable mutex.
Si la variable mutex está bloqueada (cerrada), la función que
hizo la llamada se bloquea hasta que la variable mutex esté
disponible (no-bloqueada).

• pthread_mutex_trylock() es la versión no-bloqueante.

Si la variable mutex está bloqueada (cerrada), la llamada
regresa inmediatamente.

• pthread_mutex_unlock() desbloquea (abre) la variable

mutex.



Ejemplo revisado



read balance


/

int balance =500;
void deposit ( int sum ) {

int currbalance=balance ; /
...
currbalance+=sum ;
balance=currbalance ; /



}
void withdraw ( int sum ) {

int currbalance=balance ; /
if ( currbalance >0)
currbalance−=sum ;

balance=currbalance ; /
}

... deposit (100); /
thread 1 /
... withdraw (50); /* thread 2 / ∗

... withdraw(100); /
thread 3 /




...

write balance


/



read balance


/

write balance


/

Escenario: T1(read),T2(read,write),T1(write) ,balance=600
Escenario: T2(read),T1(read,write),T2(write) ,balance=450



int balance =500;
pthread_mutex_t mutexbalance=PTHREAD_MUTEX_INITIALIZER;
void deposit ( int sum ) {
pthread_mutex_lock(&mutexbalance );
{



read balance

int currbalance=balance ; /
...
currbalance+=sum ;
balance=currbalance ; /
}
pthread_mutex_unlock(&mutexbalance );

write balance


/




/

}
void withdraw ( int sum ) {
pthread_mutex_lock(&mutexbalance );
{

Usando

Exclusión Mutua



read balance

int currbalance=balance ; /
if ( currbalance >0)
currbalance−=sum ;
balance=currbalance ; /
}
pthread_mutex_unlock(&mutexbalance );

write balance




/


/

}


thread 1 /
... deposit (100); /
... withdraw (50); /* thread 2 / ∗


... withdraw(100); /
thread 3 /
...

Escenario: T1(read),T2(read,write),T1(write) ,balance=550
Escenario: T2(read),T1(read,write),T2(write) ,balance=550



Ejemplo: Versión secuencial del

producto de dos vectores

#include <stdio.h>
#include <stdlib.h>

typedef struct {
double *a;
double *b;
double sum;
int veclen; } DOTDATA;

#define VECLEN 100000
DOTDATA dotstr;



void dotprod() {
int start, end, i;
double mysum, *x, *y;
start=0;
end = dotstr.veclen;
x = dotstr.a;
y = dotstr.b;
mysum = 0;
for (i=start; i<end ; i++) {
mysum += (x[i] * y[i]);
}
dotstr.sum = mysum;
}

int main (int argc, char *argv[]) {
int i,len;
double *a, *b;

len = VECLEN;
a = (double*) malloc (len*sizeof(double));
b = (double*) malloc (len*sizeof(double));

for (i=0; i<len; i++) {
a[i]=1; b[i]=a[i]; }
dotstr.veclen = len;
dotstr.a = a;
dotstr.b = b;
dotstr.sum=0;
dotprod ();
printf ("Sum = %f \n", dotstr.sum);
free (a);
free (b);
}



Ejemplo: Versión concurrente del

producto de dos vectores

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct
{
double *a;
double *b;
double sum;
int veclen;
} DOTDATA;

#define NUMTHRDS 4
#define VECLEN 100000
DOTDATA dotstr;
pthread_t callThd[NUMTHRDS];
pthread_mutex_t mutexsum;

void *dotprod(void *arg)
{

int i, start, end, len ;
long offset;
double mysum, *x, *y;
offset = (long)arg;

len = dotstr.veclen;
start = offset*len;
end = start + len;
x = dotstr.a;
y = d
  • Links de descarga
http://lwp-l.com/pdf17426

Comentarios de: Programación con Hilos (0)


No hay comentarios
 

Comentar...

Nombre
Correo (no se visualiza en la web)
Valoración
Comentarios...
CerrarCerrar
CerrarCerrar
Cerrar

Tienes que ser un usuario registrado para poder insertar imágenes, archivos y/o videos.

Puedes registrarte o validarte desde aquí.

Codigo
Negrita
Subrayado
Tachado
Cursiva
Insertar enlace
Imagen externa
Emoticon
Tabular
Centrar
Titulo
Linea
Disminuir
Aumentar
Vista preliminar
sonreir
dientes
lengua
guiño
enfadado
confundido
llorar
avergonzado
sorprendido
triste
sol
estrella
jarra
camara
taza de cafe
email
beso
bombilla
amor
mal
bien
Es necesario revisar y aceptar las políticas de privacidad