Está en la página 1de 14

EJERCICIOS OMP

HOLA1.C

ENUNCIADO
Generación de varios threads y modificación del número de threads
mediante: export OMP_NUM_THREADS= ?

SALIDA

Explicación
El código maneja una Arreglo ‘ A ’ compartido, el cual cuando el identificador
del hilo ‘ x ’ (tid), es igual al subíndice del arreglo, el valor del A [ x ] =x+10. En
la Figura 1.2 se ejecuta el código con la cantidad de hilos por defecto que es
4, el cual varía de acuerdo al número de procesadores. En la Figura 1.3 se
modifica el número de hilos, mediante la variable de entorno “export
OMP_NUM_THREADS = 4”.
HOLA2.C

ENUNCIADO
Definición del número de threads mediante la función omp_set_num_threads()

SALIDA

EXPLICACIÓN

En este código se define el número de threads en la línea 26, pasando como


parámetro la variable entera nthr a la función omp_set_num_threads(nthr), cuyo
valor es definido en la línea 23, mediante la captura del valor por teclado. Para la
salida se ingresó “5”, como cantidad de threads.

HOLA3.C

ENUNCIADO
Los tres casos juntos (pej: export con 16, teclado con 8, funcion con 6 threads)
SALIDA
Explicación

Este ejemplo consta de 3 partes:


En la primera el número de hilos que van a ejecutarse está definido por la propia
arquitectura, es decir el número de procesadores de la máquina donde se ejecuta.
En la segunda el número de hilos está definido por el usuario que ingresa un dato.
En la tercera parte el número está definido en la cláusula num_threads ()
dentro del programa, cuyo valor en este caso es 6.

VAR1.C
ENUNCIADO
Ámbito de variables (ejemplo transparencias)

Salida

Explicación

El código en general maneja 4 variables, una compartida mediante la


cláusula shared (y), una compartida por defecto (tid) y dos (x,z) private o
firstprivate, Figura3 y Figura 4 respectivamente. La cláusula private permite a
las variables creadas para cada hilo que cuando ingresen a la región
paralela no estén inicializadas y al salir de la región paralela sean
destruídas, en cambio la cláusula firstprivate permite a las variables que al
ingresar a la región paralela mantengan sus valores declarados
anteriormente. Como se ve en la Figura en la impresión por consola
“ANTES → x= 2 y= 1 z=-1” la variables contiene los valores como se
declararon al inicio, pero cuando ya entra en la región paralela en la Figura 3
“DENTRO(1)→ x = 0 y = 1 z = 0” , los valores private se inicializan con ‘0’ y
en la Figura 4 “DENTRO(1)→ x = 2 y = 1 z = 0-1” , los valores firstprivate se
mantienen.
En los incisos (a) y (b) de las Figuras 3 y 4, en algunos casos el Hilo maestro
(0), recorre todas condicionales, pero en otros no, ya que su identificador tid
es compartido con todos los hilos, por ese motivo los resultados de los
incisos (a) y (b) de ambas figuras son diferentes.
VAR2.C
Enunciado
Hay que declarar correctamente las variables. Para completar
Salida

Explicación

La cláusula default(none) nos obliga a declarar explícitamente el ámbito de


todas las variables dentro de la región paralela. Incluyendo las variables
shared, de no ser especificada, el compilador reporta errores.

THREADP.C

ENUNCIADO
Ejemplo de uso de variables threadprivate
RP1: copyin(x) --> x toma el valor inicial del master; y/z sin inicializar (0)
RP2: x/y mantienen el valor de la region paralela anterior (threadprivate)
RP3: una rutina: x/z mantienen valor, pero z no es privada (var. global original)
tid si es privada porque se pasa como parametro.

SALIDA
Explicación

Este código consta de 3 regiones paralelas y utiliza 3 variables “x”, “y” y “z” de tipo
entero, donde las dos primeras son declaradas como threadprivate es decir su
valor no se va a perder cuando se terminen de ejecutar las regiones paralelas y la
tercera solo es declarada como private por lo cual su valor dependerá de la región
en la que se ejecute y se perderá al salir de ésta. Inicialmente a las 3 variables se
les asigna el valor de 5.
En la primera región paralela se imprimen los valores tanto de las variables como del hilo
que esta ejecutándose, en este caso para todos los hilos (diferentes del master, es decir el 0 )
el valor de x es 5 pues se ha utilizado la cláusula copyin en “x”, la cual copia el valor de “x”
declarado en el hilo master, mientras que “y” solo conserva su valor para el hilo master, para
todos los demás es 0, en el caso de “z” no se sabe que valor toma pues no ha sido
inicializada en el resultado observamos que toma el valor de 0. Luego se ejecuta una serie de
operaciones sobre las variables, luego de ejecutarlas cada hilo se encuentra con una barrera
la que obliga a los hilos a sincronizarse, es decir que para seguir con su ejecución deberán
esperar que todos lleguen también a la barrera. Luego de dicha sincronización continúan con
su ejecución donde se imprimen los nuevos valores de las variables.
En la segunda región tanto “x” como “y” conservan su valor proveniente de la región
anterior, esto debido a como han sido declaradas, mientras que ”z” no tiene valor alguno.
En la tercera región, sucede lo mismo que en la segunda, excepto que “z” si tiene un valor, el
cual es 5, pues se ha utilizado una rutina donde no se ha pasado al “z” como parámetro es
por esto que vuelve a su naturaleza de compartida y su valor es igual para todos los hilos.
Al salir de la 3era región existen 2 impresiones mas, la primera mediante la rutina
donde se pasa como parámetro un id de un hilo diferente a los existentes e imprime
todos sus valores, el resultado es que las variables toman los valores del hilo
master, y en la segunda, se imprime los valores hilo master.

REPAR.C

Enunciado

Reparto de interacciones de un bucle entre los procesos. Reparto consecutivo


del primer bucle y entrelazado del segundo.

Salida
Explicación

El código hace uso de dos arreglos. A[i] es usado para distribuir los hilos a
cada iteración de manera consecutiva y B[i] es usado para distribuir los hilos
a cada iteración de manera entrelazada, haciendo uso de la directiva for la
cual permite repartir las iteraciones de un bucle entre todos los hilos y la
cláusula schedule para indicar como deberán repartirse las iteraciones del
bucle.

SCHED.C

ENUNCIADO
Ejemplo para analizar la planificacion o scheduling. La planificacion se indica en una
variable de entorno (Runtime) ejemplo: export OMP_SCHEDULE="static,4"

Salida

Explicación

La salida corresponde a la cláusula schedule(static). Se observa que las


iteraciones totales (N = 40) se han repartido equitativamente entre la
cantidad de hilos (4). Es decir, cada hilo se ocupó de 5 iteraciones de la
siguiente manera: las iteraciones en el intervalo [0-4] fueron ejecutadas en el
hilo de tid = 0; [4-7] por el hilo de tid = 1; [8-11] por el tid = 2, así,
sucesivamente.
TAREA.C

Enunciado
Ejemplo para ver el efecto del reparto en el tiempo de ejecución
Ejecutar modificando el scheduling: static,static 4, dynamic

Salida

Explicación

Para el caso del static a cada hilo se reparte una carga N/P donde N es 4000 y P es 4,
es decir cada hilo tiene que calcular la suma de 1000 elementos, en static 4 ya se
define el tamaño de la carga que se va a repartir en este caso a cada hilo se le asigna
4 elementos a calcular, una vez termine de calcular prosigue con otros 4 elementos.
Y en el caso de dynamic como no se ha especificado un tamaño de carga ésta toma el
valor de 1 entonces cada hilo calcula la suma de 1 elemento, por ser de un solo
elemento el resultado se parece al secuencial pero con un tiempo de ejecución menor.
Respecto a los tiempos de ejecución como se podrá observar en la salida la
cual se ha compilado y ejecutado en el orden propuesto, el static tiene un
menor tiempo de ejecución en comparación con static 4 esto debido a que la
carga repartida es de mayor dimensión y también un poco mayor al de
dynamic a pesar que este último tiene un costo extra por repartir la carga en
tiempo de ejecución.
SEC.C

Enunciado

Ejemplo de seccion paralelo(Probar con 4 threads, con 3 (lo mismo) y con 2


(el doble de tiempo))

Salida

Explicación

El código muestra el uso de la directiva section, el hilo master distribuye las


secciones a los hilos disponibles incluyéndose de ser necesario, en el ultimo
caso, al ser sólo dos hilos en los que se debe repartir la secciones implica
que uno hará dos secciones, como cada sección ejecuta el mismo código el
tiempo de ejecución será el mismo para cada sección, considerando que en
el caso de ultimo será el doble por que debe terminar una sección para
ejecutar otra, cada hilo ejecuta independientemente una sección y el tiempo
de ejecución presenta una variación irrelevante.
ORF.C

Enunciado

Calculo de un producto escalar. Reparto de tares tipo orphan.

Salida

Explicación

Se observa que los operandos fueron dividos en cantidades iguales (2) para
la cantidad de hilos total (4). De este modo, el hilo de tid = 0, ejecutó la suma
de A[0]*B[0] y A[1]*B[1] . El hilo de tid = 1, ejecutó la suma de A[2]*B[2] y
A[3]*B[3] y así sucesivamente.

NESTED.C

Enunciado
Ejemplo de regiones paralelas anidadas.

Salida
Explicación

En la salida podemos observar 2 casos:


En el primer resultado se encuentra activo el paralelismo anidado es decir que
primero los 4 hilos ejecutaran su región externa y en la región interna se define 3
hilos mas los cuales van a ejecutar la región interna de cada uno de los 4 hilos
dando un total de 12 ejecuciones de la región interna.
En el segundo resultado no se encuentra activo el paralelismo anidado por lo que al
ejecutar la región interna solo se creara un hilo que ejecute la región interna de los
4 hilos principales.

HISTO.C

Enunciado
Paralelizar un programa que efectúa unas cuantas operaciones sobre una
matriz (una "imagen"):
1. Calcula el histograma de la imagen (datos iniciales: de 0 a NG).
2. Calcula el valor mínimo del histograma ("nivel de gris que menos veces aparece").
3. A partir de ahí, calcula:
B: vector que contiene la suma de los elementos de cada fila hasta (sin incluir)
encontrar el valor mínimo
C: vector que contiene la posición del mínimo en cada fila
SPM: suma de las posiciones del mínimo
En una primera versión usar una imagen de tamaño 10 × 10 y un valor de
NG de 10.

Salida
Explicación

Se paralelizaron 2 bucles. En el primer bucle se hizo uso de la directiva


#pragma omp critical, pues el “histo[IMA[i][j]] ++;” no debía ser accedido por
un hilo cuando otro estaba modificando su valor, en el tercer bucle se usó la
directiva for y la cláusula reduction para la variable spm

SINCRO1.C

Enunciado

Ejemplo para ver como sincronizar un bucle


B(i) = B(i) + 3
C(i) = B(i-1) * 5
Sincronización mediante un contador. MAL: se bloquea.

Salida

Explicación
FIBO_SER.C

Enunciado

Ejemplo de uso de la directiva task en un programa


recursivo para calcular el numero de fibonacci
f(n) = f(n-1) + f(n-2) con f(0)=1 y f(1)=1
version serie con usleep

Salida

Explicación

Calcula, en forma serial, e imprime el número de orden ingresado de la serie


fibonacci también imprime el tiempo que este ha tardado en obtener los resultados,
este tiempo será mucho mayor comparado con un código utilizando la directiva task
explicado en el siguiente ejercicio.
FIBO.C
Enunciado
Ejemplo de uso de la directiva task en un programa
recursivo para calcular el numero de fibonacci

SALIDA

Explicación
SCRI.C
Enunciado
Uso de una sección critica para planificación guided de un bucle. Se reparte
un cuarto de la parte proporcional. Se hacen N iteraciones en las que una de
ellas, N/4, es mucho más larga.

SALIDA

Explicación

También podría gustarte