Successfully reported this slideshow.

Hebras En Accion

3,790 views

Published on

Hebras

  • Be the first to comment

Hebras En Accion

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

×