Skip to content

Commit

Permalink
OMP: Ejercicio semana 4
Browse files Browse the repository at this point in the history
  • Loading branch information
jesusc committed Oct 14, 2020
1 parent d5cb01d commit 9ce237c
Show file tree
Hide file tree
Showing 4 changed files with 287 additions and 0 deletions.
15 changes: 15 additions & 0 deletions ejercicios/semana4-openmp/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
CC=gcc
CFLAGS=-g -ggdb -DPROFILE=3000 -Wall
GLIB_FLAGS=`pkg-config --cflags --libs glib-2.0`

all: tree tree_omp

tree: tree.c
$(CC) -o tree $^ -lm -fopenmp $(CFLAGS) $(GLIB_FLAGS)

tree_omp: tree_omp.c
$(CC) -o tree_omp $^ -lm -fopenmp $(CFLAGS) $(GLIB_FLAGS)

.PHONY: clean
clean:
rm -rf main *~ tree tree_omp
26 changes: 26 additions & 0 deletions ejercicios/semana4-openmp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

# Paralelización de construcción y recorrido de árboles

Paraleliza las funciones `generate_nodes` y `sum` del programa `tree_omp.c`.
Utiliza tareas de OpenMP para ello:

* Directiva #pragma omp task
* Utiliza el modificador if para limitar la cantidad de tareas que se generan.
* Directiva #pragma omp taskwait cuando sea necesario

El programa utiliza la librería GLib para la estructura de datos GNode
(árbol en memoria). La documentación está en https://developer.gnome.org/glib/2.26/glib-N-ary-Trees.html. Para instalar GLib hay que hacer:

```
sudo apt-get install libglib2.0-dev
```

Haz diversas pruebas variando la forma de utilizar tareas. Entrega el
código desarrollado y una explicación breve de lo realizado, en
particular discutiendo acerca del efecto de usar tareas para obtener
mejores (o peores) tiempos de ejecución. No es necesario en este
ejercicio realizar un informe detallado de las mejoras obtenidas.

Nota: El programa `tree.c` es una versión que utiliza números
aleatorios, pero no hay que paralelizarla.

122 changes: 122 additions & 0 deletions ejercicios/semana4-openmp/tree.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#include <stdio.h>
#include <stdlib.h>

#include <string.h>
#include <assert.h>
#include <glib.h>

#include <omp.h>

#define MAX_HEIGHT 4
#define MAX_CHILDREN 4
#define FOLDER_RATIO 4
// 1/4 are folders => More folders may take more time

#define DEBUG 0

typedef struct {
char *name;
long size;
gboolean is_dir;
} Item;

char * new_name(int height, int child) {
char str[2048];
if (DEBUG)
printf("%d %d\n", height, child);
sprintf(str, "Node %d %d", height, child);
return g_strdup(str);
}

Item * item_new(char *name, long size, gboolean is_dir)
{
Item *item = (Item *) malloc(sizeof(Item));
item->name = name;
item->size = size;
item->is_dir = is_dir;
return item;
}

void item_free(Item *item)
{
free(item->name);
free(item);
}

void generate_nodes(GNode *root, int height) {
// https://developer.gnome.org/glib/stable/glib-N-ary-Trees.html

// Generate up to 30 children
int children = rand() % MAX_CHILDREN + 2;
for(int j = 0; j < children; j++) {
int size = 0;
int is_dir = (rand() % FOLDER_RATIO) == 0; // Some are folders
if (!is_dir) {
size = rand() % 500 + 20;
}

GNode *node = g_node_new(item_new(new_name(height, j), size, is_dir));
g_node_append(root, node);

if (is_dir) {
// Decide whether to stop.
// Hard stop if the height is too much. If height is ok, we stop 1/4 of the times
if (height < MAX_HEIGHT && (rand() % 4) != 0) {
generate_nodes(node, height + 1);
}
}
}
}

long sum(GNode *root)
{
long total = 0;
int nchildren = g_node_n_children(root);
for(int i = 0; i < nchildren; i++) {
GNode *child = g_node_nth_child(root, i);
Item *item = child->data;
if (item->is_dir) {
total += sum(child);
} else {
total += item->size;
}
}
return total;
}


void free_nodes(GNode *root) {
item_free(root->data);
int nchildren = g_node_n_children(root);
for(int i = 0; i < nchildren; i++) {
GNode *child = g_node_nth_child(root, i);
free_nodes(child);
}
}

void destroy_tree(GNode *root)
{
free_nodes(root);
g_node_destroy(root);
}

int main(int argc, char **argv)
{

GNode *root = g_node_new(item_new(new_name(0, 0), 0, TRUE));

double start = omp_get_wtime();
generate_nodes(root, 1);
double end = omp_get_wtime();
printf("Generation time %f seconds\n", end - start);

start = omp_get_wtime();
long total = sum(root);
end = omp_get_wtime();
printf("Total = %ld\n", total);
printf("Traversal time %f seconds\n", end - start);

destroy_tree(root);

return 0;
}
124 changes: 124 additions & 0 deletions ejercicios/semana4-openmp/tree_omp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#include <stdio.h>
#include <stdlib.h>

#include <string.h>
#include <assert.h>
#include <glib.h>

#include <omp.h>

#define MAX_HEIGHT 15
#define MAX_CHILDREN 12
#define FOLDER_RATIO 4
// 1/4 are folders => More folders may take more time

#define DEBUG 0

typedef struct {
char *name;
long size;
gboolean is_dir;
} Item;

char * new_name(int height, int child) {
char str[2048];
if (DEBUG)
printf("%d %d\n", height, child);
sprintf(str, "Node %d %d", height, child);
return g_strdup(str);
}

Item * item_new(char *name, long size, gboolean is_dir)
{
Item *item = (Item *) malloc(sizeof(Item));
item->name = name;
item->size = size;
item->is_dir = is_dir;
return item;
}

void item_free(Item *item)
{
free(item->name);
free(item);
}

void generate_nodes(GNode *root, int height) {
// https://developer.gnome.org/glib/stable/glib-N-ary-Trees.html

// int children = rand() % MAX_CHILDREN + 2;
int children = MAX_CHILDREN;
for(int j = 0; j < children; j++) {
int size = 0;
int is_dir = j % FOLDER_RATIO == 0; //(rand() % FOLDER_RATIO) == 0; // Some are folders
if (!is_dir) {
//size = rand() % 500 + 20;
size = j + 10;
}

GNode *node = g_node_new(item_new(new_name(height, j), size, is_dir));
g_node_append(root, node);

if (is_dir) {
// Decide whether to stop.
// Hard stop if the height is too much. If height is ok, we stop 1/4 of the times
// if (height < MAX_HEIGHT && (rand() % 4) != 0) {
if (height < MAX_HEIGHT) {
generate_nodes(node, height + 1);
}
}
}
}

long sum(GNode *root, int height)
{
long total = 0;
int nchildren = g_node_n_children(root);
for(int i = 0; i < nchildren; i++) {
GNode *child = g_node_nth_child(root, i);
Item *item = child->data;
if (item->is_dir) {
total += sum(child, height + 1);
} else {
total += item->size;
}
}
return total;
}

void free_nodes(GNode *root) {
item_free(root->data);
int nchildren = g_node_n_children(root);
for(int i = 0; i < nchildren; i++) {
GNode *child = g_node_nth_child(root, i);
free_nodes(child);
}
}

void destroy_tree(GNode *root)
{
free_nodes(root);
g_node_destroy(root);
}

int main(int argc, char **argv)
{

GNode *root = g_node_new(item_new(new_name(0, 0), 0, TRUE));

double start = omp_get_wtime();
generate_nodes(root, 1);
double end = omp_get_wtime();
printf("Generation time %f seconds\n", end - start);

long total;
start = omp_get_wtime();
total = sum(root, 1);
end = omp_get_wtime();
printf("Total = %ld\n", total);
printf("Traversal time %f seconds\n", end - start);

destroy_tree(root);

return 0;
}

0 comments on commit 9ce237c

Please sign in to comment.