-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
287 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |