104
Programación de Memoria Compartida openMP

Programación de Memoria Compartida openMP. El Modelo de Memoria Compartida Los procesadores interactuan uno con otro mediante variables compartidas. OpenMP

Embed Size (px)

Citation preview

  • Programacin de Memoria CompartidaopenMP

  • El Modelo de Memoria CompartidaLos procesadores interactuan uno con otromediante variables compartidas.

    OpenMP es el estandar para programacin de memoria compartida.

  • Que es openMP?openMP es una especificacin para una implementacin portable de paralelismo en FORTRAN y C/C++. La especificacin provee directivos de compilador, rutinas de biblioteca que se pueden usar para controlar paralelismo.

  • Paralelismo Fork/Join Inicialmente solamente el hilo maestro est activoEl hilo maestro ejecuta el cdigo secuencialFork: El hilo maestro crea hilos adicionales para ejecutar el cdigo paraleloJoin: Al finalizar de cdigo paralelo, los hilos creados mueren o se suspendien

  • Ejemplo#include #include int main (int argc, char *argv[]) {#pragma omp parallel printf(Hello world\n);return 0; }

  • El Modelo de Memoria Compartida vs. el Modelo que Pasa Mensajes (#1)El modelo de memoria compartidaEl nmero de hilos es 1 al principio y al final y cambia dinmicamente durante de la ejecutacin del programaEl Modelo que pasa mensajesTodos los procesos estan activos durante de la ejecutacion del programa.

  • Paralelizacin Incremental Un programa secuencial es un caso especial de un programa de memoria compartida

    Paralelizacin incremental es el procesos de convertir un programa secuencial a un programa paralelo poco a poco

  • Un Bucle for ParaleloLas iteraciones de un bucle for se pueden ejecutar en paralelo si ninguna iteracin depende de otra anterior.Ejemplos: Las iteraciones de - for (i=first;i
  • PragmasUna pragma en C o C++ es un directivo al compilador.La sintaxis es #pragma omp Ejemplo: #pragma omp parallel fores una directriz que dice al compilador que trate a paralelizar el bucle for que sigue

  • La Pragma for Paralelo#pragma omp parallel forfor (i = 0; i < N; i++) a[i] = b[i] + c[i];

    El compilador tiene que verificar que cuando se ejecuta, habr disponible la informacin necesaria para llevar a cabo las iteraciones

  • La sintaxis de la pragma for paralelo

  • El Contexto de EjecutacinTodo hilo tiene un contexto de ejecutacin, que consiste del espacio de direcciones que el hilo puede acederEl contexto de ejecutacin incluye variables estticas, estructuras dinmicamente asignadas, y variables en el run-time stack

  • Variables Compartidas y Variables PrivadasUna variable compartida tiene la misma direccin en el contexto de ejecutacin de cada hilo.Una variable privada tiene una direccin distinta en el contexto de ejecutacin de cada hilo.Un hilo no puede aceder las variables privadas de otro hilo.

  • Funcin omp_set_num_threadsSe usa para asignar el nmero de hilos a ser activos en secciones paralelas del cdigoSe puede llamar en varios puntos del programa

    void omp_set_num_threads (int t)

  • omp_get_thread_num()

    Todo hilo tiene una identificacin que es el nmero del hiloomp_get_thread_num() devuelve el nmero del hilo

  • Funcin omp_get_num_procsDevuelve el nmero de procesadores fisicos que estn dispondible para el uso del programa paralelo

    int omp_get_num_procs (void)

  • Hello World#include #include int main (int argc, char *argv[]) { int p,th_id; p=omp_get_num_procs(); omp_set_num_threads(p); #pragma omp parallel private(th_id); { th_id = omp_get_thread_num(); printf("Hello World from thread %d\n", th_id); } return 0; }

  • Pragmas - REPASOUna pragma en C o C++ es un directivo al compilador.La sintaxis es #pragma omp Ejemplo: #pragma omp parallel fores una directriz que dice al compilador que trate a paralelizar el bucle for que sigue

  • La sintaxis de la pragma for paralelo

  • Ejemplo 1#pragma omp parallel for for (i=0;i
  • Ejemplo 2flag = 0;for (i=0;(i
  • Ejemplo 3for (i=0;i
  • Variables privadas y compartidas#pragma omp parallel bloqueLa clausula puede ser private (lista de variables) shared (lista de variables) y otras.

  • Variables privadas y compartidas(2)Una variable compartida tiene la misma direccin en el contexto de ejecutacin de cada hiloUna variable privada tiene una direccin distinta en el contexto de ejecutacin de cada hiloCada variable en el cuerpo de un bucle paralelo, excepto la variable de iteracin, que no se especifica como privada es compartida.

  • Ejemplo//Despues de ejecutar el siguiente cdigo, debe ser cierto que a[i]
  • Ejemplo(continuado)No funciona correctamente, pues la variable temp debe ser privada//El cdigo correcto #pragma omp parallel for private(temp) for (i=0;i b[i]) {temp=a[i];a[i]=b[i]; b[i]=temp;}

  • Grafos con PesosUn grafo dirigido en la cual hay asociado con cada arista un nmero positivo (el peso) se llama un grafo dirigido con pesos. El largo de una trayectoria de un vrtice u a otro vrtice v es la suma de los pesos de las aristas que componen la trayectoria.

  • El Problema de Todos Pares Distancias mas CortasDado un grafo dirigido con pesos, cuales son las trayectorias de largos mnimos (es decir distancias mas cortas) entre todos los pares de vrtices?

  • La Matrz de Adyacencias

    Representar un grafo dirigido con pesos G con n vrtices por una matrz AG como sigue:Si 1,2, ,n son los vrtices, entonces el elemento en la fila #i y la columna #j es 0 si i=j, es (un nmero mas grande que cualquier peso) si no hay arista de I a j, y es el peso de la arista de i a j si tal arista existe. Llamemos AG la matrz de adyacencias.

  • El Algoritmo de Floydfor (k= 0;k
  • EjemploAEBCD46135312Matrz de Adyacencias

  • Como se puede paralelizar el Algoritmo de Floyd para openMP?for (k= 0;k
  • Cual es el mejor? Paralelizar el bucle en el medio o el mas interior?

    Mejor paralelizar el bucle en el medio paraEvitar el costo de multiplos fork-join.

  • Como se puede paralelizar el siguiente cdigo?x[0] = complex_function();for (i=0;j
  • Como se puede paralelizar el siguiente cdigo:x[0] = complex_function();for (i=0;j
  • firstprivate Se podra mover la inicializacin de x[0] a dentro del bucle anterior, pero es caro.Mejor usar la clusula firstprivate.x[0] = complex_function();#pragma omp parallel for private[j] firstprivate(x)for (i-0;j
  • firstprivate Se podra mover la inicializacin de x[0] a dentro del bucle anterior, pero es caro.Mejor usar la clusula firstprivate.x[0] = complex_function();#pragma omp parallel for private[j] firstprivate(x)for (i-0;j
  • firstprivate (cont)Se usa para crear una variable privada que tiene su valor inicial igual al valor de la variable controlada por el hilo maestro cuando se entra el bucle.Si un hilo cambia el valor de una variable en alguna iteracin, entonces este valor ser el valor de la variable en iteraciones subsecuentes

  • lastprivate La secuencialmente ltima iteracin es la ltima iteracin que se lleva a cabo cuando el bucle se ejecuta secuencialmenteLa clusula lastprivate se usa para copiar el valor privado del hilo que ejecut la secuencialmente ltima iteracin a la copia del hilo maestro

  • Ejemplofor (i=0;i
  • Una solucin para que x[3]=n3#pragma omp parallel for private(j) lastprivate(x)for (i=0;i
  • La Regla Rectangulo para Computar = 01 4/(1+x2) dx

    La Regla de Rectangulo consiste de estimar el area debajo de la curva y=4/(1+x2) entre x=0 y x=1 mediante areas de rectangulos

  • Cdigo para aproximar double area, pi, x;int i, n;...area = 0.0;for (i = 0; i < n; i++) { x += (i+0.5)/n; area += 4.0/(1.0 + x*x);}pi = area / n;

  • Como se puede paralelizar el cdigo para aproximar a ?for (i = 0; i < n; i++) { x += (i+0.5)/n; area += 4.0/(1.0 + x*x);}Si dos hilos, digamos A y B estn ejecutando dos iteraciones, entonces B podria intentar a poner area al dia mientras que A est haciendo lo mismo,B podra usar el valor de area antes deque A ha terminado a poner su nuevo valor Esto se llama una condicin de carrera

  • La Pragma critical#pragma omp critical bloque de cdigo garantiza que solamente un hilo ejecuta el bloque a la vez

  • Cdigo correcto, pero no eficientedouble area, pi, x;int i, n;...area = 0.0;#pragma omp parallel for private(x)for (i = 0; i < n; i++) { x += (i+0.5)/n;#pragma omp critical area += 4.0/(1.0 + x*x);}pi = area / n;

  • Ineficiente porque Poner area al dia a dentro de una seccin crtica no es eficiente ya queSolamente un hilo puede ejecutar la asignacin a la vez, es decir, es cdigo secuencial.El tiempo para ejecutarla puede ser una parte significativa del bucle

  • ReduccionesSe puede aadir una clusula de reduccin a una pragma parallel for Hay que especificar la operacin y la variable OpenMP lleva cuenta de los resultados parciales y los combina despues de ejecutar el bucle

  • La Clusula reduction La sintaxis es: reduction ( :)Operadores + Suma * Producto & Bitwise and | Bitwise or ^ Bitwise exclusive or && Logical and || Logical or

  • El Cdigo con la Clusula reduction double area, pi, x;int i, n;...area = 0.0;#pragma omp parallel for \ private(x) reduction(+:area)for (i = 0; i < n; i++) { x = (i + 0.5)/n; area += 4.0/(1.0 + x*x);}pi = area / n;

  • Compilar y Ejecutar en mathclusterPara compilar: cc fopenmp prog.c o progPara ejecutar: ./prog

  • Para medir tiempo en OpenMPEjemplo: double empezar,terminar; empezar=omp_get_wtime( ); algun cdigo terminar=omp_get_wtime(); printf(TIEMPO=%lf\n,empezar-terminar)

    El resultado es en segundos.

  • Resultados de Ejecutar pi.c en mathcluster

    hilos tiempo speedup 1 .486118 2 .284774 1.7 3 .178959 2.7 4 .157069 3.1 8 .134919 3.6

  • La multiplicacin matrz-vector Para computar y = Ax = [aij]x donde A es m X n y x es n X 1:

    for (i=0;i

  • Paralelizar el bucle exterior

    #pragma omp parallel for private(j)for (i=0;i

  • Paralelizar el bucle interior

    for (i=0;i

  • Matrices EsparcidasUna matrz es esparcida si la mayoria de sus elementos son iguales a cero.Los algoritmos ordinarios aplicados a matrices esparicidas, no son lo mas eficientes pues ocupan mucho espacio y gastan operaciones de mas.

  • Compressed Sparse Row Format(CSR) El format de fila esparcida comprimida matrz A mXn de una consiste de:(1) Un arreglo, vals, de los elementos no cero.(2) Un arreglo, cols, de los nmeros de columna en las cuales cada elemento de vals aparece.(3) Un arreglo, filas, donde filas[i] es el indice en el arreglo vals del primer elemento no cero de la fila i, i =0,1, ... , m-1, y filas[m] = nz, la cantidad de elementos no cero de A.

  • Ejemplo 1 Determinar el formato CSR (o sea los arreglos vals, cols y filas) para la siguiente matriz: 1 0 0 2 0 0 0 3 0 0 7 0 8 9 10 0 1 0 0 0 0 5 2 0 0

  • Ejemplo 2Determinar la matrz cuya representacin se da porvals: 9 3 2 7 6 8 5 4 1 1 1 2 3 4cols: 0 2 3 3 4 5 0 1 1 2 0 1 4 5filas: 0 3 5 6 8 10 14

  • La multiplicacin de una matriz nXn en el formato CSR por un vectorfor(i=0;i
  • Paralelizar el bucle exterior#pragma omp parallel for private(j,k) for(i=0;i
  • Repaso#pragma omp : #pragma omp parallel #pragma omp parallel for #pragma omp critical

    La clausula puede ser: private shared

  • Repaso 2Funciones OpenMP:void omp_set_num_threads(int t)int omp_get_num_threads()int omp_get_thread_num()Int omp_get_num_procs()

  • Otro uso del la Pragma parallelEjemplo: Como se puede optimizarlo siguiente?for (i = 0; i < m; i++) { low = a[i]; high = b[i]; if (low > high) { printf ("Exiting (%d)\n", i); break; } for (j = low; j < high; j++) c[j] = (c[j] - a[i])/b[i];}No se puede paralelizar el bucle exteriorpues contiene break.

  • Primer Intento#pragma omp parallel private(i,j)for (i = 0; i < m; i++) { low = a[i]; high = b[i]; if (low > high) { printf ("Exiting (%d)\n", i); break; }for (j = low; j < high; j++) c[j] = (c[j] - a[i])/b[i];}Ahora, cada hilo va a ejectar todas las iteraciones del bucle interior. Nos gustaria que los hilos los compartan.

  • Segundo Intento#pragma omp parallel private(i,j)for (i = 0; i < m; i++) { low = a[i]; high = b[i]; if (low > high) { printf ("Exiting (%d)\n", i); break; }#pragma omp forfor (j = low; j < high; j++) c[j] = (c[j] - a[i])/b[i];}

  • La pragma for#pragma omp for dentro de una regin paralela dice al compilador particionar las iteraciones entre los hilos

  • Segundo IntentoAhora hay solamente un problema: Cada hilo va a escribir un mensaje Exiting.. #pragma omp parallel private(i,j)for (i = 0; i < m; i++) { low = a[i]; high = b[i]; if (low > high) { printf ("Exiting (%d)\n", i); break; }#pragma omp forfor (j = low; j < high; j++) c[j] = (c[j] - a[i])/b[i];}

  • Tercer Intento#pragma omp parallel private(i,j)for (i = 0; i < m; i++) { low = a[i]; high = b[i]; if (low > high) {#prama omp single printf ("Exiting (%d)\n", i); break; }#pragma omp forfor (j = low; j < high; j++) c[j] = (c[j] - a[i])/b[i];}

  • La Pragma single#pragma omp single dice al compilar que solamente un solo hilo deberia ejecutar el bloque que sigue.

  • Cuarto IntentoFinalmente se puede remover la barrera al finalizar del segundo bucle#pragma omp parallel private(i,j,low,high)for (i = 0; i < m; i++) { low = a[i]; high = b[i]; if (low > high) {#prama omp single printf ("Exiting (%d)\n", i); break; }#pragma omp for nowaitfor (j = low; j < high; j++) c[j] = (c[j] - a[i])/b[i];}}

  • La clusula nowaitCuando se aade a un bucle for paralelo, elimina la barrera al finalizar de un bucle.

  • Dos Tipos de Paralelismo de DataLa paralelizacin del bucles for Ejemplos: El computo de , el algoritmo de FloydParalelismo de data mas general la creacin de una regin paralela mediante la pragma omp parallel Ejemplos: hello, satisfacer un circuito

  • Paralelismo Funcional Hasta ahora hemos considerado paralelismo de data nada masOpenMP nos permite asignar hilos distintos a partes distintas del cdigo (paralelismo funcional)

  • Ejemplo de Paralelismo Funcional v = alpha(); w = beta(); x = gamma(v, w); y = delta(); printf ("%6.2f\n", epsilon(x,y));

    Se puede ejecutaralpha, beta, and deltaen paralelo.

  • La pragma parallel sections Precede un bloque de k bloques de cdigo que se puede ejecutar en paralelo por k hilosLa sintaxis: #pragma omp parallel sections

  • La pragma section Precede cada bloque de cdigo dentro del bloque grande Se puede omitir para el primer bloque despus de la pragma parallel sections La sintaxis: #pragma omp section

  • Ejemplo de parallel sections#pragma omp parallel sections {#pragma omp section /* Opcional */ v = alpha();#pragma omp section w = beta();#pragma omp section y = delta(); } x = gamma(v, w); printf ("%6.2f\n", epsilon(x,y)); }

  • Otra PosibilidadEjecutar alpha ybeta en paralelo.Ejecutar gama ydelta en paralelo.

  • La otra posibilidad - usar dos secciones paralelas#pragma omp parallel sections{#pragma omp section v=alpha();#pragama omp section w=beta();}#pragma omp parallel sections { #pragma omp section y=delta(); #pragma omp section x=gamma(v,w); }printf(%6.2f\n,epsilon(x,y);

  • Uso de la pragma sections#pragma omp parallel { #pragma omp sections { #pragma omp section v = alpha(); #pragma omp section w = beta(); } #pragma omp sections { #pragma omp section x = gamma(v, w); #pragma omp section y = delta(); } } printf ("%6.2f\n", epsilon(x,y));

  • La pragma sections Aparece a dentro de un bloque paralelo de cdigoTiene el mismo significado como la pragma parallel sections Varias pragmas sections dentro de un bloque paralelo podra reducir los gastos de fork/join

  • Ejemplo de secciones#pragma omp parallel sections{#pragma omp section for(i=0;i
  • Una posibilidad mejor#pragma omp parallel{ #pragma omp for for(i=0;i
  • o simplemente#pragma parallel for for(i=0;i
  • Mejormiento en el Rendimiento de Bucles Paralelos(1) Invertiendo bucles

    (2) Ejecutando los bucles condicionalmente

    (3) Mediante el uso de schedule

  • (1) Invertiendo los BuclesMuchos fork/joins puede empeorar el rendimientoInvertir bucles puede mejorar el rendimiento siHay paralelismo en el bucle interioEl bucle exterior se puede paralelizar despus de la inversin.La inversin no disminuye la razn de cache hits

  • Ejemplo-Invertir buclesfor(i=1;i
  • Paralelizar el bucle interiorfor(i=1;i
  • Invertir los bucles#pragma omp parallel for private(i)for(j=0;j
  • Memoria CacheMemoria rpida que reduce el tiempo necesario para que el CPU busque un datoAlmanace copias de los datos de las localizaciones de la memoria principal mas usadas.Un cache hit refiere a un intento exitoso de buscar un dato en el cache.Un cache miss refiere a un intento de buscar un dato en el cache que no est

  • Ejemplo de cache miss#pragma parallel for private (i) for (j=0;j
  • (2) Ejecutando Bucles Condicionalmente

    Si un bucle tiene pocas iteraciones, los gastos generales podra ser mayor que la economia de ejecutacin paralela.La clusula if instruye al compilador determinar si el bucle se debe ejecutar en paralelo. #pragma omp parallel for if(n > 5000)

  • (3) Usando la clusula scheduleLas iteraciones de un bucles pueden variar mucho en duracin.

    Se puede usar una clusula schedule para indicar como las iteraciones se asignan a los hilos.

  • Dos tipos de schedule esttica y dinmicaSchedule esttica: todas las iteraciones se asignan a los hilos antes de ejecutarlaSchedule dinmica: solamente algunas iteraciones se asignan al prinicipio de la ejecutacin de un bucle. Las otras iteraciones se asignan a hilos que terminan sus iteraciones asignadas.

  • Esttico vs. DinmicoStatic scheduling: -Gastos generales menores (low overhead)Dynamic schedulingGastos generales mayoresPuede reduce el imbalance de trabajo

  • ChunksUn chunk es un conjunto contiguo de iteraciones que se asignan a hilosAumentar el tamao de un chunk reduce los gastos generales y podra aumentar el cache hit rateDisminuir el tamao de chunk permite uno a obtener un balance mas preciso del trabajo

  • La Clusula schedule La sintaxis: schedule ([, ])Se requiere tipo, pero el tamao del chunk es opcionalEl tipo puede serstaticdynamicguidedruntime

  • Opciones para scheduleschedule(static): asignar bloques de aproximadamente n/t iteraciones contiguas a cada hiloschedule(static,C): asignar chunks de tamao Cschedule(dynamic): asignar dinmicamente iteracones una por una.schedule(dynamic,C): asignar dinmicamente C iteraciones a la vez

  • Opciones para schedule (cont)schedule(guided, C): asignar chunks dinmicamente. Los tamaos de los chunks decrecen dependiendo de la implementacin. C es el tamao mnimo.schedule(guided): Lo mismo excepto 1 es el tamao mnimo.schedule(runtime): el tipo de schedule se escoge al tiempo de ejecutacin basado en el valor de la variable omp_schedule.

  • Ejemplo#pragma omp parallel for schedule(dynamic,1) private(j)for (i=1;i
  • Ejemplo#pragma omp parallel forfor (i=1;i
  • Ejemplo-Balancear con schedule#pragma omp parallel for schedule(dynamic 1) private(j)for (i=1;i