Hebras en acción
Cecilia Hernández
2007-1
Por qué usar hebras?
Explotar concurrencia Posible hacer varias tareas
concurrentemente• Varias hebras de ejecución en una
aplicación• Mientras tarea haciendo E/S otra usa CPU
Explotar parelismo Tareas ejecutándose en paralelo
Ejemplo simple con pthreads
// includes van aquí para pthread usar #include <pthread.h>#define NUM_HEBRAS 5void Hola(void *threadid){ printf("\n%d: Hola Hola!\n", threadid);}int main (int argc, char *argv[]){ pthread_t threads[NUM_HEBRAS]; int i, ret; for(i=0; i<NUM_HEBRAS; i++){ printf("creando hebra %d\n", i); ret = pthread_create(&threads[i], NULL,(void *)&Hola, (void *)i); if (ret){ printf("ERROR; pthread_create() retorna error %d\n", ret); exit(1); } } sleep(3); pthread_exit(NULL);}
Ejemplos
Sobreponiendo E/S Ejemplo simpleSecuencial.C Ejemplo simpleThread.C
Explotando paralelismo Ejemplo multiplicación de matrices
• www.inf.udec.cl/ejemplos/multMatrices.C• Nota implementación usa arreglos
unidimensionales para almacenar matrices• compilar como g++ -o xx xx.C -lpthread
Planificación de hebrasTambién válido para procesos
Planificador decide cuando ejecutar hebras/procesos listas
Aplicaciones no deberían asumir nada respecto al planificador Planificador es una caja negra
planificador
CPU
1 2 3 4 5
{4, 2, 3, 5, 1, 3, 4, 5, 2, …}
Qué problemas pueden surgir al usar hebras?
Aplicación hace algo incorrecto (Safety hazard) Ejemplo, problema de inconsistencia de datos Problema más común Condición de Carrera (Race
Condition)
Aplicación nunca hace lo correcto Bloqueo Mortal (Deadlocks)
Problema de desempeño Programa es muy lento porque usa demasiada
sincronización
Condición de Carrera
Salida de programa en ejecución varía y es dependiente de como las hebras involucradas fueron planificadas en la CPU Programadores deben velar por
correcto uso de recursos en sistema
Ejemplo 1
int suma = 0;void uno(int *p) { for (int i = 0; i < *p; i++) { suma++; }}int main(int argc, char *argv[]) { int r1, r2; if(argc != 3){ cout<<"Uso ./simple1 numero1 numero2"<<endl; exit(1); } r1 = atoi(argv[1]); r2 = atoi(argv[2]); uno(&r1); uno(&r2); cout<<"suma "<<suma<<endl;}
Caso secuencial Un proceso
Rutina uno es llamada dos veces secuencialmente en el tiempo
Suma siempre tendrá el mismo valor al terminar programa (dependiendo de valores de entrada)
Uno(100)
Uno(200)
tiempo
Suma=300
Ejemplo 2
//variable globalint suma = 0;
void *uno(void *p) { int *pi = (int *)p; for (int i = 0; i < *pi; i++) { suma++; }}
Ejemplo 2 (cont)
int main(int argc, char *argv[]){ int r1, r2; pthread_t thread1, thread2; if(argc != 3){ cout<<"Uso ./simple2 numero1 numero2"<<endl; exit(1); } r1 = atoi(argv[1]); r2 = atoi(argv[2]); if (pthread_create(&thread1, NULL, uno, (void *)&r1) != 0) perror("pthread_create"), exit(1); if (pthread_create(&thread2, NULL, uno, (void *)&r2) != 0) perror("pthread_create"), exit(1); if (pthread_join(thread1, NULL) != 0) perror("pthread_join"),exit(1); if (pthread_join(thread2, NULL) != 0) perror("pthread_join"),exit(1); cout<<"suma "<<suma<<endl;}
Caso multihebra
Un proceso Rutina uno asociada a dos hebras ejecutándose
concurrentemente Posibles salidas, alguna otra?
Uno(100)
Uno(200)
Uno(200)
Uno(100)
tiempo
Suma=300
Uno(100)
Uno(200)
Uno(200)
Uno(100)
Suma=283
Uno(100)
Uno(200)
Uno(200)
Uno(100)
Suma=290
Uno(200)
Uno(100)
Donde está el problema?
Sum es una variable global, compartida entre hebras en mismo proceso
Suma++ corresponde a más de una instrucción en lenguaje de máquina Leer de memoria, incrementar, escribir
en memoria Equivalente en MIPS
• lw $t0, offset($s0)• addi $t0, $t0, 1• sw $t0, offset($s0)
Vamos al detalle
Instrucciones se entrelazan en la ejecución concurrente de hebras Si suma = 0 inicialmente, cuál es el valor final?
Dado Hebra 1 y Hebra 2
tiempo lw $t0, offset($s0)
lw $t0, offset($s0)
addi $t0, $t0, 1
sw $t0, offset($s0)
addi $t0, $t0, 1
sw $t0, offset($s0)
Suma = ?
Planificador decide Cambio de hebra en CPU
Terminología
Código atómico: Sección de código que se ejecuta sin la intervención de otras hebras Ejecución toda o nada (como
transacción en bases de datos) Sección crítica: Sección de código
que accesa a recursos compartidos Recursos deben ser accesados
atómicamente
Top Related