commit 21c8be42670407c165e6e485849e30cb3b69fbfe Author: Laureηt Date: Thu Jun 22 20:19:48 2023 +0200 init diff --git a/BE_OpenMP_2014/.vscode/settings.json b/BE_OpenMP_2014/.vscode/settings.json new file mode 100644 index 0000000..d7cc77f --- /dev/null +++ b/BE_OpenMP_2014/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "files.associations": { + "*.html": "html", + "*.toml": "toml", + "*.tcc": "c" + } +} \ No newline at end of file diff --git a/BE_OpenMP_2014/Makefile b/BE_OpenMP_2014/Makefile new file mode 100644 index 0000000..51e6793 --- /dev/null +++ b/BE_OpenMP_2014/Makefile @@ -0,0 +1,13 @@ +clean: + (cd derivative_free; make clean) + (cd linked_list; make clean) + (cd matrix_multiplication; make clean) + (cd reduction; make clean) + (cd synchronizations; make clean) + + + + + + + diff --git a/BE_OpenMP_2014/derivative_free/Makefile b/BE_OpenMP_2014/derivative_free/Makefile new file mode 100644 index 0000000..53dfbb6 --- /dev/null +++ b/BE_OpenMP_2014/derivative_free/Makefile @@ -0,0 +1,31 @@ +CC = gcc +LINK = $(CC) + +CFLAGS = -O3 -fopenmp -Wunknown-pragmas +# CFLAGS = -g -fopenmp +LDFLAGS = $(CFLAGS) +LIBS = -lm + +OBJS = aux.o main.o + +main: $(OBJS) + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + + + + + + +clean: + (rm -f *.o main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< + + + + diff --git a/BE_OpenMP_2014/derivative_free/aux.c b/BE_OpenMP_2014/derivative_free/aux.c new file mode 100644 index 0000000..2e80e15 --- /dev/null +++ b/BE_OpenMP_2014/derivative_free/aux.c @@ -0,0 +1,31 @@ +#include +#include +#include + + + +long usecs (){ + struct timeval t; + + gettimeofday(&t,NULL); + return t.tv_sec*1000000+t.tv_usec; +} + + +void mysleep(double sec){ + + long s, e; + s=0; e=0; + s = usecs(); + while(((double) e-s)/1000000 < sec) + { + e = usecs(); + } + return; +} + +double evaluate(double x, double y){ + /* mysleep(0.000001); */ + return 1.34*x*x+1.15*y*y+2 + x*y -y-2*x+0.33; +} + diff --git a/BE_OpenMP_2014/derivative_free/aux.h b/BE_OpenMP_2014/derivative_free/aux.h new file mode 100644 index 0000000..665b3b9 --- /dev/null +++ b/BE_OpenMP_2014/derivative_free/aux.h @@ -0,0 +1,3 @@ +long usecs (); +double evaluate(double x, double y); +void mysleep(double sec); diff --git a/BE_OpenMP_2014/derivative_free/main.c b/BE_OpenMP_2014/derivative_free/main.c new file mode 100644 index 0000000..fab5bfd --- /dev/null +++ b/BE_OpenMP_2014/derivative_free/main.c @@ -0,0 +1,168 @@ +#include +#include +#include +#include "aux.h" +#include "omp.h" +#define MAX_THREADS 16 +#define MAXIT 1000000 + +double sequential_minimization(double s, int p, double x0, double y0); +double parallel_minimization(double s, int p, double x0, double y0); + +int main(int argc, char **argv) +{ + long t_start, t_end; + double s, x0, y0, z; + int i, p; + + // Command line argument: array length + if (argc == 3) + { + p = atoi(argv[1]); /* the number of points to be evaluated */ + s = atof(argv[2]); /* the step length */ + } + else + { + printf("Usage:\n\n ./main p s\n\nwhere p is the number of points around the current minimum where the function has to be evaluated\nand s is the step size.\n"); + return 1; + } + + /* No need to change this seetings unless for debugging */ + x0 = 10; + y0 = 10; + + t_start = usecs(); + z = sequential_minimization(s, p, x0, y0); + t_end = usecs(); + printf("Sequential time : %8.2f msec.\n", ((double)t_end - t_start) / 1000.0); + + printf("\n\n"); + + t_start = usecs(); + z = parallel_minimization(s, p, x0, y0); + t_end = usecs(); + printf("Parallel time : %8.2f msec.\n", ((double)t_end - t_start) / 1000.0); + + return 0; +} + +double parallel_minimization(double s, int p, double x0, double y0) +{ + int i; + int cnt = 0; + double x, y, z; + double nx, ny, nz; + double min_nx, min_ny, min_nz; + double xyz[MAX_THREADS][3]; + int running = 1; + + min_nx = x0; + min_ny = y0; + min_nz = evaluate(min_nx, min_ny); + +#pragma omp parallel shared(cnt, xyz, running) + + xyz[omp_get_thread_num()][0] = x0; + xyz[omp_get_thread_num()][1] = y0; + xyz[omp_get_thread_num()][2] = evaluate(xyz[omp_get_thread_num()][0], xyz[omp_get_thread_num()][1]); + + while (cnt < MAXIT && running) + { + x = xyz[omp_get_thread_num()][0]; + y = xyz[omp_get_thread_num()][1]; + z = xyz[omp_get_thread_num()][2]; + /* Evaluate function on the 8 points around the current minimum */ + /* The current minimum is included again in the evaluation for + simplicipy; this makes a total of 9 evaluations */ +#pragma omp for + for (i = 0; i < p; i++) + { + nx = x + s * cos(2.0 * M_PI * i / ((double)p)); + ny = y + s * sin(2.0 * M_PI * i / ((double)p)); + nz = evaluate(nx, ny); + /* printf("%f %f %f\n",nx,ny,nz); */ + /* If the evaluation at this point is lower than the current + minimum, set this point as the new minimum */ + if (nz < xyz[omp_get_thread_num()][2]) + { + xyz[omp_get_thread_num()][0] = nx; + xyz[omp_get_thread_num()][1] = ny; + xyz[omp_get_thread_num()][2] = nz; + } + } + /* Uncomment the line below if you want to debug */ + /* printf("%4d -- %5.2f %5.2f %10.4f\n",cnt,xyz[0][0], xyz[0][1], xyz[0][2]); */ + +#pragma omp master + { + // increment counter + cnt++; + + // get result from threads + for (i = 0; i < MAX_THREADS; i++) + { + if (min_nz > xyz[i][2]) + { + min_nx = xyz[i][0]; + min_ny = xyz[i][1]; + min_nz = xyz[i][2]; + } + } + + /* If no improvement over the old minimum, terminate */ + if (xyz[omp_get_thread_num()][2] >= z) + { + running = 0; + } + } + } + + printf("Minimum found is %.10f at x=%.4f, y=%.4f in %d steps\n", min_nx, min_nz, min_ny, cnt); + return min_nz; +} + +double sequential_minimization(double s, int p, double x0, double y0) +{ + + int cnt, i; + double z, x, y, nx, ny, nz; + double xyz[MAX_THREADS][3]; + + xyz[0][0] = x0; + xyz[0][1] = y0; + xyz[0][2] = evaluate(xyz[0][0], xyz[0][1]); + + for (cnt = 0; cnt < MAXIT; cnt++) + { + x = xyz[0][0]; + y = xyz[0][1]; + z = xyz[0][2]; + /* Evaluate function on the 8 points around the current minimum */ + /* The current minimum is included again in the evaluation for + simplicipy; this makes a total of 9 evaluations */ + for (i = 0; i < p; i++) + { + nx = x + s * cos(2.0 * M_PI * i / ((double)p)); + ny = y + s * sin(2.0 * M_PI * i / ((double)p)); + nz = evaluate(nx, ny); + /* printf("%f %f %f\n",nx,ny,nz); */ + /* If the evaluation at this point is lower than the current + minimum, set this point as the new minimum */ + if (nz < xyz[0][2]) + { + xyz[0][2] = nz; + xyz[0][0] = nx; + xyz[0][1] = ny; + } + } + /* Uncomment the line below if you want to debug */ + /* printf("%4d -- %5.2f %5.2f %10.4f\n",cnt,xyz[0][0], xyz[0][1], xyz[0][2]); */ + + /* If no improvement over the old minimum, terminate */ + if (xyz[0][2] >= z) + break; + } + + printf("Minimum found is %.10f at x=%.4f, y=%.4f in %d steps\n", xyz[0][2], xyz[0][0], xyz[0][1], cnt); + return xyz[0][2]; +} diff --git a/BE_OpenMP_2014/derivative_free/subject.pdf b/BE_OpenMP_2014/derivative_free/subject.pdf new file mode 100644 index 0000000..6a0a691 Binary files /dev/null and b/BE_OpenMP_2014/derivative_free/subject.pdf differ diff --git a/BE_OpenMP_2014/environment.sh b/BE_OpenMP_2014/environment.sh new file mode 100644 index 0000000..c420007 --- /dev/null +++ b/BE_OpenMP_2014/environment.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +export LBLAS="/mnt/n7fs/ens/tp_abuttari/acml-4.4.0/gfortran64/lib/libacml.a -lgfortran -lm" +export PATH=/mnt/n7fs/ens/tp_abuttari/opt/gcc_trunk/bin/:$PATH; +export LD_LIBRARY_PATH=/mnt/n7fs/ens/tp_abuttari/opt/gmp-4.3.2/lib/:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH=/mnt/n7fs/ens/tp_abuttari/opt/mpfr-2.4.2/lib/:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH=/mnt/n7fs/ens/tp_abuttari/opt/mpc-0.8.1/lib/:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH=/mnt/n7fs/ens/tp_abuttari/opt/isl-0.12.2/lib/:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH=/mnt/n7fs/ens/tp_abuttari/opt/gcc_trunk/lib64/:$LD_LIBRARY_PATH diff --git a/BE_OpenMP_2014/linked_list/Makefile b/BE_OpenMP_2014/linked_list/Makefile new file mode 100644 index 0000000..53dfbb6 --- /dev/null +++ b/BE_OpenMP_2014/linked_list/Makefile @@ -0,0 +1,31 @@ +CC = gcc +LINK = $(CC) + +CFLAGS = -O3 -fopenmp -Wunknown-pragmas +# CFLAGS = -g -fopenmp +LDFLAGS = $(CFLAGS) +LIBS = -lm + +OBJS = aux.o main.o + +main: $(OBJS) + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + + + + + + +clean: + (rm -f *.o main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< + + + + diff --git a/BE_OpenMP_2014/linked_list/aux.c b/BE_OpenMP_2014/linked_list/aux.c new file mode 100644 index 0000000..e9c288e --- /dev/null +++ b/BE_OpenMP_2014/linked_list/aux.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include +#include "aux.h" + +unsigned long process_node(struct node *node){ + mysleep(0.00005); + return node->val+1; +} + + + +long usecs (){ + struct timeval t; + + gettimeofday(&t,NULL); + return t.tv_sec*1000000+t.tv_usec; +} + + +void mysleep(double sec){ + + long s, e; + s=0; e=0; + s = usecs(); + while(((double) e-s)/1000000 < sec) + { + e = usecs(); + } + return; +} + + + +void init_list(struct node **head){ + + struct node *curr; + int n, i; + + n = 10000; + + *head = (struct node*)malloc(sizeof(struct node)); + curr = *head; + + for(i=0; ival = i+1; + curr->next = (struct node*)malloc(sizeof(struct node)); + curr = curr->next; + } + curr->val=1; + curr->next = NULL; + + return; + +} diff --git a/BE_OpenMP_2014/linked_list/aux.h b/BE_OpenMP_2014/linked_list/aux.h new file mode 100644 index 0000000..506ffca --- /dev/null +++ b/BE_OpenMP_2014/linked_list/aux.h @@ -0,0 +1,11 @@ + +struct node{ + unsigned long val; + struct node *next; +}; + + +long usecs (); +unsigned long process_node(struct node *node); +void mysleep(double sec); +void init_list(struct node **head); diff --git a/BE_OpenMP_2014/linked_list/main.c b/BE_OpenMP_2014/linked_list/main.c new file mode 100644 index 0000000..2fbff53 --- /dev/null +++ b/BE_OpenMP_2014/linked_list/main.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include "aux.h" +#include "omp.h" +#define MAX_SIZE 10000 + +unsigned long sequential_sweep(struct node *head); +unsigned long parallel_for_sweep(struct node *head); +unsigned long parallel_task_sweep(struct node *head); + +int main(int argc, char **argv) +{ + int n, i, s; + long t_start, t_end, save; + int *x; + unsigned long acc, result; + struct node *head, *curr; + + init_list(&head); + + t_start = usecs(); + result = sequential_sweep(head); + t_end = usecs(); + printf("Sequential time : %8.2f msec.", ((double)t_end - t_start) / 1000.0); + printf(" -- result: %5ld\n", result); + + t_start = usecs(); + result = parallel_for_sweep(head); + t_end = usecs(); + printf("Parallel for time : %8.2f msec.", ((double)t_end - t_start) / 1000.0); + printf(" -- result: %5ld\n", result); + + t_start = usecs(); + result = parallel_task_sweep(head); + t_end = usecs(); + + printf("Parallel task time : %8.2f msec.", ((double)t_end - t_start) / 1000.0); + printf(" -- result: %5ld\n", result); + + return 0; +} + +unsigned long sequential_sweep(struct node *head) +{ + + unsigned long acc; + struct node *curr; + + curr = head; + acc = 0; + while (curr) + { + /* Loop until the last element in the list and accumulate the + result of nodes processing */ + acc += process_node(curr); + curr = curr->next; + } + + return acc; +} + +unsigned long parallel_for_sweep(struct node *head) +{ + unsigned int size = 0; + unsigned long acc = 0; + struct node *curr = head; + + struct node **pointers = malloc(sizeof(struct node *) * MAX_SIZE); // utiliser un std::vector en c++ + + // on trouve la longuer de la liste + while (curr) + { + pointers[size++] = curr; + curr = curr->next; + } + +#pragma omp parallel + { +#pragma omp for reduction(+ : acc) + for (int i = 0; i < size; i++) + { + acc += process_node(pointers[i]); + } + +#pragma omp master + { + free(pointers); + } + } + + return acc; +} + +unsigned long parallel_task_sweep(struct node *head) +{ + unsigned long acc; + struct node *curr; + +#pragma omp parallel + { + curr = head; + acc = 0; + +#pragma omp single + { + while (curr) + { +#pragma omp task firstprivate(curr) + { + acc += process_node(curr); + } + curr = curr->next; + } + } + } + + return acc; +} diff --git a/BE_OpenMP_2014/linked_list/subject.pdf b/BE_OpenMP_2014/linked_list/subject.pdf new file mode 100644 index 0000000..6461812 Binary files /dev/null and b/BE_OpenMP_2014/linked_list/subject.pdf differ diff --git a/BE_OpenMP_2014/matrix_multiplication/Makefile b/BE_OpenMP_2014/matrix_multiplication/Makefile new file mode 100644 index 0000000..9ec5430 --- /dev/null +++ b/BE_OpenMP_2014/matrix_multiplication/Makefile @@ -0,0 +1,27 @@ +CC = gcc +LINK = $(CC) + +CFLAGS = -O3 -fopenmp -Wunknown-pragmas +# CFLAGS = -g -fopenmp +LDFLAGS = $(CFLAGS) +LIBS = -lm $(LBLAS) + +OBJS = aux.o main.o + +main: $(OBJS) + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + + +clean: + (rm -f *.o main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< + + + + diff --git a/BE_OpenMP_2014/matrix_multiplication/aux.c b/BE_OpenMP_2014/matrix_multiplication/aux.c new file mode 100644 index 0000000..c16f54b --- /dev/null +++ b/BE_OpenMP_2014/matrix_multiplication/aux.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include +#include "aux.h" + +int ISEED[4] = {0, 0, 0, 1}; +int IONE = 1; +char NoTran = 'N'; +double DONE = 1.0, DMONE = -1.0; +double alpha = 1.0, beta = 1.0; + +void init_data(block ***a, block ***b, block ***c, block ***d, int n, int nb) +{ + + int i, j, k, nbnb; + + nbnb = nb * nb; + + *a = (block **)malloc(n * sizeof(block *)); + *b = (block **)malloc(n * sizeof(block *)); + *c = (block **)malloc(n * sizeof(block *)); + *d = (block **)malloc(n * sizeof(block *)); + + for (i = 0; i < n; i++) + { + (*a)[i] = (block *)malloc(n * sizeof(block)); + (*b)[i] = (block *)malloc(n * sizeof(block)); + (*c)[i] = (block *)malloc(n * sizeof(block)); + (*d)[i] = (block *)malloc(n * sizeof(block)); + for (j = 0; j < n; j++) + { + (*a)[i][j].b = (double *)malloc(nbnb * sizeof(double)); + (*b)[i][j].b = (double *)malloc(nbnb * sizeof(double)); + (*c)[i][j].b = (double *)malloc(nbnb * sizeof(double)); + (*d)[i][j].b = (double *)malloc(nbnb * sizeof(double)); + dlarnv_(&IONE, ISEED, &nbnb, (*a)[i][j].b); + dlarnv_(&IONE, ISEED, &nbnb, (*b)[i][j].b); + dlarnv_(&IONE, ISEED, &nbnb, (*c)[i][j].b); + /* for(k=0; k mx) + mx = abs((c[i][j].b)[k] - (d[i][j].b)[k]); + } + } + } + + printf("The maximum difference on coefficients is %e\n", mx); +} + +long usecs() +{ + struct timeval t; + + gettimeofday(&t, NULL); + return t.tv_sec * 1000000 + t.tv_usec; +} diff --git a/BE_OpenMP_2014/matrix_multiplication/aux.h b/BE_OpenMP_2014/matrix_multiplication/aux.h new file mode 100644 index 0000000..470da1a --- /dev/null +++ b/BE_OpenMP_2014/matrix_multiplication/aux.h @@ -0,0 +1,19 @@ +struct { + double *b; +} typedef block; + + +void init_data(block ***a, block ***b, block ***c, block ***d, int n, int nb); +long usecs (); +void block_mult(block a, block b, block c, int nb); +void compare_matrices(block **c, block **d, int n, int nb); + +void dgemm_ (char *TRANSA, char *TRANSB, + int *M, int *N, int *K, + double *ALPHA, + double *A, int *LDA, + double *B, int *LDB, + double *BETA, + double *C, int *LDC); + +void dlarnv_(int *idist, int *iseed, int *n, double *x); diff --git a/BE_OpenMP_2014/matrix_multiplication/main.c b/BE_OpenMP_2014/matrix_multiplication/main.c new file mode 100644 index 0000000..1e6a960 --- /dev/null +++ b/BE_OpenMP_2014/matrix_multiplication/main.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include +#include "aux.h" + +void sequential_product(block **a, block **b, block **c, int n, int nb); +void parallel_product(block **a, block **b, block **c, int n, int nb); + +int main(int argc, char **argv) +{ + int n, nb; + long t_start, t_end; + block **a, **b, **c, **d; + + // Command line argument: array length + if (argc == 2) + { + n = atoi(argv[1]); /* for a matrix of size nxn blocks */ + } + else + { + printf("Usage:\n\n ./main n\n\nwhere n is the number of blocks in rows and columns of the matrices.\n"); + return 1; + } + + /* Statically fixed to 100, no need to change this unless for debugging */ + nb = 100; + + init_data(&a, &b, &c, &d, n, nb); + + /* Sequential version */ + t_start = usecs(); + sequential_product(a, b, c, n, nb); + t_end = usecs(); + printf("Sequential time : %8.2f msec.\n", ((double)t_end - t_start) / 1000.0); + + /* Parallel with tasks */ + t_start = usecs(); + parallel_product(a, b, d, n, nb); + t_end = usecs(); + printf("Parallel time : %8.2f msec.\n", ((double)t_end - t_start) / 1000.0); + + /* Comprare the two resulting matrices */ + compare_matrices(c, d, n, nb); + return 0; +} + +void sequential_product(block **a, block **b, block **c, int n, int nb) +{ + int i, j, k; + + for (i = 0; i < n; i++) + for (j = 0; j < n; j++) + for (k = 0; k < n; k++) + { + block_mult(a[i][k], b[k][j], c[i][j], nb); + } +} + +void parallel_product(block **a, block **b, block **c, int n, int nb) +{ + int i, j, k; + +#pragma omp parallel private(i, j, k) +#pragma omp single + + for (i = 0; i < n; i++) + for (j = 0; j < n; j++) +#pragma omp task firstprivate(i, j) + for (k = 0; k < n; k++) + { + block_mult(a[i][k], b[k][j], c[i][j], nb); + } +} diff --git a/BE_OpenMP_2014/matrix_multiplication/subject.pdf b/BE_OpenMP_2014/matrix_multiplication/subject.pdf new file mode 100644 index 0000000..b812a70 Binary files /dev/null and b/BE_OpenMP_2014/matrix_multiplication/subject.pdf differ diff --git a/BE_OpenMP_2014/pack.sh b/BE_OpenMP_2014/pack.sh new file mode 100644 index 0000000..0f3306b --- /dev/null +++ b/BE_OpenMP_2014/pack.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +make clean; +mkdir $USER +cp -r responses.txt derivative_free linked_list matrix_multiplication reduction synchronizations $USER; +cd $USER; find . -name "*.pdf" | xargs rm; cd ..; +tar zcvf $USER.tgz $USER; +rm -rf $USER; +mv $USER.tgz /mnt/n7fs/ens/tp_abuttari/rendus_2014 +chmod 600 /mnt/n7fs/ens/tp_abuttari/rendus_2014/$USER.tgz diff --git a/BE_OpenMP_2014/reduction/Makefile b/BE_OpenMP_2014/reduction/Makefile new file mode 100644 index 0000000..53dfbb6 --- /dev/null +++ b/BE_OpenMP_2014/reduction/Makefile @@ -0,0 +1,31 @@ +CC = gcc +LINK = $(CC) + +CFLAGS = -O3 -fopenmp -Wunknown-pragmas +# CFLAGS = -g -fopenmp +LDFLAGS = $(CFLAGS) +LIBS = -lm + +OBJS = aux.o main.o + +main: $(OBJS) + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + + + + + + +clean: + (rm -f *.o main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< + + + + diff --git a/BE_OpenMP_2014/reduction/aux.c b/BE_OpenMP_2014/reduction/aux.c new file mode 100644 index 0000000..bb542ae --- /dev/null +++ b/BE_OpenMP_2014/reduction/aux.c @@ -0,0 +1,32 @@ +#include +#include + + + +long usecs (){ + struct timeval t; + + gettimeofday(&t,NULL); + return t.tv_sec*1000000+t.tv_usec; +} + + +void mysleep(double sec){ + + long s, e; + s=0; e=0; + s = usecs(); + while(((double) e-s)/1000000 < sec) + { + e = usecs(); + } + return; +} + + +void operator(int *a, int *b){ + mysleep(0.01); + *a += *b; + +} + diff --git a/BE_OpenMP_2014/reduction/aux.h b/BE_OpenMP_2014/reduction/aux.h new file mode 100644 index 0000000..fa7e775 --- /dev/null +++ b/BE_OpenMP_2014/reduction/aux.h @@ -0,0 +1,3 @@ +long usecs (); +void operator(int *a, int *b); +void mysleep(double sec); diff --git a/BE_OpenMP_2014/reduction/main.c b/BE_OpenMP_2014/reduction/main.c new file mode 100644 index 0000000..e65aa75 --- /dev/null +++ b/BE_OpenMP_2014/reduction/main.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include "omp.h" +#include "aux.h" + +int sequential_reduction(int *x, int n); +int parallel_reduction(int *x, int n); + +int main(int argc, char **argv) +{ + int n, i, result; + long t_start, t_end; + int *x; + + // Command line argument: array length + if (argc == 2) + { + n = atoi(argv[1]); /* the length of the pref */ + } + else + { + printf("Usage:\n\n ./main n\n\nwhere n is the length of the array to be used.\n"); + return 1; + } + + x = (int *)malloc(sizeof(int) * n); + + /* Fill the array with random numbers */ + srand(1); + for (i = 0; i < n; i++) + x[i] = rand() % n; + + /* Sequential reduction */ + t_start = usecs(); + result = sequential_reduction(x, n); + t_end = usecs(); + printf("Sequential time : %8.2f msec. --- Result: %d\n", ((double)t_end - t_start) / 1000.0, result); + + /* Fill the array with random numbers */ + srand(1); + for (i = 0; i < n; i++) + x[i] = rand() % n; + + /* Parallel reduction */ + t_start = usecs(); + result = parallel_reduction(x, n); + t_end = usecs(); + printf("Parallel time : %8.2f msec. --- Result: %d\n", ((double)t_end - t_start) / 1000.0, result); + + return 0; +} + +int sequential_reduction(int *x, int n) +{ + int i; + + for (i = 1; i < n; i++) + operator(x, x + i); + + return x[0]; +} + +int parallel_reduction(int *x, int n) +{ + int i; + int red = 0; + +#pragma omp parallel + +#pragma omp for reduction(+ : red) + for (i = 0; i < n; i++) + { + operator(&red, x + i); + } + + return red; +} diff --git a/BE_OpenMP_2014/reduction/subject.pdf b/BE_OpenMP_2014/reduction/subject.pdf new file mode 100644 index 0000000..1050e9d Binary files /dev/null and b/BE_OpenMP_2014/reduction/subject.pdf differ diff --git a/BE_OpenMP_2014/responses.txt b/BE_OpenMP_2014/responses.txt new file mode 100644 index 0000000..d0f238c --- /dev/null +++ b/BE_OpenMP_2014/responses.txt @@ -0,0 +1,43 @@ +In this file you have to write the answers to the questions marked +with the "pencil" symbol that you will find in the subjects of the +various exam parts. + + +=============================================================================== +Part 1: Derivative-free minimization + + + + + + +=============================================================================== +Part 2: Linked list + + + + + + + + + +=============================================================================== +Part 3: Matrix Multiplication + + + + + + +=============================================================================== +Part 4: Reduction + + + + + + + +======================================================================= +Part 5: Synchronizations diff --git a/BE_OpenMP_2014/subject.pdf b/BE_OpenMP_2014/subject.pdf new file mode 100644 index 0000000..0404376 Binary files /dev/null and b/BE_OpenMP_2014/subject.pdf differ diff --git a/BE_OpenMP_2014/synchronizations/Makefile b/BE_OpenMP_2014/synchronizations/Makefile new file mode 100644 index 0000000..53dfbb6 --- /dev/null +++ b/BE_OpenMP_2014/synchronizations/Makefile @@ -0,0 +1,31 @@ +CC = gcc +LINK = $(CC) + +CFLAGS = -O3 -fopenmp -Wunknown-pragmas +# CFLAGS = -g -fopenmp +LDFLAGS = $(CFLAGS) +LIBS = -lm + +OBJS = aux.o main.o + +main: $(OBJS) + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + + + + + + +clean: + (rm -f *.o main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< + + + + diff --git a/BE_OpenMP_2014/synchronizations/aux.c b/BE_OpenMP_2014/synchronizations/aux.c new file mode 100644 index 0000000..f9f32fc --- /dev/null +++ b/BE_OpenMP_2014/synchronizations/aux.c @@ -0,0 +1,31 @@ +#include +#include + + +long usecs (){ + struct timeval t; + + gettimeofday(&t,NULL); + return t.tv_sec*1000000+t.tv_usec; +} + + +void mysleep(double sec){ + + long s, e; + s=0; e=0; + s = usecs(); + while(((double) e-s)/1000000 < sec) + { + e = usecs(); + } + return; +} + + + +int func(){ + mysleep(0.0000001); + return 1; +} + diff --git a/BE_OpenMP_2014/synchronizations/aux.h b/BE_OpenMP_2014/synchronizations/aux.h new file mode 100644 index 0000000..248349a --- /dev/null +++ b/BE_OpenMP_2014/synchronizations/aux.h @@ -0,0 +1,4 @@ +long usecs (); +int func(); +void mysleep(double sec); + diff --git a/BE_OpenMP_2014/synchronizations/main.c b/BE_OpenMP_2014/synchronizations/main.c new file mode 100644 index 0000000..fe8175d --- /dev/null +++ b/BE_OpenMP_2014/synchronizations/main.c @@ -0,0 +1,156 @@ +#include +#include +#include +#include "omp.h" +#include "aux.h" +#define NIT 1000000 +#define NE 10000 + +void sequential(int *data); +void parallel_critical(int *data); +void parallel_atomic(int *data); +void parallel_locks(int *data); + +int main(int argc, char **argv) +{ + int n, i, j, k, nth, thn, cnt; + long t_start, t_end, save; + double s, z, x, y, nx, ny, nz, mz; + int data[NE]; + + /* Initialize data */ + for (i = 0; i < NE; i++) + data[i] = 0; + + t_start = usecs(); + sequential(data); + t_end = usecs(); + + for (cnt = 0, i = 0; i < NE; i++) + { + cnt += data[i]; + } + printf("Sequential time : %8.2f msec.", ((double)t_end - t_start) / 1000.0); + printf(" -- result: %4d\n", cnt); + + /***********************************************************************/ + /***********************************************************************/ + /***********************************************************************/ + + for (i = 0; i < NE; i++) + data[i] = 0; + + t_start = usecs(); + parallel_critical(data); + t_end = usecs(); + + for (cnt = 0, i = 0; i < NE; i++) + { + cnt += data[i]; + } + printf("Critical time : %8.2f msec.", ((double)t_end - t_start) / 1000.0); + printf(" -- result: %4d\n", cnt); + + /***********************************************************************/ + /***********************************************************************/ + /***********************************************************************/ + + for (i = 0; i < NE; i++) + data[i] = 0; + + t_start = usecs(); + parallel_atomic(data); + t_end = usecs(); + + for (cnt = 0, i = 0; i < NE; i++) + { + cnt += data[i]; + } + printf("Atomic time : %8.2f msec.", ((double)t_end - t_start) / 1000.0); + printf(" -- result: %4d\n", cnt); + + /***********************************************************************/ + /***********************************************************************/ + /***********************************************************************/ + + for (i = 0; i < NE; i++) + { + data[i] = 0; + } + + t_start = usecs(); + parallel_locks(data); + t_end = usecs(); + + for (cnt = 0, i = 0; i < NE; i++) + { + cnt += data[i]; + } + printf("Locks time : %8.2f msec.", ((double)t_end - t_start) / 1000.0); + printf(" -- result: %4d\n", cnt); + + return 0; +} + +void sequential(int *data) +{ + int i, j; + + for (i = 0; i < NIT; i++) + { + j = rand() % NE; + data[j] += func(); + } +} + +void parallel_critical(int *data) +{ + int i, j; + +#pragma omp parallel + +#pragma omp for + for (i = 0; i < NIT; i++) + { + j = rand() % NE; +#pragma omp critical + data[j] += func(); + } +} + +void parallel_atomic(int *data) +{ + int i, j; + +#pragma omp parallel + +#pragma omp for + for (i = 0; i < NIT; i++) + { + j = rand() % NE; +#pragma omp atomic update + data[j] += func(); + } +} + +void parallel_locks(int *data) +{ + int i, j; + omp_lock_t *lock = malloc(sizeof(omp_lock_t)); + + omp_init_lock(lock); + +#pragma omp parallel shared(lock) + +#pragma omp for + for (i = 0; i < NIT; i++) + { + j = rand() % NE; + omp_set_lock(lock); + data[j] += func(); + omp_unset_lock(lock); + } + +#pragma omp single + free(lock); +} diff --git a/BE_OpenMP_2014/synchronizations/subject.pdf b/BE_OpenMP_2014/synchronizations/subject.pdf new file mode 100644 index 0000000..08bb4a5 Binary files /dev/null and b/BE_OpenMP_2014/synchronizations/subject.pdf differ diff --git a/BE_OpenMP_2019/BE_OpenMP_2019.zip b/BE_OpenMP_2019/BE_OpenMP_2019.zip new file mode 100644 index 0000000..679bf40 Binary files /dev/null and b/BE_OpenMP_2019/BE_OpenMP_2019.zip differ diff --git a/BE_OpenMP_2019/Makefile b/BE_OpenMP_2019/Makefile new file mode 100644 index 0000000..6918907 --- /dev/null +++ b/BE_OpenMP_2019/Makefile @@ -0,0 +1,13 @@ +clean: + (cd band_matrix; make clean) + (cd lu_tasks; make clean) + (cd norm2_noowr; make clean) + (cd stacks; make clean) + (cd tree_branch; make clean) + + + + + + + diff --git a/BE_OpenMP_2019/band_matrix/Makefile b/BE_OpenMP_2019/band_matrix/Makefile new file mode 100644 index 0000000..7f37361 --- /dev/null +++ b/BE_OpenMP_2019/band_matrix/Makefile @@ -0,0 +1,23 @@ +CC = gcc +LINK = $(CC) + +CFLAGS = -O3 -fopenmp -Wunknown-pragmas +# CFLAGS = -g -fopenmp +LDFLAGS = $(CFLAGS) +LIBS = -lm + +OBJS = aux.o main.o + +main: $(OBJS) + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + + +clean: + (rm -f *.o main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< diff --git a/BE_OpenMP_2019/band_matrix/aux.c b/BE_OpenMP_2019/band_matrix/aux.c new file mode 100644 index 0000000..173b5ab --- /dev/null +++ b/BE_OpenMP_2019/band_matrix/aux.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include +#include "aux.h" + +int ISEED[4] = {0,0,0,1}; +int IONE=1; +char NoTran = 'N'; +double DONE=1.0, DMONE=-1.0; +double alpha=1.0, beta=1.0; + +void init_data(double **A, double **Ac, double *x, int n, int b){ + + int i, j, k, nbnb; + + + for(i=0; i=n) { + Ac[i-j+b][j] = 0.0; + } else { + Ac[i-j+b][j] = A[i][j]; + } + } + } + + /* for(i=0; imx) + mx = abs(y1[i]); + if(abs(y1[i]-y2[i])>mxdif) + mxdif = abs(y1[i]-y2[i]); + } + + if(mxdif/mx>1e-10){ + printf("!!! Result is wrong !!!\n"); + } else { + printf("Result is correct\n"); + } + + return; + + +} + + + +long usecs (){ + struct timeval t; + + gettimeofday(&t,NULL); + return t.tv_sec*1000000+t.tv_usec; +} diff --git a/BE_OpenMP_2019/band_matrix/aux.h b/BE_OpenMP_2019/band_matrix/aux.h new file mode 100644 index 0000000..3c77ac0 --- /dev/null +++ b/BE_OpenMP_2019/band_matrix/aux.h @@ -0,0 +1,17 @@ +void init_data(double **A, double **Ac, double *x, int n, int b); +long usecs (); + +void dgemm_ (char *TRANSA, char *TRANSB, + int *M, int *N, int *K, + double *ALPHA, + double *A, int *LDA, + double *B, int *LDB, + double *BETA, + double *C, int *LDC); + +void dlarnv_(int *idist, int *iseed, int *n, double *x); + +void matmul_compact_row(double **A, double *x, double *y, int n, int b); +void matmul_compact_diag(double **A, double *x, double *y, int n, int b); +void matmul(double **A, double *x, double *y, int n); +void check_result(double *y1, double *y2, int n); diff --git a/BE_OpenMP_2019/band_matrix/main.c b/BE_OpenMP_2019/band_matrix/main.c new file mode 100644 index 0000000..f4d12fc --- /dev/null +++ b/BE_OpenMP_2019/band_matrix/main.c @@ -0,0 +1,142 @@ +#include +#include +#include +#include +#include +#include "omp.h" +#include "aux.h" + +int main(int argc, char **argv) +{ + int n, b, i; + long t_start, t_end; + double **A, **Ac, *x, *y1, *y2, *y3; + double diff; + + // Command line argument: array length + if (argc == 3) + { + n = atoi(argv[1]); /* the matrix size */ + b = atoi(argv[2]); /* the band width */ + } + else + { + printf("Usage:\n\n ./main n b\n\nwhere n is the number of blocks in rows and\n"); + printf("columns of the matrix and b the band width.\n"); + return 1; + } + + printf("\n"); + + A = (double **)malloc(n * sizeof(double *)); + Ac = (double **)malloc((2 * b + 1) * sizeof(double *)); + x = (double *)malloc(n * sizeof(double)); + y1 = (double *)malloc(n * sizeof(double)); + y2 = (double *)malloc(n * sizeof(double)); + y3 = (double *)malloc(n * sizeof(double)); + + for (i = 0; i < n; i++) + { + A[i] = (double *)malloc(n * sizeof(double)); + } + + for (i = 0; i < 2 * b + 1; i++) + { + Ac[i] = (double *)malloc(n * sizeof(double)); + } + + init_data(A, Ac, x, n, b); + + /* Sequential version */ + t_start = usecs(); + matmul(A, x, y1, n); + t_end = usecs(); + printf("Full matrix. Time : %8.2f msec.\n", ((double)t_end - t_start) / 1000.0); + + /* Parallel with tasks */ + t_start = usecs(); + matmul_compact_row(Ac, x, y2, n, b); + t_end = usecs(); + printf("Compact by rows. Time : %8.2f msec. ", ((double)t_end - t_start) / 1000.0); + /* Comprare the two resulting vectors */ + check_result(y1, y2, n); + + /* Parallel with tasks */ + t_start = usecs(); + matmul_compact_diag(Ac, x, y3, n, b); + t_end = usecs(); + printf("Compact by diagonals. Time : %8.2f msec. ", ((double)t_end - t_start) / 1000.0); + check_result(y1, y3, n); + + return 0; +} + +void matmul(double **A, double *x, double *y, int n) +{ + int i, j; + + for (i = 0; i < n; i++) + { + y[i] = 0; + for (j = 0; j < n; j++) + { + y[i] += A[i][j] * x[j]; + } + } + + return; +} + +void matmul_compact_row(double **Ac, double *x, double *y, int n, int b) +{ + int i, j; + +#pragma omp parallel private(i, j) + +#pragma omp single + for (i = 0; i < n; i++) + { + y[i] = 0; + } + + for (j = 0; j < n; j++) + { +#pragma omp for + for (i = j - b; i < j + b + 1; i++) + { + if (i >= 0 || i < n) + { + y[i] += Ac[i - j + b][j] * x[j]; + } + } + } + + return; +} + +void matmul_compact_diag(double **Ac, double *x, double *y, int n, int b) +{ + int i, j; + +#pragma omp parallel private(i, j) + +#pragma omp single + for (i = 0; i < n; i++) + { + y[i] = 0; + } + + for (i = 0; i < 2 * b + 1; i++) + { +#pragma omp for + for (j = 0; j < n; j++) + { + if ((j - b + i) >= 0 && (j - b + i) < n) + { + y[j - b + i] += Ac[i][j] * x[j]; + } + } + } + + return; +} diff --git a/BE_OpenMP_2019/band_matrix/subject.pdf b/BE_OpenMP_2019/band_matrix/subject.pdf new file mode 100644 index 0000000..9cc61f3 Binary files /dev/null and b/BE_OpenMP_2019/band_matrix/subject.pdf differ diff --git a/BE_OpenMP_2019/lu_tasks/Makefile b/BE_OpenMP_2019/lu_tasks/Makefile new file mode 100644 index 0000000..b1c40c7 --- /dev/null +++ b/BE_OpenMP_2019/lu_tasks/Makefile @@ -0,0 +1,30 @@ +CC = gcc +FC = gfortran +LINK = $(FC) + +FCFLAGS = -O3 -fopenmp +CFLAGS = -O3 -fopenmp -Wunknown-pragmas +LDFLAGS = $(FCFLAGS) +LBLAS = /mnt/n7fs/ens/tp_abuttari/acml-4.4.0/gfortran64/lib/libacml.a -lm + +OBJS = aux.o auxf.o lu_seq.o lu_par_tasks.o kernels.o main.o trace.o + +main: clean $(OBJS) + $(LINK) $(LDFLAGS) -o $@ $(OBJS) $(LBLAS) + +main_dbg: + ($(MAKE) clean main CDEFS=-DDBG) + +clean: + (rm -f *.o *.svg main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< + + + + diff --git a/BE_OpenMP_2019/lu_tasks/_aux.c b/BE_OpenMP_2019/lu_tasks/_aux.c new file mode 100644 index 0000000..52499c7 --- /dev/null +++ b/BE_OpenMP_2019/lu_tasks/_aux.c @@ -0,0 +1,10 @@ +#include +#include +#include + +long usecs (){ + struct timeval t; + + gettimeofday(&t,NULL); + return t.tv_sec*1000000+t.tv_usec; +} diff --git a/BE_OpenMP_2019/lu_tasks/auxf.f90 b/BE_OpenMP_2019/lu_tasks/auxf.f90 new file mode 100644 index 0000000..f8abd99 --- /dev/null +++ b/BE_OpenMP_2019/lu_tasks/auxf.f90 @@ -0,0 +1,28 @@ +function dnrm2_c(n, x, incx) bind(c) + use iso_c_binding + + integer(c_int), value :: n, incx + real(c_double) :: x(n), dnrm2_c + + real(kind(1.d0)) :: dnrm2 + + dnrm2_c = dnrm2(n, x(1), incx) + + return + +end function dnrm2_c + + +function dnrmf_c(m, n, a, lda) bind(c) + + use iso_c_binding + + integer(c_int), value :: m, n, lda + real(c_double) :: a(lda,n), dnrmf_c + + real(kind(1.d0)) :: dlange, w + + + dnrmf_c = dlange('F', m, n, a(1,1), lda, w) + +end function dnrmf_c diff --git a/BE_OpenMP_2019/lu_tasks/common.h b/BE_OpenMP_2019/lu_tasks/common.h new file mode 100644 index 0000000..dad4e23 --- /dev/null +++ b/BE_OpenMP_2019/lu_tasks/common.h @@ -0,0 +1,41 @@ +typedef struct infostruct{ + int B; // The size of block-columns + int NB; // The number of block-columns in a matrix + int N; // The total size of the matrix N=B*NB + int *ipiv; // Permutation vector for numerical pivoting +} info_type; + + +typedef double** Matrix; + +/* typedef struct matstruct{ */ + /* double **BC; // Permutation vector for numerical pivoting */ +/* } Matrix; */ + + +typedef enum {PNL = 0, UPD, END, NONE} Type; + +void dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv, int *info); +void dtrsm_(char *side, char *uplo, char *transa, char *diag, + int *m, int *n, const double *alpha, const double *A, int *lda, + double *B, int *ldb); +void dlaswp_(int *n, double * a, int *lda, int *k1, int *k2, int *ipiv, int *incx); +void dlarnv_(int *idist, int *iseed, int *n, double *x); +void dgetrs_(char *t, int *n, int *nrhs, double *A, int *lda, int *ipiv, double *x, int *incx, int *info); +void dgemv_(char *t, int *m, int *n, const double *alpha, const double *A, int *lda, const double *x, int *incx, const double *beta, double *y, int *incy); +double dnrm2_c(int n, double *x, int incx); +double dnrmf_c(int m, int n, double *A, int lda); + +void dgemm_(char *ta, char *tb, int *m, int *n, int *k, const double *alpha, const double *A, int *lda, const double *B, int *ldB, const double *beta, const double *c, int *ldc); + +void panel(double *P, int k, info_type info ); +void update(double *P, double *U, int k, int j, info_type info); +void backperm(Matrix A, info_type info); +void checkres(double *A, double *Acpy, info_type info); + +long usecs (); + + +void lu_seq (Matrix A, info_type info); +void lu_par_tasks(Matrix A, info_type info); + diff --git a/BE_OpenMP_2019/lu_tasks/kernels.c b/BE_OpenMP_2019/lu_tasks/kernels.c new file mode 100644 index 0000000..0f1d9ce --- /dev/null +++ b/BE_OpenMP_2019/lu_tasks/kernels.c @@ -0,0 +1,114 @@ +#include "trace.h" +#include "common.h" +#include +#include +#include + +void panel(double *P, int k, info_type info){ + + int m, ld, err, np, i; + + i = k*info.B; + np = info.B; + m = info.N-i; + ld = info.N; +#if defined(DBG) + printf("%2d -- panel : %d\n",omp_get_thread_num(),k); +#endif + trace_event_start(PNL); + dgetrf_(&m, &np, P+i, &ld, info.ipiv+i, &err); + trace_event_stop(PNL); +} + + +void update(double *P, double *U, int k, int j, info_type info){ + + int m, mu, nu, np, ld, err, i; + char NoTran = 'N', Lower='L', Unit='U', Left='L'; + int IONE=1, IMONE=-1, IZERO=0; + double DONE=(double)1.0, DMONE=-1.0, DZERO=0.0; + + i = k*info.B; + np = info.B; + nu = info.B; + + m = info.N-i; + mu = m-np; + ld = info.N; + +#if defined(DBG) + printf("%2d -- update: %d %d\n",omp_get_thread_num(),k,j); +#endif + trace_event_start(UPD); + dlaswp_(&nu, U+i, &ld, &IONE, &np, info.ipiv+i, &IONE); + dtrsm_ (&Left, &Lower, &NoTran, &Unit, + &np, &nu, + &DONE, + P+i, &ld, + U+i, &ld); + dgemm_ (&NoTran, &NoTran, + &mu, &nu, &np, + &DMONE, + P+i+np, &ld, + U+i, &ld, + &DONE, + U+i+np, &ld); + trace_event_stop(UPD); + + return; +} + + +void backperm(Matrix A, info_type info){ + + int i, j, ld, ipb, ipo; + int IONE=1; + + ld = info.N; + + trace_event_start(END); + for(i=info.B; i + +/* This is a sequential routine for the LU factorization of a square + matrix in block-columns */ +void lu_par_tasks(Matrix A, info_type info) +{ + + int i, j; + + trace_init(); +#pragma omp parallel + { +#pragma single + { + //Un seul processus génère toutes les tâchs pour tout le monde + for (i = 0; i < info.NB; i++) + { + /* Do the panel */ +#pragma omp task depend(inout \ + : A[i]) firstprivate(i) + //firstprivate pour initialiser à la valeur qu'on veut. + panel(A[i], i, info); + + for (j = i + 1; j < info.NB; j++) + { +/* Do all the correspondint updates */ +#pragma omp task depend(in \ + : A[i]) depend(inout \ + : A[j]) firstprivate(i, j) + update(A[i], A[j], i, j, info); + } + } + } + } + /* Do row permutations resulting from the numerical pivoting */ + /* This operation can be ignored and should be left out of the parallel region */ + backperm(A, info); + + trace_dump("trace_par_tasks.svg"); + + return; +} diff --git a/BE_OpenMP_2019/lu_tasks/lu_seq.c b/BE_OpenMP_2019/lu_tasks/lu_seq.c new file mode 100644 index 0000000..34891cc --- /dev/null +++ b/BE_OpenMP_2019/lu_tasks/lu_seq.c @@ -0,0 +1,31 @@ +#include "trace.h" +#include "common.h" + +/* This is a sequential routine for the LU factorization of a square + matrix in block-columns */ +void lu_seq(Matrix A, info_type info){ + + + int i, j; + + trace_init(); + + for(i=0; i +#include +#include +#include +#include +#include "common.h" + + + + +int main(int argc, char **argv){ + + int N, NB, B, NN; + double flops, nrm2, nrmf; + double *Acpy1, *Acpy2, *x, *b; + Matrix A; + info_type info; + long t_start,t_end; + int err, nth, i, j; + int ISEED[4] = {0,0,0,1}; + int IONE=1; + char NoTran = 'N', *nt; + double DONE=1.0, DMONE=-1.0; + + + if(argc != 3){ + printf("Usage:\n\n./main B NB\n\nwhere B is the size of block-columns and \n\ +NB is the number of block-columns the matrix is made of.\n"); + return 1; + } + + + B = atoi(argv[1]); /* block size */ + NB = atoi(argv[2]); /* dimension in blocks */ + N = B*NB; + NN = N*N; + + nt = getenv("OMP_NUM_THREADS"); + + flops = ((double)2.0*(double) N)*((double) N)*((double) N)/3.0; + + Acpy1 = (double *)malloc(NN*sizeof(double)); + Acpy2 = (double *)malloc(NN*sizeof(double)); + info.ipiv = (int *)malloc(N*sizeof(int)); + + dlarnv_(&IONE, ISEED, &NN, Acpy1); + + info.B = B; + info.NB = NB; + info.N = N; + + printf("Matrix size: %d\n",N); + + A = (double **)malloc(info.NB*sizeof(double*)); + /* get pointers to block-columns */ + for (j=0; j + + +Event events[MAXTHREADS][MAXEVENTS]; +int nevents[MAXTHREADS]; + + +void trace_init(){ + int i; + +#pragma omp master + { + /* strcpy(colors[0], "#d38d5f"); */ + /* strcpy(colors[1], "#ffdd55"); */ + /* strcpy(colors[2], "#8dd35f"); */ + /* strcpy(colors[3], "#80b3ff"); */ + /* strcpy(colors[4], "#e580ff"); */ + + for(i=0; i 0) nth=i+1; + + /* scale_x = 1000.0; */ + /* scale_y = ((double)(nth+1)) *30000 / ((double)(t_stop-t_zero)); */ + + scale_x = ((double)(t_stop-t_zero))/1000.0; + scale_y = 0.1; + + + + pFile = fopen (fname,"w"); + fprintf(pFile,"\n", + ((double)t_stop-t_zero)*1.06/scale_x, ((double)nth+1)*1.05/scale_y+8); + + for(t=0; t\n", + (double)(ev.t_start-t_zero)/scale_x, + ((double)t)/scale_y, + ((double)(ev.t_stop-ev.t_start))/scale_x, + ((double)1.0)/scale_y, + colors[ev.type]); + } + + } + + + + fprintf(pFile, "\n", + ((double)nth+1)*1.01/scale_y, + ((double)t_stop-t_zero)*1.02/scale_x, + ((double)nth+1)*1.01/scale_y); + + for(t=0; tThread %d\n", + ((double)t_stop-t_zero)*1.01/scale_x, ((double)t+0.8)/scale_y, t); + } + + fprintf(pFile,"Time (usec.)\n",((double)nth+1)*1.05/scale_y+7); + + for(x=((double)t_stop-t_zero)/scale_x/10.0; x<=((double)t_stop-t_zero)/scale_x; x+=((double)t_stop-t_zero)/scale_x/10.0){ + fprintf(pFile, "\n", + x,((double)nth+1)*1.01/scale_y-1, x, ((double)nth+1)*1.01/scale_y+1); + fprintf(pFile," %.0f \n", + x,((double)nth+1)*1.01/scale_y+7,x*scale_x); + } + + + fprintf(pFile,"\n"); + } +} diff --git a/BE_OpenMP_2019/lu_tasks/trace.h b/BE_OpenMP_2019/lu_tasks/trace.h new file mode 100644 index 0000000..83a75aa --- /dev/null +++ b/BE_OpenMP_2019/lu_tasks/trace.h @@ -0,0 +1,22 @@ +#include +#include + +long t_zero; + +#define MAXEVENTS 10000 +#define MAXTHREADS 48 + +long usecs (); + + +typedef struct event_struct{ + int type; + long t_start, t_stop; +} Event; + + +void trace_init(); +void trace_event_start(int type); +void trace_event_stop(int type); +void trace_dump(char *); + diff --git a/BE_OpenMP_2019/norm2_noowr/Makefile b/BE_OpenMP_2019/norm2_noowr/Makefile new file mode 100644 index 0000000..4ae3d4a --- /dev/null +++ b/BE_OpenMP_2019/norm2_noowr/Makefile @@ -0,0 +1,31 @@ +CC = gcc +LINK = $(CC) + +CFLAGS = -O3 -fopenmp +# CFLAGS = -g -fopenmp +LDFLAGS = $(CFLAGS) +LIBS = -lm + +OBJS = main.o + +main: $(OBJS) + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + + + + + + +clean: + (rm -f *.o main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< + + + + diff --git a/BE_OpenMP_2019/norm2_noowr/main.c b/BE_OpenMP_2019/norm2_noowr/main.c new file mode 100644 index 0000000..a9f9385 --- /dev/null +++ b/BE_OpenMP_2019/norm2_noowr/main.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include + +long usecs() +{ + struct timeval t; + + gettimeofday(&t, NULL); + return t.tv_sec * 1000000 + t.tv_usec; +} + +double dnorm2_seq(double *x, int n) +{ + int i; + double res, scale, ssq, absxi; + + scale = 0.0; + ssq = 1.0; + + for (i = 0; i < n; i++) + { + if (x[i] != 0.0) + { + absxi = fabs(x[i]); + if (scale < absxi) + { + ssq = 1.0 + ssq * pow(scale / absxi, 2); + scale = absxi; + } + else + { + ssq = ssq + pow(absxi / scale, 2); + } + } + } + + res = scale * sqrt(ssq); + + return res; +} + +double dnorm2_par(double *x, int n) +{ + int i; + double res, scale, ssq, absxi, myssq, myscale; + + scale = 0.0; + ssq = 1.0; + +#pragma omp parallel private(myssq, myscale, absxi) +#pragma omp for + for (i = 0; i < n; i++) + { + if (x[i] != 0.0) + { + absxi = fabs(x[i]); + if (myscale < absxi) + { + myssq = 1.0 + myssq * pow(myscale / absxi, 2); + myscale = absxi; + } + else + { + myssq = myssq + pow(absxi / myscale, 2); + } + } +#pragma omp critical + { + if (myscale > scale) + { + ssq = 1.0 + myssq * pow(scale / myscale, 2); + scale = myscale; + } + else + { + ssq = ssq + pow(myssq / scale, 2); + } + } + } + + res = scale * sqrt(ssq); + + return res; +} + +int main(int argc, char *argv[]) +{ + + int n, i; + double *x; + double n2_seq, n2_par; + long t_start, t_end; + + if (argc != 2) + { + printf("Wrong number of arguments.\n Usage:\n\n\ +./main n \n\n where n is the size of the vector x whose 2-norm has to be computed.\n"); + return 1; + } + + sscanf(argv[1], "%d", &n); + + x = (double *)malloc(sizeof(double) * n); + + for (i = 0; i < n; i++) + x[i] = ((double)500.0 * rand() / (RAND_MAX)); + + printf("\n================== Sequential version ==================\n"); + t_start = usecs(); + n2_seq = dnorm2_seq(x, n); + t_end = usecs(); + printf("Time (msec.) : %7.1f\n", (t_end - t_start) / 1e3); + printf("Computed norm is: %10.3lf\n", n2_seq); + + printf("\n\n=========== Parallel version with reduction ===========\n"); + t_start = usecs(); + n2_par = dnorm2_par(x, n); + t_end = usecs(); + printf("Time (msec.) : %7.1f\n", (t_end - t_start) / 1e3); + printf("Computed norm is: %10.3lf\n", n2_par); + + printf("\n\n"); + if (fabs(n2_seq - n2_par) / n2_seq > 1e-10) + { + printf("The parallel version is numerically wrong! \n"); + } + else + { + printf("The parallel version is numerically okay!\n"); + } + + return 0; +} diff --git a/BE_OpenMP_2019/norm2_noowr/subject.pdf b/BE_OpenMP_2019/norm2_noowr/subject.pdf new file mode 100644 index 0000000..ed967f5 Binary files /dev/null and b/BE_OpenMP_2019/norm2_noowr/subject.pdf differ diff --git a/BE_OpenMP_2019/pack.sh b/BE_OpenMP_2019/pack.sh new file mode 100644 index 0000000..a33df9d --- /dev/null +++ b/BE_OpenMP_2019/pack.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +make clean; +mkdir $USER +cp -r responses.txt band_matrix lu_tasks norm2_noowr stacks tree_branch $USER; +cd $USER; find . -name "*.pdf" | xargs rm; cd ..; +tar zcvf $USER.tgz $USER; +rm -rf $USER; diff --git a/BE_OpenMP_2019/responses.txt b/BE_OpenMP_2019/responses.txt new file mode 100644 index 0000000..47e5d0a --- /dev/null +++ b/BE_OpenMP_2019/responses.txt @@ -0,0 +1,43 @@ +In this file you have to write the answers to the questions marked +with the "pencil" symbol that you will find in the subjects of the +various exam parts. + + +======================================================================= +Part 1: Banded matrix product + + + + + + +======================================================================= +Part 2: LU factorization with tasks + + + + + + + + + +======================================================================= +Part 3: Norm2 without overflow + + + + + + +======================================================================= +Part 4: Stacks + + + + + + + +======================================================================= +Part 5: Longest branch of a tree diff --git a/BE_OpenMP_2019/stacks/Makefile b/BE_OpenMP_2019/stacks/Makefile new file mode 100644 index 0000000..374e810 --- /dev/null +++ b/BE_OpenMP_2019/stacks/Makefile @@ -0,0 +1,27 @@ +CC = gcc +LINK = $(CC) + +# CFLAGS = -O3 -fopenmp -Wunknown-pragmas +CFLAGS = -g -fopenmp +LDFLAGS = $(CFLAGS) +LIBS = -lm $(LBLAS) + +OBJS = aux.o main.o + +main: $(OBJS) + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + + +clean: + (rm -f *.o main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< + + + + diff --git a/BE_OpenMP_2019/stacks/aux.c b/BE_OpenMP_2019/stacks/aux.c new file mode 100644 index 0000000..e735f02 --- /dev/null +++ b/BE_OpenMP_2019/stacks/aux.c @@ -0,0 +1,166 @@ +#include "aux.h" + +int *stacks_list; +int *stacks_cnts; +int cnt, cnt2; + +long usecs (){ + struct timeval t; + + gettimeofday(&t,NULL); + return t.tv_sec*1000000+t.tv_usec; +} + + +void mysleep(double sec){ + + long s, e; + s=0; e=0; + s = usecs(); + while(((double) e-s)/1000000 < sec) + { + e = usecs(); + } + return; +} + + + + +void init_stacks(stack_t **stacks, int n){ + + int i; + + *stacks = (stack_t*)malloc(n*sizeof(stack_t)); + + for(i=0; i= MAXELEMS){ + return -1; + } else { + return stacks_list[c]; + } +} + + +int process(){ + + int c; + + mysleep(0.0001); + +#pragma omp atomic capture + c = cnt2++; + + return c; + +} + + +void check_result(stack_t *stacks, int n){ + + int i, j; + int *check; + + /* for(i=0; i +#include +#include + +typedef struct stackstruct{ + int cnt; + int *elems; +} stack_t; + + +void init_stacks(stack_t **stacks, int n); + +void free_stacks(stack_t **stacks, int n); + + +int get_random_stack(); +int process(); +void check_result(stack_t *stacks, int n); + + +long usecs (); +void mysleep(double sec); diff --git a/BE_OpenMP_2019/stacks/main.c b/BE_OpenMP_2019/stacks/main.c new file mode 100644 index 0000000..961972c --- /dev/null +++ b/BE_OpenMP_2019/stacks/main.c @@ -0,0 +1,158 @@ +#include "aux.h" +#include + +void stacks_seq(stack_t *stacks, int n); +void stacks_par_critical(stack_t *stacks, int n); +void stacks_par_atomic(stack_t *stacks, int n); +void stacks_par_locks(stack_t *stacks, int n); + +int main(int argc, char **argv) +{ + + stack_t *stacks; + int i, j, n; + long t_start, t_end, save; + + if (argc == 2) + { + n = atoi(argv[1]); /* the number of stacks */ + } + else + { + printf("Usage:\n\n ./main n\n\nwhere n is the number of stacks.\n"); + return 1; + } + + printf("\n"); + + init_stacks(&stacks, n); + t_start = usecs(); + stacks_seq(stacks, n); + t_end = usecs(); + printf("Sequential version. -------- time : %8.2f msec. ", ((double)t_end - t_start) / 1000.0); + check_result(stacks, n); + free_stacks(&stacks, n); + + init_stacks(&stacks, n); + t_start = usecs(); + stacks_par_critical(stacks, n); + t_end = usecs(); + printf("Critical version. -------- time : %8.2f msec. ", ((double)t_end - t_start) / 1000.0); + check_result(stacks, n); + free_stacks(&stacks, n); + + init_stacks(&stacks, n); + t_start = usecs(); + stacks_par_atomic(stacks, n); + t_end = usecs(); + printf("Atomic version. -------- time : %8.2f msec. ", ((double)t_end - t_start) / 1000.0); + check_result(stacks, n); + free_stacks(&stacks, n); + + init_stacks(&stacks, n); + t_start = usecs(); + stacks_par_locks(stacks, n); + t_end = usecs(); + printf("Locks version. -------- time : %8.2f msec. ", ((double)t_end - t_start) / 1000.0); + check_result(stacks, n); + free_stacks(&stacks, n); + + return 0; +} + +void stacks_seq(stack_t *stacks, int n) +{ + + int s; + + for (;;) + { + + /* Get the stack number s */ + s = get_random_stack(); + + if (s == -1) + break; + + /* Push some value on stack s */ + stacks[s].elems[stacks[s].cnt++] = process(); + } +} + +void stacks_par_critical(stack_t *stacks, int n) +{ + + int s, tmp; + +#pragma omp parallel private(s, tmp) + for (;;) + { + + /* Get the stack number s */ + s = get_random_stack(); + + if (s == -1) + break; + + /* Push some value on stack s */ + // On sort la fonction process de la section critique parce que cela ne pose pas de problème/ + tmp = process(); +#pragma omp critical + stacks[s].elems[stacks[s].cnt++] = tmp; + } +} + +void stacks_par_atomic(stack_t *stacks, int n) +{ + + int s, tmp; +#pragma omp parallel private(s, tmp) + for (;;) + { + + /* Get the stack number s */ + s = get_random_stack(); + + if (s == -1) + break; +#pragma omp atomic capture + tmp = stacks[s].cnt++; // On réserve la pile + + /* Push some value on stack s */ + stacks[s].elems[tmp] = process(); + } +} + +void stacks_par_locks(stack_t *stacks, int n) +{ + + int s, tmp; + omp_lock_t* lock = malloc(1000 * sizeof(omp_lock_t)); + + for (int i = 0; i < 1000; i++) + { + omp_init_lock(lock + i); + } + +#pragma omp parallel private(s, tmp) + for (;;) + { + + /* Get the stack number s */ + s = get_random_stack(); + + if (s == -1) + break; + + tmp = process(); + + /* Push some value on stack s */ + omp_set_lock(lock + s); + stacks[s].elems[stacks[s].cnt++] = tmp; + omp_unset_lock(lock + s); + } + for (int i = 0; i < 1000; i++) + { + omp_destroy_lock(lock + i); + } +} diff --git a/BE_OpenMP_2019/stacks/subject.pdf b/BE_OpenMP_2019/stacks/subject.pdf new file mode 100644 index 0000000..e354e8d Binary files /dev/null and b/BE_OpenMP_2019/stacks/subject.pdf differ diff --git a/BE_OpenMP_2019/subject.pdf b/BE_OpenMP_2019/subject.pdf new file mode 100644 index 0000000..1b2b3ea Binary files /dev/null and b/BE_OpenMP_2019/subject.pdf differ diff --git a/BE_OpenMP_2019/tree_branch/Makefile b/BE_OpenMP_2019/tree_branch/Makefile new file mode 100644 index 0000000..e990659 --- /dev/null +++ b/BE_OpenMP_2019/tree_branch/Makefile @@ -0,0 +1,31 @@ +CC = gcc +LINK = $(CC) + +CFLAGS = -g -fopenmp -Wunknown-pragmas +# CFLAGS = -g -fopenmp +LDFLAGS = $(CFLAGS) +LIBS = -lm + +OBJS = _aux.o longest_branch_seq.o longest_branch_par.o main.o + +main: $(OBJS) + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + + + + + + +clean: + (rm -f *.o main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< + + + + diff --git a/BE_OpenMP_2019/tree_branch/_aux.c b/BE_OpenMP_2019/tree_branch/_aux.c new file mode 100644 index 0000000..25e3c9b --- /dev/null +++ b/BE_OpenMP_2019/tree_branch/_aux.c @@ -0,0 +1,119 @@ +#include "_aux.h" +#include +#include + +long usecs (){ + struct timeval t; + + gettimeofday(&t,NULL); + return t.tv_sec*1000000+t.tv_usec; +} + + +void mysleep(double sec){ + + long s, e; + s=0; e=0; + s = usecs(); + while(((double) e-s)/1000000 < sec) + { + e = usecs(); + } + return; +} + + + + + +void treeinitrec(node_t *root, int l, int *id){ + + int i; + + if (l==-1) + return; + + root->id = ++(*id); + root->nc = rand()%l; + root->children = (node_t*)malloc(root->nc*sizeof(node_t)); + root->weight = rand()%50+1; + /* root->branch_weight = 0; */ + + for(i=0; inc; i++) + treeinitrec(root->children+i, l-1, id); + + return ; +} + + +void treeinit(node_t *root, int l){ + + int id; + + id = 0; + + + treeinitrec(root, l, &id); + + treeprint(root, "tree.dot"); + + return ; +} + + + + + +void treeprintrec(node_t *root, FILE *pfile){ + + int i; + + + fprintf(pfile, "node%4.4d[label=\"id:%d\\lwg:%d\\l\"];\n",root->id,root->id, root->weight); + + for(i=0; inc; i++) + fprintf(pfile, "node%4.4d -- node%4.4d\n",root->id,root->children[i].id); + + for(i=0; inc; i++) + treeprintrec(root->children+i, pfile); + + return; + +} + + + +void treeprint(node_t *root, char *fname){ + + FILE *pfile; + + pfile = fopen (fname,"w"); + + + fprintf(pfile, "graph G {\n"); + fprintf(pfile, "node [color=black,\n"); + fprintf(pfile, "fillcolor=white,\n"); + fprintf(pfile, "shape=circle,\n"); + fprintf(pfile, "fontname=Courier,\n"); + fprintf(pfile, "style=filled\n"); + fprintf(pfile, "];\n"); + + + treeprintrec(root, pfile); + + fprintf(pfile, "}"); + + + fclose(pfile); + +} + + + +int process(node_t *node){ + + /* printf("%2d ---> %4d\n",omp_get_thread_num(), node->id); */ + mysleep(((double)node->weight)/10000.0); + return 0; + +} diff --git a/BE_OpenMP_2019/tree_branch/_aux.h b/BE_OpenMP_2019/tree_branch/_aux.h new file mode 100644 index 0000000..25ab640 --- /dev/null +++ b/BE_OpenMP_2019/tree_branch/_aux.h @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +typedef struct nodestruct{ + unsigned int weight, branch_weight; + unsigned int id, nc; + struct nodestruct *children; +} node_t; + + +long usecs (); +void treeinit(node_t *root, int l); +int process(node_t *node); +void treeprint(node_t *root, char *fname); + + +void longest_branch_seq(node_t *root, unsigned int *weight, unsigned int *leaf); +void longest_branch_seq_rec(node_t *root, unsigned int *weight, unsigned int *leaf); +void longest_branch_par(node_t *root, unsigned int *weight, unsigned int *leaf); +void longest_branch_par_rec(node_t *root, unsigned int *weight, unsigned int *leaf, int * updates); diff --git a/BE_OpenMP_2019/tree_branch/longest_branch_par.c b/BE_OpenMP_2019/tree_branch/longest_branch_par.c new file mode 100644 index 0000000..2ed3354 --- /dev/null +++ b/BE_OpenMP_2019/tree_branch/longest_branch_par.c @@ -0,0 +1,53 @@ +#include "_aux.h" +#include "omp.h" + + +void longest_branch_par(node_t *root, unsigned int *longest_branch_weight, unsigned int *longest_branch_leaf){ + + *longest_branch_weight = 0; + *longest_branch_leaf = -1; + root->branch_weight = 0; + + int *updates = (int*) calloc(omp_get_max_threads(),sizeof(int)); + #pragma omp parallel + { + #pragma omp single + { + longest_branch_par_rec(root, longest_branch_weight, longest_branch_leaf, updates); + } + } + for (int thread = 0; thread < omp_get_max_threads(); thread++) { + printf("%d ",updates[thread]); + } + printf("\n"); + free(updates); + + +} + +void longest_branch_par_rec(node_t *root, unsigned int *longest_branch_weight, unsigned int *longest_branch_leaf, int * updates){ + + int i; + + process(root); + root->branch_weight += root->weight; + + if(root->nc>0) { + for(i=0; inc; i++){ + #pragma omp task firstprivate(i) + { + root->children[i].branch_weight = root->branch_weight; + updates[omp_get_thread_num()] += 1; + longest_branch_par_rec(root->children+i, longest_branch_weight, longest_branch_leaf,updates); + } + + } + + } else { + if(root->branch_weight > *longest_branch_weight){ + *longest_branch_weight = root->branch_weight; + *longest_branch_leaf = root->id; + } + } + +} diff --git a/BE_OpenMP_2019/tree_branch/longest_branch_seq.c b/BE_OpenMP_2019/tree_branch/longest_branch_seq.c new file mode 100644 index 0000000..d6d40d9 --- /dev/null +++ b/BE_OpenMP_2019/tree_branch/longest_branch_seq.c @@ -0,0 +1,37 @@ +#include "_aux.h" + +void longest_branch_seq(node_t *root, unsigned int *longest_branch_weight, unsigned int *longest_branch_leaf){ + + *longest_branch_weight = 0; + *longest_branch_leaf = -1; + root->branch_weight = 0; + + longest_branch_seq_rec(root, longest_branch_weight, longest_branch_leaf); + + +} + +void longest_branch_seq_rec(node_t *root, unsigned int *longest_branch_weight, unsigned int *longest_branch_leaf){ + + int i; + + process(root); + root->branch_weight += root->weight; + + if(root->nc>0) { + for(i=0; inc; i++){ + root->children[i].branch_weight = root->branch_weight; + longest_branch_seq_rec(root->children+i, longest_branch_weight, longest_branch_leaf); + } + } else { + if(root->branch_weight > *longest_branch_weight){ + *longest_branch_weight = root->branch_weight; + *longest_branch_leaf = root->id; + } + } + +} + + + + diff --git a/BE_OpenMP_2019/tree_branch/main.c b/BE_OpenMP_2019/tree_branch/main.c new file mode 100644 index 0000000..1f21b1c --- /dev/null +++ b/BE_OpenMP_2019/tree_branch/main.c @@ -0,0 +1,63 @@ +#include "_aux.h" + +void longest_branch_seq(node_t *root, unsigned int *longest_branch_weight, unsigned int *longest_branch_leaf); +void longest_branch_seq_rec(node_t *root, unsigned int *longest_branch_weight, unsigned int *longest_branch_leaf); + +void longest_branch_par(node_t *root, unsigned int *longest_branch_weight, unsigned int *longest_branch_leaf); +void longest_branch_par_rec(node_t *root, unsigned int *longest_branch_weight, unsigned int *longest_branch_leaf, int * updates); + +int main(int argc, char **argv) { + + int n; + int i, l, r, s; + long ts, te; + node_t root; + unsigned int longest_branch_weight, longest_branch_leaf; + + if ( argc == 3 ) { + l = atoi(argv[1]); /* the number of levels in the tree */ + s = atoi(argv[2]); /* the seed for the random number generation */ + } else { + printf("Usage:\n\n ./main l s\n\nwhere l is the number of levels in the tree and s the seed for the random number generation.\n"); + return 1; + } + + /* Chage this to generate different trees */ + srand(s); + + treeinit(&root, l); + + + printf("==================================================\n\n"); + printf("Starting sequential execution\n"); + + ts = usecs(); + longest_branch_seq(&root, &longest_branch_weight, &longest_branch_leaf); + te = usecs()-ts; + + printf("Sequential execution time: %6ld msec.\n",te/1000); + printf("Sequential weight : %d\n",longest_branch_weight); + printf("Sequential leaf : %d\n",longest_branch_leaf); + + + + + printf("==================================================\n\n"); + printf("Starting parallel execution\n"); + + ts = usecs(); + longest_branch_par(&root, &longest_branch_weight, &longest_branch_leaf); + te = usecs()-ts; + + printf("Parallel execution time : %6ld msec.\n",te/1000); + printf("Parallel weight : %d\n",longest_branch_weight); + printf("Parallel leaf : %d\n",longest_branch_leaf); + + return 0; + +} + + + + + diff --git a/BE_OpenMP_2019/tree_branch/subject.pdf b/BE_OpenMP_2019/tree_branch/subject.pdf new file mode 100644 index 0000000..5098865 Binary files /dev/null and b/BE_OpenMP_2019/tree_branch/subject.pdf differ diff --git a/BE_OpenMP_2019/tree_branch/subject.tex b/BE_OpenMP_2019/tree_branch/subject.tex new file mode 100644 index 0000000..b24e494 --- /dev/null +++ b/BE_OpenMP_2019/tree_branch/subject.tex @@ -0,0 +1,174 @@ +\documentclass{article} + +\usepackage{algorithm} +\usepackage{algorithmic} +\usepackage{graphicx} +\usepackage{marvosym} +\usepackage{dingbat} +\usepackage{tikz} + +\title{Longest branch of a tree} +\date{} + +\usetikzlibrary{arrows} + +\tikzset{ + treenode/.style = {align=center, inner sep=0pt, text centered, font=\sffamily}, + wn/.style = {treenode, circle, black, font=\ttfamily, draw=white, fill=white, text width=1.5em}, + txt/.style = {black, anchor=west, font=\ttfamily, draw=white, fill=white}, + edge from parent/.style={thick,draw=black, latex-} +} + +\begin{document} +\maketitle + +\section{Longest tree branch} + +This exercise is about parallelizing a Depth First Search (DFS) traversal of +a random tree. We assume that each node has a weight which corresponds +to the time it takes to process it. Our DFS traversal finds the +longest branch in the tree, i.e., the branch such that the sum of the +weigths of its nodes is maximum. + +The tree is nodes of type \texttt{node\_t} which contain the following members + +\begin{itemize} +\item \texttt{weight}: the weight of the node; +\item \texttt{branch\_weight}: the weight of the branch that connects + the node to the root of the tree; this is set to zero at the + beginning and is updated during the DFS traversal; +\item \texttt{id}: the node number; +\item \texttt{nc}: the number of children of the node. +\item \texttt{*children}: an array of pointers to the children of the node. +\end{itemize} + +The traversal is done recursively using the following code + +\begin{verbatim} +void longest_branch_seq_rec(node_t *root, unsigned int *weight, unsigned int *leaf){ + int i; + process(root); + root->branch_weight += root->weight; + + if(root->nc>0) { + for(i=0; inc; i++){ + root->children[i].branch_weight = root->branch_weight; + longest_branch_seq_rec(root->children+i, weight, leaf); + } + } else { + if(root->branch_weight > *weight){ + *weight = root->branch_weight; + *leaf = root->id; + } + } +} +\end{verbatim} + +The \texttt{weight} and \texttt{leaf} arguments of this function are +meant to return the weight of the longest branch and the corresponding +leaf. When we visit a node, first we process it using the +\texttt{process} routine and we update the weight of the branch that +connects it to the root (i.e., we add its weight to the branch weight +of its father). Then, if it has children, we recursively call this +code on each one of them, if not then it means that we have reached a +leaf of the tree; in this case if the weight of the current branch is +grater than the current maximum contained in the \texttt{weight} +variable, we update \texttt{weight} and \texttt{leaf}. + +For example, on the tree below, this method would return the leaf +number $3$ and the associated weight of $137$. + +\begin{center} + \includegraphics[width=0.4\textwidth]{tree.pdf} +\end{center} + + +\section{Package content} +In the \texttt{tree\_branch} directory you will find the +following files: +\begin{itemize} +\item \texttt{main.c}: this file contains the main program which first + initializes the tree for a provided number of maximum levels. The main + program then calls a sequential routine \texttt{longest\_branch\_seq} + containing the above code, then calls the + \texttt{longest\_branch\_par} routine which is supposed to contain a + parallel version of the traversal code. +\item \texttt{longest\_branch\_seq.c}: contains a routine implementing a + sequential traversal with the code presented above. +\item \texttt{longest\_branch\_par.c} contains a routine implementing a + parallel tree traversal. \textbf{Only this file has to be modified + for this exercise}. +\item \texttt{aux.c, aux.h}: these two files contain auxiliary + routines and \textbf{must not be modified}. +\end{itemize} + + + +The code can be compiled with the \texttt{make} command: just type +\texttt{make} inside the \texttt{tree\_branch} directory; this +will generate a \texttt{main} program that can be run like this: + +\begin{verbatim} +$ ./main l s +\end{verbatim} + +where \texttt{l} is the number of levels in the tree. The argument $s$ +is the seed for the random number generation (which is used to build +the tree), and can be used to create trees of different shapes for a +fixed number of levels. + +\section{Assignment} +\begin{itemize} +\item {\huge \Keyboard} At the beginning, the + \texttt{longest\_branch\_par} routine contains an exact copy of the + \texttt{longest\_branch\_seq} one. Modify these routine in order to + parallelize it. Make sure that the result computed by the three + routines (sequential and parallel ones) is consistently (that is, at + every execution of the parallel code) the same; a message printed at + the end of the execution will tell you whether this is the + case. Note that there may be multiple branches of the same length; + in this case any of them will be considered a correct result. Also, + modify the code in order to count the number of nodes updated by + each of the working threads. +\item \smallpencil Report the execution times for the implemented + parallel version with 1, 2 and 4 threads and for different tree + sizes. Analyze and comment on your results: is the achieved speedup + reasonable or not? Report your answer in the \texttt{responses.txt} + file. +\end{itemize} + + +\paragraph{Advice} +\begin{itemize} +\item As usual, when developing and debugging choose trees of small + size. When evaluating performance it's better to choose a larges + tree size. +\end{itemize} + + + + + + + + + + + + + + + + + + + +\end{document} + + + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: t +%%% End: diff --git a/BE_OpenMP_2019/tree_branch/tree.dot b/BE_OpenMP_2019/tree_branch/tree.dot new file mode 100644 index 0000000..3beb37b --- /dev/null +++ b/BE_OpenMP_2019/tree_branch/tree.dot @@ -0,0 +1,3747 @@ +graph G { +node [color=black, +fillcolor=white, +shape=circle, +fontname=Courier, +style=filled +]; +node0001[label="id:1\lwg:23\l"]; +node0001 -- node0002 +node0002[label="id:2\lwg:37\l"]; +node0002 -- node0003 +node0002 -- node0153 +node0002 -- node0405 +node0002 -- node0406 +node0002 -- node0814 +node0002 -- node1173 +node0003[label="id:3\lwg:12\l"]; +node0003 -- node0004 +node0003 -- node0111 +node0003 -- node0112 +node0003 -- node0113 +node0003 -- node0114 +node0003 -- node0134 +node0003 -- node0135 +node0004[label="id:4\lwg:29\l"]; +node0004 -- node0005 +node0004 -- node0042 +node0004 -- node0043 +node0004 -- node0073 +node0004 -- node0079 +node0004 -- node0085 +node0005[label="id:5\lwg:42\l"]; +node0005 -- node0006 +node0005 -- node0019 +node0005 -- node0033 +node0005 -- node0035 +node0005 -- node0041 +node0006[label="id:6\lwg:10\l"]; +node0006 -- node0007 +node0006 -- node0015 +node0006 -- node0018 +node0007[label="id:7\lwg:20\l"]; +node0007 -- node0008 +node0007 -- node0010 +node0007 -- node0014 +node0008[label="id:8\lwg:2\l"]; +node0008 -- node0009 +node0009[label="id:9\lwg:8\l"]; +node0010[label="id:10\lwg:9\l"]; +node0010 -- node0011 +node0010 -- node0012 +node0011[label="id:11\lwg:11\l"]; +node0012[label="id:12\lwg:25\l"]; +node0012 -- node0013 +node0013[label="id:13\lwg:35\l"]; +node0014[label="id:14\lwg:36\l"]; +node0015[label="id:15\lwg:15\l"]; +node0015 -- node0016 +node0016[label="id:16\lwg:27\l"]; +node0016 -- node0017 +node0017[label="id:17\lwg:44\l"]; +node0018[label="id:18\lwg:19\l"]; +node0019[label="id:19\lwg:30\l"]; +node0019 -- node0020 +node0019 -- node0021 +node0019 -- node0028 +node0019 -- node0029 +node0020[label="id:20\lwg:38\l"]; +node0021[label="id:21\lwg:42\l"]; +node0021 -- node0022 +node0021 -- node0025 +node0022[label="id:22\lwg:50\l"]; +node0022 -- node0023 +node0022 -- node0024 +node0023[label="id:23\lwg:25\l"]; +node0024[label="id:24\lwg:28\l"]; +node0025[label="id:25\lwg:2\l"]; +node0025 -- node0026 +node0026[label="id:26\lwg:37\l"]; +node0026 -- node0027 +node0027[label="id:27\lwg:42\l"]; +node0028[label="id:28\lwg:42\l"]; +node0029[label="id:29\lwg:2\l"]; +node0029 -- node0030 +node0030[label="id:30\lwg:43\l"]; +node0030 -- node0031 +node0030 -- node0032 +node0031[label="id:31\lwg:2\l"]; +node0032[label="id:32\lwg:5\l"]; +node0033[label="id:33\lwg:34\l"]; +node0033 -- node0034 +node0034[label="id:34\lwg:3\l"]; +node0035[label="id:35\lwg:22\l"]; +node0035 -- node0036 +node0035 -- node0040 +node0036[label="id:36\lwg:36\l"]; +node0036 -- node0037 +node0037[label="id:37\lwg:38\l"]; +node0037 -- node0038 +node0037 -- node0039 +node0038[label="id:38\lwg:28\l"]; +node0039[label="id:39\lwg:40\l"]; +node0040[label="id:40\lwg:1\l"]; +node0041[label="id:41\lwg:40\l"]; +node0042[label="id:42\lwg:4\l"]; +node0043[label="id:43\lwg:1\l"]; +node0043 -- node0044 +node0043 -- node0045 +node0043 -- node0061 +node0043 -- node0072 +node0044[label="id:44\lwg:13\l"]; +node0045[label="id:45\lwg:22\l"]; +node0045 -- node0046 +node0045 -- node0049 +node0045 -- node0050 +node0045 -- node0057 +node0046[label="id:46\lwg:23\l"]; +node0046 -- node0047 +node0046 -- node0048 +node0047[label="id:47\lwg:26\l"]; +node0048[label="id:48\lwg:24\l"]; +node0049[label="id:49\lwg:4\l"]; +node0050[label="id:50\lwg:23\l"]; +node0050 -- node0051 +node0050 -- node0056 +node0051[label="id:51\lwg:18\l"]; +node0051 -- node0052 +node0051 -- node0054 +node0052[label="id:52\lwg:41\l"]; +node0052 -- node0053 +node0053[label="id:53\lwg:47\l"]; +node0054[label="id:54\lwg:24\l"]; +node0054 -- node0055 +node0055[label="id:55\lwg:22\l"]; +node0056[label="id:56\lwg:28\l"]; +node0057[label="id:57\lwg:14\l"]; +node0057 -- node0058 +node0058[label="id:58\lwg:48\l"]; +node0058 -- node0059 +node0059[label="id:59\lwg:28\l"]; +node0059 -- node0060 +node0060[label="id:60\lwg:18\l"]; +node0061[label="id:61\lwg:15\l"]; +node0061 -- node0062 +node0062[label="id:62\lwg:27\l"]; +node0062 -- node0063 +node0062 -- node0066 +node0062 -- node0067 +node0063[label="id:63\lwg:21\l"]; +node0063 -- node0064 +node0064[label="id:64\lwg:50\l"]; +node0064 -- node0065 +node0065[label="id:65\lwg:28\l"]; +node0066[label="id:66\lwg:2\l"]; +node0067[label="id:67\lwg:34\l"]; +node0067 -- node0068 +node0067 -- node0070 +node0068[label="id:68\lwg:7\l"]; +node0068 -- node0069 +node0069[label="id:69\lwg:12\l"]; +node0070[label="id:70\lwg:17\l"]; +node0070 -- node0071 +node0071[label="id:71\lwg:7\l"]; +node0072[label="id:72\lwg:48\l"]; +node0073[label="id:73\lwg:28\l"]; +node0073 -- node0074 +node0073 -- node0075 +node0073 -- node0076 +node0074[label="id:74\lwg:33\l"]; +node0075[label="id:75\lwg:5\l"]; +node0076[label="id:76\lwg:9\l"]; +node0076 -- node0077 +node0076 -- node0078 +node0077[label="id:77\lwg:44\l"]; +node0078[label="id:78\lwg:12\l"]; +node0079[label="id:79\lwg:38\l"]; +node0079 -- node0080 +node0080[label="id:80\lwg:39\l"]; +node0080 -- node0081 +node0080 -- node0083 +node0081[label="id:81\lwg:37\l"]; +node0081 -- node0082 +node0082[label="id:82\lwg:15\l"]; +node0083[label="id:83\lwg:34\l"]; +node0083 -- node0084 +node0084[label="id:84\lwg:1\l"]; +node0085[label="id:85\lwg:4\l"]; +node0085 -- node0086 +node0085 -- node0096 +node0086[label="id:86\lwg:29\l"]; +node0086 -- node0087 +node0086 -- node0093 +node0086 -- node0094 +node0087[label="id:87\lwg:16\l"]; +node0087 -- node0088 +node0087 -- node0089 +node0087 -- node0090 +node0088[label="id:88\lwg:29\l"]; +node0089[label="id:89\lwg:24\l"]; +node0090[label="id:90\lwg:2\l"]; +node0090 -- node0091 +node0091[label="id:91\lwg:17\l"]; +node0091 -- node0092 +node0092[label="id:92\lwg:3\l"]; +node0093[label="id:93\lwg:46\l"]; +node0094[label="id:94\lwg:28\l"]; +node0094 -- node0095 +node0095[label="id:95\lwg:29\l"]; +node0096[label="id:96\lwg:1\l"]; +node0096 -- node0097 +node0096 -- node0104 +node0096 -- node0110 +node0097[label="id:97\lwg:10\l"]; +node0097 -- node0098 +node0097 -- node0100 +node0098[label="id:98\lwg:38\l"]; +node0098 -- node0099 +node0099[label="id:99\lwg:37\l"]; +node0100[label="id:100\lwg:39\l"]; +node0100 -- node0101 +node0100 -- node0103 +node0101[label="id:101\lwg:8\l"]; +node0101 -- node0102 +node0102[label="id:102\lwg:1\l"]; +node0103[label="id:103\lwg:48\l"]; +node0104[label="id:104\lwg:19\l"]; +node0104 -- node0105 +node0104 -- node0109 +node0105[label="id:105\lwg:45\l"]; +node0105 -- node0106 +node0105 -- node0107 +node0106[label="id:106\lwg:2\l"]; +node0107[label="id:107\lwg:30\l"]; +node0107 -- node0108 +node0108[label="id:108\lwg:26\l"]; +node0109[label="id:109\lwg:22\l"]; +node0110[label="id:110\lwg:9\l"]; +node0111[label="id:111\lwg:21\l"]; +node0112[label="id:112\lwg:18\l"]; +node0113[label="id:113\lwg:25\l"]; +node0114[label="id:114\lwg:25\l"]; +node0114 -- node0115 +node0114 -- node0127 +node0115[label="id:115\lwg:46\l"]; +node0115 -- node0116 +node0115 -- node0126 +node0116[label="id:116\lwg:4\l"]; +node0116 -- node0117 +node0116 -- node0123 +node0116 -- node0124 +node0117[label="id:117\lwg:35\l"]; +node0117 -- node0118 +node0117 -- node0121 +node0118[label="id:118\lwg:29\l"]; +node0118 -- node0119 +node0119[label="id:119\lwg:38\l"]; +node0119 -- node0120 +node0120[label="id:120\lwg:6\l"]; +node0121[label="id:121\lwg:19\l"]; +node0121 -- node0122 +node0122[label="id:122\lwg:45\l"]; +node0123[label="id:123\lwg:15\l"]; +node0124[label="id:124\lwg:28\l"]; +node0124 -- node0125 +node0125[label="id:125\lwg:25\l"]; +node0126[label="id:126\lwg:39\l"]; +node0127[label="id:127\lwg:46\l"]; +node0127 -- node0128 +node0127 -- node0133 +node0128[label="id:128\lwg:27\l"]; +node0128 -- node0129 +node0128 -- node0132 +node0129[label="id:129\lwg:14\l"]; +node0129 -- node0130 +node0130[label="id:130\lwg:34\l"]; +node0130 -- node0131 +node0131[label="id:131\lwg:17\l"]; +node0132[label="id:132\lwg:15\l"]; +node0133[label="id:133\lwg:46\l"]; +node0134[label="id:134\lwg:34\l"]; +node0135[label="id:135\lwg:43\l"]; +node0135 -- node0136 +node0135 -- node0137 +node0135 -- node0139 +node0135 -- node0150 +node0135 -- node0151 +node0135 -- node0152 +node0136[label="id:136\lwg:14\l"]; +node0137[label="id:137\lwg:49\l"]; +node0137 -- node0138 +node0138[label="id:138\lwg:16\l"]; +node0139[label="id:139\lwg:32\l"]; +node0139 -- node0140 +node0139 -- node0149 +node0140[label="id:140\lwg:50\l"]; +node0140 -- node0141 +node0140 -- node0145 +node0141[label="id:141\lwg:30\l"]; +node0141 -- node0142 +node0142[label="id:142\lwg:3\l"]; +node0142 -- node0143 +node0142 -- node0144 +node0143[label="id:143\lwg:47\l"]; +node0144[label="id:144\lwg:48\l"]; +node0145[label="id:145\lwg:32\l"]; +node0145 -- node0146 +node0146[label="id:146\lwg:20\l"]; +node0146 -- node0147 +node0147[label="id:147\lwg:21\l"]; +node0147 -- node0148 +node0148[label="id:148\lwg:50\l"]; +node0149[label="id:149\lwg:32\l"]; +node0150[label="id:150\lwg:48\l"]; +node0151[label="id:151\lwg:25\l"]; +node0152[label="id:152\lwg:42\l"]; +node0153[label="id:153\lwg:25\l"]; +node0153 -- node0154 +node0153 -- node0304 +node0153 -- node0404 +node0154[label="id:154\lwg:36\l"]; +node0154 -- node0155 +node0154 -- node0178 +node0154 -- node0179 +node0154 -- node0180 +node0154 -- node0231 +node0155[label="id:155\lwg:49\l"]; +node0155 -- node0156 +node0155 -- node0169 +node0156[label="id:156\lwg:14\l"]; +node0156 -- node0157 +node0156 -- node0163 +node0157[label="id:157\lwg:27\l"]; +node0157 -- node0158 +node0158[label="id:158\lwg:4\l"]; +node0158 -- node0159 +node0158 -- node0161 +node0159[label="id:159\lwg:49\l"]; +node0159 -- node0160 +node0160[label="id:160\lwg:35\l"]; +node0161[label="id:161\lwg:33\l"]; +node0161 -- node0162 +node0162[label="id:162\lwg:30\l"]; +node0163[label="id:163\lwg:42\l"]; +node0163 -- node0164 +node0163 -- node0167 +node0164[label="id:164\lwg:20\l"]; +node0164 -- node0165 +node0165[label="id:165\lwg:18\l"]; +node0165 -- node0166 +node0166[label="id:166\lwg:2\l"]; +node0167[label="id:167\lwg:31\l"]; +node0167 -- node0168 +node0168[label="id:168\lwg:17\l"]; +node0169[label="id:169\lwg:49\l"]; +node0169 -- node0170 +node0169 -- node0176 +node0170[label="id:170\lwg:16\l"]; +node0170 -- node0171 +node0170 -- node0175 +node0171[label="id:171\lwg:42\l"]; +node0171 -- node0172 +node0171 -- node0173 +node0172[label="id:172\lwg:26\l"]; +node0173[label="id:173\lwg:49\l"]; +node0173 -- node0174 +node0174[label="id:174\lwg:43\l"]; +node0175[label="id:175\lwg:31\l"]; +node0176[label="id:176\lwg:28\l"]; +node0176 -- node0177 +node0177[label="id:177\lwg:34\l"]; +node0178[label="id:178\lwg:17\l"]; +node0179[label="id:179\lwg:42\l"]; +node0180[label="id:180\lwg:2\l"]; +node0180 -- node0181 +node0180 -- node0194 +node0180 -- node0218 +node0180 -- node0220 +node0180 -- node0222 +node0181[label="id:181\lwg:4\l"]; +node0181 -- node0182 +node0181 -- node0183 +node0181 -- node0188 +node0182[label="id:182\lwg:2\l"]; +node0183[label="id:183\lwg:47\l"]; +node0183 -- node0184 +node0184[label="id:184\lwg:43\l"]; +node0184 -- node0185 +node0184 -- node0186 +node0185[label="id:185\lwg:23\l"]; +node0186[label="id:186\lwg:45\l"]; +node0186 -- node0187 +node0187[label="id:187\lwg:41\l"]; +node0188[label="id:188\lwg:33\l"]; +node0188 -- node0189 +node0189[label="id:189\lwg:50\l"]; +node0189 -- node0190 +node0189 -- node0192 +node0190[label="id:190\lwg:39\l"]; +node0190 -- node0191 +node0191[label="id:191\lwg:5\l"]; +node0192[label="id:192\lwg:44\l"]; +node0192 -- node0193 +node0193[label="id:193\lwg:29\l"]; +node0194[label="id:194\lwg:16\l"]; +node0194 -- node0195 +node0194 -- node0199 +node0194 -- node0206 +node0194 -- node0217 +node0195[label="id:195\lwg:45\l"]; +node0195 -- node0196 +node0196[label="id:196\lwg:30\l"]; +node0196 -- node0197 +node0197[label="id:197\lwg:24\l"]; +node0197 -- node0198 +node0198[label="id:198\lwg:36\l"]; +node0199[label="id:199\lwg:49\l"]; +node0199 -- node0200 +node0199 -- node0204 +node0200[label="id:200\lwg:21\l"]; +node0200 -- node0201 +node0200 -- node0202 +node0201[label="id:201\lwg:42\l"]; +node0202[label="id:202\lwg:36\l"]; +node0202 -- node0203 +node0203[label="id:203\lwg:37\l"]; +node0204[label="id:204\lwg:24\l"]; +node0204 -- node0205 +node0205[label="id:205\lwg:48\l"]; +node0206[label="id:206\lwg:20\l"]; +node0206 -- node0207 +node0206 -- node0212 +node0206 -- node0214 +node0207[label="id:207\lwg:33\l"]; +node0207 -- node0208 +node0207 -- node0210 +node0208[label="id:208\lwg:39\l"]; +node0208 -- node0209 +node0209[label="id:209\lwg:23\l"]; +node0210[label="id:210\lwg:30\l"]; +node0210 -- node0211 +node0211[label="id:211\lwg:25\l"]; +node0212[label="id:212\lwg:19\l"]; +node0212 -- node0213 +node0213[label="id:213\lwg:42\l"]; +node0214[label="id:214\lwg:23\l"]; +node0214 -- node0215 +node0215[label="id:215\lwg:38\l"]; +node0215 -- node0216 +node0216[label="id:216\lwg:15\l"]; +node0217[label="id:217\lwg:10\l"]; +node0218[label="id:218\lwg:12\l"]; +node0218 -- node0219 +node0219[label="id:219\lwg:24\l"]; +node0220[label="id:220\lwg:37\l"]; +node0220 -- node0221 +node0221[label="id:221\lwg:50\l"]; +node0222[label="id:222\lwg:22\l"]; +node0222 -- node0223 +node0222 -- node0229 +node0223[label="id:223\lwg:21\l"]; +node0223 -- node0224 +node0223 -- node0225 +node0223 -- node0228 +node0224[label="id:224\lwg:45\l"]; +node0225[label="id:225\lwg:18\l"]; +node0225 -- node0226 +node0226[label="id:226\lwg:17\l"]; +node0226 -- node0227 +node0227[label="id:227\lwg:37\l"]; +node0228[label="id:228\lwg:44\l"]; +node0229[label="id:229\lwg:45\l"]; +node0229 -- node0230 +node0230[label="id:230\lwg:21\l"]; +node0231[label="id:231\lwg:9\l"]; +node0231 -- node0232 +node0231 -- node0242 +node0231 -- node0265 +node0231 -- node0272 +node0231 -- node0293 +node0232[label="id:232\lwg:12\l"]; +node0232 -- node0233 +node0233[label="id:233\lwg:41\l"]; +node0233 -- node0234 +node0233 -- node0237 +node0233 -- node0240 +node0234[label="id:234\lwg:18\l"]; +node0234 -- node0235 +node0235[label="id:235\lwg:11\l"]; +node0235 -- node0236 +node0236[label="id:236\lwg:37\l"]; +node0237[label="id:237\lwg:14\l"]; +node0237 -- node0238 +node0238[label="id:238\lwg:45\l"]; +node0238 -- node0239 +node0239[label="id:239\lwg:22\l"]; +node0240[label="id:240\lwg:31\l"]; +node0240 -- node0241 +node0241[label="id:241\lwg:17\l"]; +node0242[label="id:242\lwg:34\l"]; +node0242 -- node0243 +node0242 -- node0244 +node0242 -- node0255 +node0243[label="id:243\lwg:36\l"]; +node0244[label="id:244\lwg:32\l"]; +node0244 -- node0245 +node0244 -- node0250 +node0244 -- node0251 +node0245[label="id:245\lwg:43\l"]; +node0245 -- node0246 +node0245 -- node0248 +node0246[label="id:246\lwg:13\l"]; +node0246 -- node0247 +node0247[label="id:247\lwg:43\l"]; +node0248[label="id:248\lwg:23\l"]; +node0248 -- node0249 +node0249[label="id:249\lwg:50\l"]; +node0250[label="id:250\lwg:50\l"]; +node0251[label="id:251\lwg:46\l"]; +node0251 -- node0252 +node0251 -- node0254 +node0252[label="id:252\lwg:25\l"]; +node0252 -- node0253 +node0253[label="id:253\lwg:46\l"]; +node0254[label="id:254\lwg:46\l"]; +node0255[label="id:255\lwg:12\l"]; +node0255 -- node0256 +node0255 -- node0261 +node0256[label="id:256\lwg:7\l"]; +node0256 -- node0257 +node0256 -- node0259 +node0257[label="id:257\lwg:27\l"]; +node0257 -- node0258 +node0258[label="id:258\lwg:32\l"]; +node0259[label="id:259\lwg:17\l"]; +node0259 -- node0260 +node0260[label="id:260\lwg:45\l"]; +node0261[label="id:261\lwg:18\l"]; +node0261 -- node0262 +node0261 -- node0263 +node0262[label="id:262\lwg:16\l"]; +node0263[label="id:263\lwg:36\l"]; +node0263 -- node0264 +node0264[label="id:264\lwg:46\l"]; +node0265[label="id:265\lwg:32\l"]; +node0265 -- node0266 +node0266[label="id:266\lwg:48\l"]; +node0266 -- node0267 +node0267[label="id:267\lwg:31\l"]; +node0267 -- node0268 +node0267 -- node0270 +node0268[label="id:268\lwg:37\l"]; +node0268 -- node0269 +node0269[label="id:269\lwg:47\l"]; +node0270[label="id:270\lwg:44\l"]; +node0270 -- node0271 +node0271[label="id:271\lwg:12\l"]; +node0272[label="id:272\lwg:39\l"]; +node0272 -- node0273 +node0272 -- node0278 +node0272 -- node0283 +node0272 -- node0287 +node0273[label="id:273\lwg:40\l"]; +node0273 -- node0274 +node0273 -- node0275 +node0274[label="id:274\lwg:4\l"]; +node0275[label="id:275\lwg:34\l"]; +node0275 -- node0276 +node0275 -- node0277 +node0276[label="id:276\lwg:19\l"]; +node0277[label="id:277\lwg:9\l"]; +node0278[label="id:278\lwg:17\l"]; +node0278 -- node0279 +node0278 -- node0280 +node0279[label="id:279\lwg:24\l"]; +node0280[label="id:280\lwg:31\l"]; +node0280 -- node0281 +node0280 -- node0282 +node0281[label="id:281\lwg:9\l"]; +node0282[label="id:282\lwg:33\l"]; +node0283[label="id:283\lwg:6\l"]; +node0283 -- node0284 +node0284[label="id:284\lwg:19\l"]; +node0284 -- node0285 +node0285[label="id:285\lwg:5\l"]; +node0285 -- node0286 +node0286[label="id:286\lwg:11\l"]; +node0287[label="id:287\lwg:12\l"]; +node0287 -- node0288 +node0287 -- node0290 +node0287 -- node0292 +node0288[label="id:288\lwg:6\l"]; +node0288 -- node0289 +node0289[label="id:289\lwg:20\l"]; +node0290[label="id:290\lwg:11\l"]; +node0290 -- node0291 +node0291[label="id:291\lwg:10\l"]; +node0292[label="id:292\lwg:10\l"]; +node0293[label="id:293\lwg:15\l"]; +node0293 -- node0294 +node0293 -- node0303 +node0294[label="id:294\lwg:12\l"]; +node0294 -- node0295 +node0294 -- node0296 +node0294 -- node0299 +node0295[label="id:295\lwg:39\l"]; +node0296[label="id:296\lwg:45\l"]; +node0296 -- node0297 +node0297[label="id:297\lwg:25\l"]; +node0297 -- node0298 +node0298[label="id:298\lwg:41\l"]; +node0299[label="id:299\lwg:50\l"]; +node0299 -- node0300 +node0299 -- node0301 +node0300[label="id:300\lwg:34\l"]; +node0301[label="id:301\lwg:21\l"]; +node0301 -- node0302 +node0302[label="id:302\lwg:22\l"]; +node0303[label="id:303\lwg:45\l"]; +node0304[label="id:304\lwg:39\l"]; +node0304 -- node0305 +node0304 -- node0347 +node0304 -- node0354 +node0304 -- node0355 +node0304 -- node0370 +node0305[label="id:305\lwg:38\l"]; +node0305 -- node0306 +node0305 -- node0307 +node0305 -- node0316 +node0305 -- node0329 +node0305 -- node0335 +node0306[label="id:306\lwg:19\l"]; +node0307[label="id:307\lwg:32\l"]; +node0307 -- node0308 +node0308[label="id:308\lwg:17\l"]; +node0308 -- node0309 +node0308 -- node0310 +node0308 -- node0312 +node0309[label="id:309\lwg:5\l"]; +node0310[label="id:310\lwg:38\l"]; +node0310 -- node0311 +node0311[label="id:311\lwg:24\l"]; +node0312[label="id:312\lwg:42\l"]; +node0312 -- node0313 +node0312 -- node0315 +node0313[label="id:313\lwg:14\l"]; +node0313 -- node0314 +node0314[label="id:314\lwg:30\l"]; +node0315[label="id:315\lwg:41\l"]; +node0316[label="id:316\lwg:17\l"]; +node0316 -- node0317 +node0316 -- node0324 +node0317[label="id:317\lwg:8\l"]; +node0317 -- node0318 +node0317 -- node0323 +node0318[label="id:318\lwg:49\l"]; +node0318 -- node0319 +node0318 -- node0321 +node0319[label="id:319\lwg:16\l"]; +node0319 -- node0320 +node0320[label="id:320\lwg:18\l"]; +node0321[label="id:321\lwg:40\l"]; +node0321 -- node0322 +node0322[label="id:322\lwg:2\l"]; +node0323[label="id:323\lwg:15\l"]; +node0324[label="id:324\lwg:21\l"]; +node0324 -- node0325 +node0325[label="id:325\lwg:48\l"]; +node0325 -- node0326 +node0325 -- node0328 +node0326[label="id:326\lwg:13\l"]; +node0326 -- node0327 +node0327[label="id:327\lwg:44\l"]; +node0328[label="id:328\lwg:21\l"]; +node0329[label="id:329\lwg:38\l"]; +node0329 -- node0330 +node0330[label="id:330\lwg:20\l"]; +node0330 -- node0331 +node0331[label="id:331\lwg:16\l"]; +node0331 -- node0332 +node0331 -- node0334 +node0332[label="id:332\lwg:43\l"]; +node0332 -- node0333 +node0333[label="id:333\lwg:27\l"]; +node0334[label="id:334\lwg:29\l"]; +node0335[label="id:335\lwg:32\l"]; +node0335 -- node0336 +node0335 -- node0339 +node0335 -- node0342 +node0336[label="id:336\lwg:49\l"]; +node0336 -- node0337 +node0337[label="id:337\lwg:33\l"]; +node0337 -- node0338 +node0338[label="id:338\lwg:44\l"]; +node0339[label="id:339\lwg:20\l"]; +node0339 -- node0340 +node0339 -- node0341 +node0340[label="id:340\lwg:19\l"]; +node0341[label="id:341\lwg:26\l"]; +node0342[label="id:342\lwg:40\l"]; +node0342 -- node0343 +node0342 -- node0346 +node0343[label="id:343\lwg:39\l"]; +node0343 -- node0344 +node0344[label="id:344\lwg:28\l"]; +node0344 -- node0345 +node0345[label="id:345\lwg:13\l"]; +node0346[label="id:346\lwg:4\l"]; +node0347[label="id:347\lwg:36\l"]; +node0347 -- node0348 +node0348[label="id:348\lwg:4\l"]; +node0348 -- node0349 +node0348 -- node0351 +node0349[label="id:349\lwg:41\l"]; +node0349 -- node0350 +node0350[label="id:350\lwg:7\l"]; +node0351[label="id:351\lwg:29\l"]; +node0351 -- node0352 +node0352[label="id:352\lwg:43\l"]; +node0352 -- node0353 +node0353[label="id:353\lwg:8\l"]; +node0354[label="id:354\lwg:11\l"]; +node0355[label="id:355\lwg:6\l"]; +node0355 -- node0356 +node0355 -- node0357 +node0356[label="id:356\lwg:48\l"]; +node0357[label="id:357\lwg:14\l"]; +node0357 -- node0358 +node0357 -- node0364 +node0358[label="id:358\lwg:2\l"]; +node0358 -- node0359 +node0358 -- node0363 +node0359[label="id:359\lwg:50\l"]; +node0359 -- node0360 +node0359 -- node0361 +node0360[label="id:360\lwg:30\l"]; +node0361[label="id:361\lwg:27\l"]; +node0361 -- node0362 +node0362[label="id:362\lwg:43\l"]; +node0363[label="id:363\lwg:33\l"]; +node0364[label="id:364\lwg:25\l"]; +node0364 -- node0365 +node0364 -- node0366 +node0364 -- node0367 +node0365[label="id:365\lwg:32\l"]; +node0366[label="id:366\lwg:45\l"]; +node0367[label="id:367\lwg:38\l"]; +node0367 -- node0368 +node0367 -- node0369 +node0368[label="id:368\lwg:25\l"]; +node0369[label="id:369\lwg:29\l"]; +node0370[label="id:370\lwg:26\l"]; +node0370 -- node0371 +node0370 -- node0385 +node0370 -- node0386 +node0370 -- node0394 +node0371[label="id:371\lwg:20\l"]; +node0371 -- node0372 +node0371 -- node0373 +node0371 -- node0380 +node0371 -- node0381 +node0372[label="id:372\lwg:17\l"]; +node0373[label="id:373\lwg:11\l"]; +node0373 -- node0374 +node0373 -- node0379 +node0374[label="id:374\lwg:36\l"]; +node0374 -- node0375 +node0374 -- node0377 +node0375[label="id:375\lwg:50\l"]; +node0375 -- node0376 +node0376[label="id:376\lwg:23\l"]; +node0377[label="id:377\lwg:1\l"]; +node0377 -- node0378 +node0378[label="id:378\lwg:41\l"]; +node0379[label="id:379\lwg:14\l"]; +node0380[label="id:380\lwg:8\l"]; +node0381[label="id:381\lwg:50\l"]; +node0381 -- node0382 +node0381 -- node0384 +node0382[label="id:382\lwg:9\l"]; +node0382 -- node0383 +node0383[label="id:383\lwg:42\l"]; +node0384[label="id:384\lwg:36\l"]; +node0385[label="id:385\lwg:21\l"]; +node0386[label="id:386\lwg:7\l"]; +node0386 -- node0387 +node0386 -- node0393 +node0387[label="id:387\lwg:35\l"]; +node0387 -- node0388 +node0387 -- node0389 +node0387 -- node0392 +node0388[label="id:388\lwg:26\l"]; +node0389[label="id:389\lwg:45\l"]; +node0389 -- node0390 +node0390[label="id:390\lwg:6\l"]; +node0390 -- node0391 +node0391[label="id:391\lwg:31\l"]; +node0392[label="id:392\lwg:26\l"]; +node0393[label="id:393\lwg:46\l"]; +node0394[label="id:394\lwg:17\l"]; +node0394 -- node0395 +node0394 -- node0401 +node0395[label="id:395\lwg:35\l"]; +node0395 -- node0396 +node0395 -- node0399 +node0396[label="id:396\lwg:6\l"]; +node0396 -- node0397 +node0397[label="id:397\lwg:27\l"]; +node0397 -- node0398 +node0398[label="id:398\lwg:22\l"]; +node0399[label="id:399\lwg:50\l"]; +node0399 -- node0400 +node0400[label="id:400\lwg:41\l"]; +node0401[label="id:401\lwg:21\l"]; +node0401 -- node0402 +node0402[label="id:402\lwg:14\l"]; +node0402 -- node0403 +node0403[label="id:403\lwg:21\l"]; +node0404[label="id:404\lwg:3\l"]; +node0405[label="id:405\lwg:4\l"]; +node0406[label="id:406\lwg:15\l"]; +node0406 -- node0407 +node0406 -- node0408 +node0406 -- node0409 +node0406 -- node0525 +node0406 -- node0647 +node0407[label="id:407\lwg:37\l"]; +node0408[label="id:408\lwg:16\l"]; +node0409[label="id:409\lwg:7\l"]; +node0409 -- node0410 +node0409 -- node0427 +node0409 -- node0487 +node0409 -- node0490 +node0410[label="id:410\lwg:43\l"]; +node0410 -- node0411 +node0410 -- node0420 +node0411[label="id:411\lwg:8\l"]; +node0411 -- node0412 +node0411 -- node0417 +node0412[label="id:412\lwg:26\l"]; +node0412 -- node0413 +node0413[label="id:413\lwg:15\l"]; +node0413 -- node0414 +node0413 -- node0416 +node0414[label="id:414\lwg:5\l"]; +node0414 -- node0415 +node0415[label="id:415\lwg:6\l"]; +node0416[label="id:416\lwg:37\l"]; +node0417[label="id:417\lwg:43\l"]; +node0417 -- node0418 +node0417 -- node0419 +node0418[label="id:418\lwg:35\l"]; +node0419[label="id:419\lwg:43\l"]; +node0420[label="id:420\lwg:32\l"]; +node0420 -- node0421 +node0420 -- node0423 +node0421[label="id:421\lwg:47\l"]; +node0421 -- node0422 +node0422[label="id:422\lwg:32\l"]; +node0423[label="id:423\lwg:37\l"]; +node0423 -- node0424 +node0424[label="id:424\lwg:17\l"]; +node0424 -- node0425 +node0424 -- node0426 +node0425[label="id:425\lwg:31\l"]; +node0426[label="id:426\lwg:38\l"]; +node0427[label="id:427\lwg:10\l"]; +node0427 -- node0428 +node0427 -- node0447 +node0427 -- node0457 +node0427 -- node0481 +node0428[label="id:428\lwg:25\l"]; +node0428 -- node0429 +node0428 -- node0440 +node0429[label="id:429\lwg:12\l"]; +node0429 -- node0430 +node0429 -- node0434 +node0429 -- node0438 +node0430[label="id:430\lwg:41\l"]; +node0430 -- node0431 +node0430 -- node0433 +node0431[label="id:431\lwg:23\l"]; +node0431 -- node0432 +node0432[label="id:432\lwg:48\l"]; +node0433[label="id:433\lwg:31\l"]; +node0434[label="id:434\lwg:29\l"]; +node0434 -- node0435 +node0434 -- node0436 +node0435[label="id:435\lwg:19\l"]; +node0436[label="id:436\lwg:21\l"]; +node0436 -- node0437 +node0437[label="id:437\lwg:7\l"]; +node0438[label="id:438\lwg:1\l"]; +node0438 -- node0439 +node0439[label="id:439\lwg:50\l"]; +node0440[label="id:440\lwg:38\l"]; +node0440 -- node0441 +node0440 -- node0444 +node0441[label="id:441\lwg:32\l"]; +node0441 -- node0442 +node0441 -- node0443 +node0442[label="id:442\lwg:23\l"]; +node0443[label="id:443\lwg:39\l"]; +node0444[label="id:444\lwg:19\l"]; +node0444 -- node0445 +node0444 -- node0446 +node0445[label="id:445\lwg:25\l"]; +node0446[label="id:446\lwg:22\l"]; +node0447[label="id:447\lwg:40\l"]; +node0447 -- node0448 +node0447 -- node0449 +node0447 -- node0454 +node0448[label="id:448\lwg:15\l"]; +node0449[label="id:449\lwg:2\l"]; +node0449 -- node0450 +node0449 -- node0451 +node0450[label="id:450\lwg:45\l"]; +node0451[label="id:451\lwg:7\l"]; +node0451 -- node0452 +node0451 -- node0453 +node0452[label="id:452\lwg:40\l"]; +node0453[label="id:453\lwg:18\l"]; +node0454[label="id:454\lwg:8\l"]; +node0454 -- node0455 +node0455[label="id:455\lwg:12\l"]; +node0455 -- node0456 +node0456[label="id:456\lwg:50\l"]; +node0457[label="id:457\lwg:23\l"]; +node0457 -- node0458 +node0457 -- node0472 +node0458[label="id:458\lwg:38\l"]; +node0458 -- node0459 +node0458 -- node0464 +node0458 -- node0469 +node0459[label="id:459\lwg:20\l"]; +node0459 -- node0460 +node0459 -- node0462 +node0460[label="id:460\lwg:13\l"]; +node0460 -- node0461 +node0461[label="id:461\lwg:18\l"]; +node0462[label="id:462\lwg:46\l"]; +node0462 -- node0463 +node0463[label="id:463\lwg:6\l"]; +node0464[label="id:464\lwg:30\l"]; +node0464 -- node0465 +node0464 -- node0467 +node0465[label="id:465\lwg:6\l"]; +node0465 -- node0466 +node0466[label="id:466\lwg:32\l"]; +node0467[label="id:467\lwg:39\l"]; +node0467 -- node0468 +node0468[label="id:468\lwg:25\l"]; +node0469[label="id:469\lwg:14\l"]; +node0469 -- node0470 +node0470[label="id:470\lwg:25\l"]; +node0470 -- node0471 +node0471[label="id:471\lwg:30\l"]; +node0472[label="id:472\lwg:20\l"]; +node0472 -- node0473 +node0472 -- node0475 +node0472 -- node0477 +node0473[label="id:473\lwg:49\l"]; +node0473 -- node0474 +node0474[label="id:474\lwg:12\l"]; +node0475[label="id:475\lwg:14\l"]; +node0475 -- node0476 +node0476[label="id:476\lwg:15\l"]; +node0477[label="id:477\lwg:12\l"]; +node0477 -- node0478 +node0477 -- node0480 +node0478[label="id:478\lwg:40\l"]; +node0478 -- node0479 +node0479[label="id:479\lwg:21\l"]; +node0480[label="id:480\lwg:29\l"]; +node0481[label="id:481\lwg:45\l"]; +node0481 -- node0482 +node0482[label="id:482\lwg:40\l"]; +node0482 -- node0483 +node0483[label="id:483\lwg:34\l"]; +node0483 -- node0484 +node0483 -- node0486 +node0484[label="id:484\lwg:40\l"]; +node0484 -- node0485 +node0485[label="id:485\lwg:47\l"]; +node0486[label="id:486\lwg:23\l"]; +node0487[label="id:487\lwg:42\l"]; +node0487 -- node0488 +node0488[label="id:488\lwg:27\l"]; +node0488 -- node0489 +node0489[label="id:489\lwg:48\l"]; +node0490[label="id:490\lwg:12\l"]; +node0490 -- node0491 +node0490 -- node0492 +node0490 -- node0496 +node0490 -- node0518 +node0491[label="id:491\lwg:17\l"]; +node0492[label="id:492\lwg:42\l"]; +node0492 -- node0493 +node0493[label="id:493\lwg:38\l"]; +node0493 -- node0494 +node0494[label="id:494\lwg:1\l"]; +node0494 -- node0495 +node0495[label="id:495\lwg:2\l"]; +node0496[label="id:496\lwg:39\l"]; +node0496 -- node0497 +node0496 -- node0501 +node0496 -- node0511 +node0497[label="id:497\lwg:42\l"]; +node0497 -- node0498 +node0498[label="id:498\lwg:30\l"]; +node0498 -- node0499 +node0498 -- node0500 +node0499[label="id:499\lwg:44\l"]; +node0500[label="id:500\lwg:23\l"]; +node0501[label="id:501\lwg:39\l"]; +node0501 -- node0502 +node0501 -- node0503 +node0501 -- node0508 +node0502[label="id:502\lwg:20\l"]; +node0503[label="id:503\lwg:39\l"]; +node0503 -- node0504 +node0503 -- node0506 +node0504[label="id:504\lwg:25\l"]; +node0504 -- node0505 +node0505[label="id:505\lwg:38\l"]; +node0506[label="id:506\lwg:49\l"]; +node0506 -- node0507 +node0507[label="id:507\lwg:14\l"]; +node0508[label="id:508\lwg:38\l"]; +node0508 -- node0509 +node0509[label="id:509\lwg:25\l"]; +node0509 -- node0510 +node0510[label="id:510\lwg:14\l"]; +node0511[label="id:511\lwg:19\l"]; +node0511 -- node0512 +node0511 -- node0515 +node0511 -- node0517 +node0512[label="id:512\lwg:23\l"]; +node0512 -- node0513 +node0513[label="id:513\lwg:31\l"]; +node0513 -- node0514 +node0514[label="id:514\lwg:37\l"]; +node0515[label="id:515\lwg:24\l"]; +node0515 -- node0516 +node0516[label="id:516\lwg:16\l"]; +node0517[label="id:517\lwg:8\l"]; +node0518[label="id:518\lwg:45\l"]; +node0518 -- node0519 +node0518 -- node0520 +node0518 -- node0521 +node0518 -- node0523 +node0519[label="id:519\lwg:32\l"]; +node0520[label="id:520\lwg:37\l"]; +node0521[label="id:521\lwg:6\l"]; +node0521 -- node0522 +node0522[label="id:522\lwg:27\l"]; +node0523[label="id:523\lwg:29\l"]; +node0523 -- node0524 +node0524[label="id:524\lwg:23\l"]; +node0525[label="id:525\lwg:2\l"]; +node0525 -- node0526 +node0525 -- node0555 +node0525 -- node0607 +node0525 -- node0627 +node0525 -- node0628 +node0526[label="id:526\lwg:30\l"]; +node0526 -- node0527 +node0526 -- node0533 +node0526 -- node0543 +node0527[label="id:527\lwg:39\l"]; +node0527 -- node0528 +node0528[label="id:528\lwg:31\l"]; +node0528 -- node0529 +node0529[label="id:529\lwg:5\l"]; +node0529 -- node0530 +node0529 -- node0531 +node0530[label="id:530\lwg:45\l"]; +node0531[label="id:531\lwg:30\l"]; +node0531 -- node0532 +node0532[label="id:532\lwg:40\l"]; +node0533[label="id:533\lwg:46\l"]; +node0533 -- node0534 +node0533 -- node0541 +node0533 -- node0542 +node0534[label="id:534\lwg:37\l"]; +node0534 -- node0535 +node0534 -- node0537 +node0534 -- node0538 +node0535[label="id:535\lwg:4\l"]; +node0535 -- node0536 +node0536[label="id:536\lwg:50\l"]; +node0537[label="id:537\lwg:10\l"]; +node0538[label="id:538\lwg:31\l"]; +node0538 -- node0539 +node0539[label="id:539\lwg:42\l"]; +node0539 -- node0540 +node0540[label="id:540\lwg:42\l"]; +node0541[label="id:541\lwg:40\l"]; +node0542[label="id:542\lwg:16\l"]; +node0543[label="id:543\lwg:22\l"]; +node0543 -- node0544 +node0543 -- node0551 +node0543 -- node0553 +node0543 -- node0554 +node0544[label="id:544\lwg:50\l"]; +node0544 -- node0545 +node0544 -- node0549 +node0545[label="id:545\lwg:17\l"]; +node0545 -- node0546 +node0545 -- node0548 +node0546[label="id:546\lwg:5\l"]; +node0546 -- node0547 +node0547[label="id:547\lwg:5\l"]; +node0548[label="id:548\lwg:37\l"]; +node0549[label="id:549\lwg:30\l"]; +node0549 -- node0550 +node0550[label="id:550\lwg:31\l"]; +node0551[label="id:551\lwg:48\l"]; +node0551 -- node0552 +node0552[label="id:552\lwg:45\l"]; +node0553[label="id:553\lwg:8\l"]; +node0554[label="id:554\lwg:48\l"]; +node0555[label="id:555\lwg:29\l"]; +node0555 -- node0556 +node0555 -- node0574 +node0555 -- node0582 +node0555 -- node0595 +node0555 -- node0605 +node0556[label="id:556\lwg:44\l"]; +node0556 -- node0557 +node0556 -- node0563 +node0556 -- node0568 +node0557[label="id:557\lwg:9\l"]; +node0557 -- node0558 +node0558[label="id:558\lwg:49\l"]; +node0558 -- node0559 +node0558 -- node0561 +node0559[label="id:559\lwg:8\l"]; +node0559 -- node0560 +node0560[label="id:560\lwg:9\l"]; +node0561[label="id:561\lwg:44\l"]; +node0561 -- node0562 +node0562[label="id:562\lwg:24\l"]; +node0563[label="id:563\lwg:11\l"]; +node0563 -- node0564 +node0564[label="id:564\lwg:2\l"]; +node0564 -- node0565 +node0564 -- node0566 +node0565[label="id:565\lwg:34\l"]; +node0566[label="id:566\lwg:26\l"]; +node0566 -- node0567 +node0567[label="id:567\lwg:13\l"]; +node0568[label="id:568\lwg:41\l"]; +node0568 -- node0569 +node0568 -- node0572 +node0568 -- node0573 +node0569[label="id:569\lwg:46\l"]; +node0569 -- node0570 +node0570[label="id:570\lwg:20\l"]; +node0570 -- node0571 +node0571[label="id:571\lwg:28\l"]; +node0572[label="id:572\lwg:43\l"]; +node0573[label="id:573\lwg:26\l"]; +node0574[label="id:574\lwg:21\l"]; +node0574 -- node0575 +node0574 -- node0580 +node0575[label="id:575\lwg:42\l"]; +node0575 -- node0576 +node0575 -- node0577 +node0576[label="id:576\lwg:11\l"]; +node0577[label="id:577\lwg:44\l"]; +node0577 -- node0578 +node0578[label="id:578\lwg:35\l"]; +node0578 -- node0579 +node0579[label="id:579\lwg:45\l"]; +node0580[label="id:580\lwg:46\l"]; +node0580 -- node0581 +node0581[label="id:581\lwg:19\l"]; +node0582[label="id:582\lwg:13\l"]; +node0582 -- node0583 +node0582 -- node0593 +node0583[label="id:583\lwg:44\l"]; +node0583 -- node0584 +node0583 -- node0588 +node0584[label="id:584\lwg:3\l"]; +node0584 -- node0585 +node0584 -- node0586 +node0585[label="id:585\lwg:47\l"]; +node0586[label="id:586\lwg:16\l"]; +node0586 -- node0587 +node0587[label="id:587\lwg:39\l"]; +node0588[label="id:588\lwg:14\l"]; +node0588 -- node0589 +node0588 -- node0591 +node0589[label="id:589\lwg:2\l"]; +node0589 -- node0590 +node0590[label="id:590\lwg:1\l"]; +node0591[label="id:591\lwg:15\l"]; +node0591 -- node0592 +node0592[label="id:592\lwg:30\l"]; +node0593[label="id:593\lwg:48\l"]; +node0593 -- node0594 +node0594[label="id:594\lwg:15\l"]; +node0595[label="id:595\lwg:3\l"]; +node0595 -- node0596 +node0595 -- node0597 +node0595 -- node0598 +node0596[label="id:596\lwg:23\l"]; +node0597[label="id:597\lwg:35\l"]; +node0598[label="id:598\lwg:6\l"]; +node0598 -- node0599 +node0598 -- node0600 +node0599[label="id:599\lwg:44\l"]; +node0600[label="id:600\lwg:21\l"]; +node0600 -- node0601 +node0600 -- node0603 +node0601[label="id:601\lwg:34\l"]; +node0601 -- node0602 +node0602[label="id:602\lwg:15\l"]; +node0603[label="id:603\lwg:48\l"]; +node0603 -- node0604 +node0604[label="id:604\lwg:37\l"]; +node0605[label="id:605\lwg:14\l"]; +node0605 -- node0606 +node0606[label="id:606\lwg:47\l"]; +node0607[label="id:607\lwg:3\l"]; +node0607 -- node0608 +node0607 -- node0609 +node0607 -- node0616 +node0608[label="id:608\lwg:37\l"]; +node0609[label="id:609\lwg:44\l"]; +node0609 -- node0610 +node0610[label="id:610\lwg:45\l"]; +node0610 -- node0611 +node0610 -- node0614 +node0611[label="id:611\lwg:13\l"]; +node0611 -- node0612 +node0612[label="id:612\lwg:23\l"]; +node0612 -- node0613 +node0613[label="id:613\lwg:8\l"]; +node0614[label="id:614\lwg:30\l"]; +node0614 -- node0615 +node0615[label="id:615\lwg:37\l"]; +node0616[label="id:616\lwg:44\l"]; +node0616 -- node0617 +node0617[label="id:617\lwg:40\l"]; +node0617 -- node0618 +node0617 -- node0622 +node0617 -- node0623 +node0618[label="id:618\lwg:43\l"]; +node0618 -- node0619 +node0618 -- node0621 +node0619[label="id:619\lwg:38\l"]; +node0619 -- node0620 +node0620[label="id:620\lwg:41\l"]; +node0621[label="id:621\lwg:22\l"]; +node0622[label="id:622\lwg:30\l"]; +node0623[label="id:623\lwg:14\l"]; +node0623 -- node0624 +node0623 -- node0626 +node0624[label="id:624\lwg:26\l"]; +node0624 -- node0625 +node0625[label="id:625\lwg:21\l"]; +node0626[label="id:626\lwg:5\l"]; +node0627[label="id:627\lwg:42\l"]; +node0628[label="id:628\lwg:34\l"]; +node0628 -- node0629 +node0628 -- node0638 +node0629[label="id:629\lwg:6\l"]; +node0629 -- node0630 +node0629 -- node0631 +node0629 -- node0637 +node0630[label="id:630\lwg:4\l"]; +node0631[label="id:631\lwg:19\l"]; +node0631 -- node0632 +node0631 -- node0633 +node0631 -- node0636 +node0632[label="id:632\lwg:16\l"]; +node0633[label="id:633\lwg:7\l"]; +node0633 -- node0634 +node0634[label="id:634\lwg:49\l"]; +node0634 -- node0635 +node0635[label="id:635\lwg:41\l"]; +node0636[label="id:636\lwg:47\l"]; +node0637[label="id:637\lwg:27\l"]; +node0638[label="id:638\lwg:37\l"]; +node0638 -- node0639 +node0638 -- node0640 +node0638 -- node0644 +node0639[label="id:639\lwg:48\l"]; +node0640[label="id:640\lwg:49\l"]; +node0640 -- node0641 +node0640 -- node0642 +node0640 -- node0643 +node0641[label="id:641\lwg:36\l"]; +node0642[label="id:642\lwg:3\l"]; +node0643[label="id:643\lwg:33\l"]; +node0644[label="id:644\lwg:28\l"]; +node0644 -- node0645 +node0645[label="id:645\lwg:5\l"]; +node0645 -- node0646 +node0646[label="id:646\lwg:34\l"]; +node0647[label="id:647\lwg:27\l"]; +node0647 -- node0648 +node0647 -- node0649 +node0647 -- node0704 +node0647 -- node0743 +node0647 -- node0765 +node0648[label="id:648\lwg:34\l"]; +node0649[label="id:649\lwg:8\l"]; +node0649 -- node0650 +node0649 -- node0677 +node0649 -- node0693 +node0650[label="id:650\lwg:30\l"]; +node0650 -- node0651 +node0650 -- node0652 +node0650 -- node0662 +node0650 -- node0672 +node0651[label="id:651\lwg:25\l"]; +node0652[label="id:652\lwg:11\l"]; +node0652 -- node0653 +node0652 -- node0654 +node0652 -- node0659 +node0653[label="id:653\lwg:8\l"]; +node0654[label="id:654\lwg:44\l"]; +node0654 -- node0655 +node0654 -- node0657 +node0655[label="id:655\lwg:12\l"]; +node0655 -- node0656 +node0656[label="id:656\lwg:23\l"]; +node0657[label="id:657\lwg:47\l"]; +node0657 -- node0658 +node0658[label="id:658\lwg:26\l"]; +node0659[label="id:659\lwg:17\l"]; +node0659 -- node0660 +node0659 -- node0661 +node0660[label="id:660\lwg:21\l"]; +node0661[label="id:661\lwg:33\l"]; +node0662[label="id:662\lwg:47\l"]; +node0662 -- node0663 +node0662 -- node0668 +node0662 -- node0671 +node0663[label="id:663\lwg:4\l"]; +node0663 -- node0664 +node0663 -- node0666 +node0664[label="id:664\lwg:47\l"]; +node0664 -- node0665 +node0665[label="id:665\lwg:16\l"]; +node0666[label="id:666\lwg:9\l"]; +node0666 -- node0667 +node0667[label="id:667\lwg:5\l"]; +node0668[label="id:668\lwg:44\l"]; +node0668 -- node0669 +node0668 -- node0670 +node0669[label="id:669\lwg:21\l"]; +node0670[label="id:670\lwg:20\l"]; +node0671[label="id:671\lwg:30\l"]; +node0672[label="id:672\lwg:32\l"]; +node0672 -- node0673 +node0672 -- node0675 +node0672 -- node0676 +node0673[label="id:673\lwg:21\l"]; +node0673 -- node0674 +node0674[label="id:674\lwg:9\l"]; +node0675[label="id:675\lwg:10\l"]; +node0676[label="id:676\lwg:11\l"]; +node0677[label="id:677\lwg:34\l"]; +node0677 -- node0678 +node0677 -- node0681 +node0677 -- node0692 +node0678[label="id:678\lwg:7\l"]; +node0678 -- node0679 +node0678 -- node0680 +node0679[label="id:679\lwg:40\l"]; +node0680[label="id:680\lwg:47\l"]; +node0681[label="id:681\lwg:30\l"]; +node0681 -- node0682 +node0681 -- node0685 +node0681 -- node0690 +node0682[label="id:682\lwg:48\l"]; +node0682 -- node0683 +node0682 -- node0684 +node0683[label="id:683\lwg:30\l"]; +node0684[label="id:684\lwg:49\l"]; +node0685[label="id:685\lwg:31\l"]; +node0685 -- node0686 +node0685 -- node0688 +node0686[label="id:686\lwg:35\l"]; +node0686 -- node0687 +node0687[label="id:687\lwg:13\l"]; +node0688[label="id:688\lwg:42\l"]; +node0688 -- node0689 +node0689[label="id:689\lwg:24\l"]; +node0690[label="id:690\lwg:23\l"]; +node0690 -- node0691 +node0691[label="id:691\lwg:30\l"]; +node0692[label="id:692\lwg:29\l"]; +node0693[label="id:693\lwg:43\l"]; +node0693 -- node0694 +node0693 -- node0695 +node0693 -- node0696 +node0693 -- node0697 +node0694[label="id:694\lwg:1\l"]; +node0695[label="id:695\lwg:40\l"]; +node0696[label="id:696\lwg:42\l"]; +node0697[label="id:697\lwg:8\l"]; +node0697 -- node0698 +node0697 -- node0702 +node0698[label="id:698\lwg:5\l"]; +node0698 -- node0699 +node0698 -- node0701 +node0699[label="id:699\lwg:33\l"]; +node0699 -- node0700 +node0700[label="id:700\lwg:40\l"]; +node0701[label="id:701\lwg:24\l"]; +node0702[label="id:702\lwg:24\l"]; +node0702 -- node0703 +node0703[label="id:703\lwg:39\l"]; +node0704[label="id:704\lwg:21\l"]; +node0704 -- node0705 +node0704 -- node0713 +node0704 -- node0714 +node0704 -- node0726 +node0705[label="id:705\lwg:16\l"]; +node0705 -- node0706 +node0706[label="id:706\lwg:47\l"]; +node0706 -- node0707 +node0706 -- node0708 +node0706 -- node0710 +node0707[label="id:707\lwg:28\l"]; +node0708[label="id:708\lwg:11\l"]; +node0708 -- node0709 +node0709[label="id:709\lwg:13\l"]; +node0710[label="id:710\lwg:5\l"]; +node0710 -- node0711 +node0711[label="id:711\lwg:14\l"]; +node0711 -- node0712 +node0712[label="id:712\lwg:23\l"]; +node0713[label="id:713\lwg:36\l"]; +node0714[label="id:714\lwg:8\l"]; +node0714 -- node0715 +node0715[label="id:715\lwg:34\l"]; +node0715 -- node0716 +node0715 -- node0718 +node0715 -- node0721 +node0716[label="id:716\lwg:30\l"]; +node0716 -- node0717 +node0717[label="id:717\lwg:22\l"]; +node0718[label="id:718\lwg:45\l"]; +node0718 -- node0719 +node0719[label="id:719\lwg:22\l"]; +node0719 -- node0720 +node0720[label="id:720\lwg:24\l"]; +node0721[label="id:721\lwg:11\l"]; +node0721 -- node0722 +node0721 -- node0724 +node0722[label="id:722\lwg:36\l"]; +node0722 -- node0723 +node0723[label="id:723\lwg:50\l"]; +node0724[label="id:724\lwg:10\l"]; +node0724 -- node0725 +node0725[label="id:725\lwg:11\l"]; +node0726[label="id:726\lwg:14\l"]; +node0726 -- node0727 +node0726 -- node0732 +node0726 -- node0740 +node0727[label="id:727\lwg:11\l"]; +node0727 -- node0728 +node0728[label="id:728\lwg:46\l"]; +node0728 -- node0729 +node0728 -- node0731 +node0729[label="id:729\lwg:14\l"]; +node0729 -- node0730 +node0730[label="id:730\lwg:15\l"]; +node0731[label="id:731\lwg:2\l"]; +node0732[label="id:732\lwg:6\l"]; +node0732 -- node0733 +node0732 -- node0738 +node0732 -- node0739 +node0733[label="id:733\lwg:1\l"]; +node0733 -- node0734 +node0733 -- node0736 +node0734[label="id:734\lwg:35\l"]; +node0734 -- node0735 +node0735[label="id:735\lwg:17\l"]; +node0736[label="id:736\lwg:12\l"]; +node0736 -- node0737 +node0737[label="id:737\lwg:31\l"]; +node0738[label="id:738\lwg:15\l"]; +node0739[label="id:739\lwg:47\l"]; +node0740[label="id:740\lwg:44\l"]; +node0740 -- node0741 +node0741[label="id:741\lwg:40\l"]; +node0741 -- node0742 +node0742[label="id:742\lwg:34\l"]; +node0743[label="id:743\lwg:44\l"]; +node0743 -- node0744 +node0744[label="id:744\lwg:48\l"]; +node0744 -- node0745 +node0744 -- node0754 +node0744 -- node0759 +node0745[label="id:745\lwg:34\l"]; +node0745 -- node0746 +node0745 -- node0751 +node0746[label="id:746\lwg:8\l"]; +node0746 -- node0747 +node0746 -- node0749 +node0747[label="id:747\lwg:10\l"]; +node0747 -- node0748 +node0748[label="id:748\lwg:13\l"]; +node0749[label="id:749\lwg:14\l"]; +node0749 -- node0750 +node0750[label="id:750\lwg:35\l"]; +node0751[label="id:751\lwg:7\l"]; +node0751 -- node0752 +node0752[label="id:752\lwg:9\l"]; +node0752 -- node0753 +node0753[label="id:753\lwg:45\l"]; +node0754[label="id:754\lwg:21\l"]; +node0754 -- node0755 +node0754 -- node0758 +node0755[label="id:755\lwg:1\l"]; +node0755 -- node0756 +node0756[label="id:756\lwg:1\l"]; +node0756 -- node0757 +node0757[label="id:757\lwg:22\l"]; +node0758[label="id:758\lwg:41\l"]; +node0759[label="id:759\lwg:14\l"]; +node0759 -- node0760 +node0759 -- node0763 +node0760[label="id:760\lwg:25\l"]; +node0760 -- node0761 +node0761[label="id:761\lwg:4\l"]; +node0761 -- node0762 +node0762[label="id:762\lwg:37\l"]; +node0763[label="id:763\lwg:48\l"]; +node0763 -- node0764 +node0764[label="id:764\lwg:26\l"]; +node0765[label="id:765\lwg:47\l"]; +node0765 -- node0766 +node0765 -- node0790 +node0765 -- node0803 +node0766[label="id:766\lwg:44\l"]; +node0766 -- node0767 +node0766 -- node0770 +node0766 -- node0773 +node0766 -- node0781 +node0767[label="id:767\lwg:7\l"]; +node0767 -- node0768 +node0767 -- node0769 +node0768[label="id:768\lwg:44\l"]; +node0769[label="id:769\lwg:29\l"]; +node0770[label="id:770\lwg:47\l"]; +node0770 -- node0771 +node0771[label="id:771\lwg:29\l"]; +node0771 -- node0772 +node0772[label="id:772\lwg:20\l"]; +node0773[label="id:773\lwg:34\l"]; +node0773 -- node0774 +node0773 -- node0777 +node0773 -- node0780 +node0774[label="id:774\lwg:18\l"]; +node0774 -- node0775 +node0775[label="id:775\lwg:2\l"]; +node0775 -- node0776 +node0776[label="id:776\lwg:49\l"]; +node0777[label="id:777\lwg:28\l"]; +node0777 -- node0778 +node0777 -- node0779 +node0778[label="id:778\lwg:19\l"]; +node0779[label="id:779\lwg:37\l"]; +node0780[label="id:780\lwg:38\l"]; +node0781[label="id:781\lwg:3\l"]; +node0781 -- node0782 +node0781 -- node0785 +node0782[label="id:782\lwg:38\l"]; +node0782 -- node0783 +node0782 -- node0784 +node0783[label="id:783\lwg:37\l"]; +node0784[label="id:784\lwg:16\l"]; +node0785[label="id:785\lwg:48\l"]; +node0785 -- node0786 +node0785 -- node0788 +node0786[label="id:786\lwg:47\l"]; +node0786 -- node0787 +node0787[label="id:787\lwg:11\l"]; +node0788[label="id:788\lwg:29\l"]; +node0788 -- node0789 +node0789[label="id:789\lwg:27\l"]; +node0790[label="id:790\lwg:45\l"]; +node0790 -- node0791 +node0790 -- node0793 +node0791[label="id:791\lwg:41\l"]; +node0791 -- node0792 +node0792[label="id:792\lwg:32\l"]; +node0793[label="id:793\lwg:31\l"]; +node0793 -- node0794 +node0793 -- node0795 +node0793 -- node0799 +node0794[label="id:794\lwg:47\l"]; +node0795[label="id:795\lwg:43\l"]; +node0795 -- node0796 +node0795 -- node0798 +node0796[label="id:796\lwg:2\l"]; +node0796 -- node0797 +node0797[label="id:797\lwg:19\l"]; +node0798[label="id:798\lwg:10\l"]; +node0799[label="id:799\lwg:23\l"]; +node0799 -- node0800 +node0799 -- node0801 +node0800[label="id:800\lwg:23\l"]; +node0801[label="id:801\lwg:38\l"]; +node0801 -- node0802 +node0802[label="id:802\lwg:1\l"]; +node0803[label="id:803\lwg:34\l"]; +node0803 -- node0804 +node0803 -- node0813 +node0804[label="id:804\lwg:44\l"]; +node0804 -- node0805 +node0804 -- node0809 +node0805[label="id:805\lwg:26\l"]; +node0805 -- node0806 +node0805 -- node0808 +node0806[label="id:806\lwg:40\l"]; +node0806 -- node0807 +node0807[label="id:807\lwg:35\l"]; +node0808[label="id:808\lwg:38\l"]; +node0809[label="id:809\lwg:23\l"]; +node0809 -- node0810 +node0809 -- node0812 +node0810[label="id:810\lwg:34\l"]; +node0810 -- node0811 +node0811[label="id:811\lwg:19\l"]; +node0812[label="id:812\lwg:16\l"]; +node0813[label="id:813\lwg:25\l"]; +node0814[label="id:814\lwg:45\l"]; +node0814 -- node0815 +node0814 -- node0904 +node0815[label="id:815\lwg:1\l"]; +node0815 -- node0816 +node0815 -- node0837 +node0815 -- node0838 +node0815 -- node0880 +node0815 -- node0903 +node0816[label="id:816\lwg:22\l"]; +node0816 -- node0817 +node0816 -- node0822 +node0817[label="id:817\lwg:35\l"]; +node0817 -- node0818 +node0817 -- node0821 +node0818[label="id:818\lwg:38\l"]; +node0818 -- node0819 +node0819[label="id:819\lwg:2\l"]; +node0819 -- node0820 +node0820[label="id:820\lwg:32\l"]; +node0821[label="id:821\lwg:22\l"]; +node0822[label="id:822\lwg:46\l"]; +node0822 -- node0823 +node0822 -- node0832 +node0823[label="id:823\lwg:45\l"]; +node0823 -- node0824 +node0823 -- node0828 +node0823 -- node0829 +node0824[label="id:824\lwg:21\l"]; +node0824 -- node0825 +node0824 -- node0826 +node0825[label="id:825\lwg:20\l"]; +node0826[label="id:826\lwg:36\l"]; +node0826 -- node0827 +node0827[label="id:827\lwg:40\l"]; +node0828[label="id:828\lwg:29\l"]; +node0829[label="id:829\lwg:27\l"]; +node0829 -- node0830 +node0830[label="id:830\lwg:16\l"]; +node0830 -- node0831 +node0831[label="id:831\lwg:42\l"]; +node0832[label="id:832\lwg:16\l"]; +node0832 -- node0833 +node0832 -- node0836 +node0833[label="id:833\lwg:10\l"]; +node0833 -- node0834 +node0833 -- node0835 +node0834[label="id:834\lwg:50\l"]; +node0835[label="id:835\lwg:37\l"]; +node0836[label="id:836\lwg:41\l"]; +node0837[label="id:837\lwg:5\l"]; +node0838[label="id:838\lwg:16\l"]; +node0838 -- node0839 +node0838 -- node0861 +node0838 -- node0871 +node0839[label="id:839\lwg:25\l"]; +node0839 -- node0840 +node0839 -- node0843 +node0839 -- node0846 +node0839 -- node0853 +node0840[label="id:840\lwg:18\l"]; +node0840 -- node0841 +node0841[label="id:841\lwg:43\l"]; +node0841 -- node0842 +node0842[label="id:842\lwg:36\l"]; +node0843[label="id:843\lwg:5\l"]; +node0843 -- node0844 +node0844[label="id:844\lwg:1\l"]; +node0844 -- node0845 +node0845[label="id:845\lwg:42\l"]; +node0846[label="id:846\lwg:9\l"]; +node0846 -- node0847 +node0846 -- node0849 +node0846 -- node0851 +node0847[label="id:847\lwg:6\l"]; +node0847 -- node0848 +node0848[label="id:848\lwg:13\l"]; +node0849[label="id:849\lwg:31\l"]; +node0849 -- node0850 +node0850[label="id:850\lwg:29\l"]; +node0851[label="id:851\lwg:45\l"]; +node0851 -- node0852 +node0852[label="id:852\lwg:30\l"]; +node0853[label="id:853\lwg:9\l"]; +node0853 -- node0854 +node0853 -- node0856 +node0853 -- node0860 +node0854[label="id:854\lwg:1\l"]; +node0854 -- node0855 +node0855[label="id:855\lwg:35\l"]; +node0856[label="id:856\lwg:30\l"]; +node0856 -- node0857 +node0856 -- node0858 +node0857[label="id:857\lwg:21\l"]; +node0858[label="id:858\lwg:13\l"]; +node0858 -- node0859 +node0859[label="id:859\lwg:34\l"]; +node0860[label="id:860\lwg:8\l"]; +node0861[label="id:861\lwg:33\l"]; +node0861 -- node0862 +node0862[label="id:862\lwg:11\l"]; +node0862 -- node0863 +node0862 -- node0866 +node0862 -- node0869 +node0863[label="id:863\lwg:44\l"]; +node0863 -- node0864 +node0864[label="id:864\lwg:7\l"]; +node0864 -- node0865 +node0865[label="id:865\lwg:38\l"]; +node0866[label="id:866\lwg:46\l"]; +node0866 -- node0867 +node0867[label="id:867\lwg:6\l"]; +node0867 -- node0868 +node0868[label="id:868\lwg:35\l"]; +node0869[label="id:869\lwg:21\l"]; +node0869 -- node0870 +node0870[label="id:870\lwg:48\l"]; +node0871[label="id:871\lwg:3\l"]; +node0871 -- node0872 +node0871 -- node0873 +node0871 -- node0877 +node0871 -- node0879 +node0872[label="id:872\lwg:34\l"]; +node0873[label="id:873\lwg:44\l"]; +node0873 -- node0874 +node0873 -- node0876 +node0874[label="id:874\lwg:49\l"]; +node0874 -- node0875 +node0875[label="id:875\lwg:12\l"]; +node0876[label="id:876\lwg:5\l"]; +node0877[label="id:877\lwg:26\l"]; +node0877 -- node0878 +node0878[label="id:878\lwg:36\l"]; +node0879[label="id:879\lwg:41\l"]; +node0880[label="id:880\lwg:45\l"]; +node0880 -- node0881 +node0881[label="id:881\lwg:28\l"]; +node0881 -- node0882 +node0881 -- node0887 +node0881 -- node0898 +node0881 -- node0899 +node0882[label="id:882\lwg:15\l"]; +node0882 -- node0883 +node0883[label="id:883\lwg:14\l"]; +node0883 -- node0884 +node0883 -- node0886 +node0884[label="id:884\lwg:50\l"]; +node0884 -- node0885 +node0885[label="id:885\lwg:34\l"]; +node0886[label="id:886\lwg:41\l"]; +node0887[label="id:887\lwg:26\l"]; +node0887 -- node0888 +node0887 -- node0890 +node0887 -- node0894 +node0888[label="id:888\lwg:10\l"]; +node0888 -- node0889 +node0889[label="id:889\lwg:21\l"]; +node0890[label="id:890\lwg:50\l"]; +node0890 -- node0891 +node0890 -- node0892 +node0891[label="id:891\lwg:18\l"]; +node0892[label="id:892\lwg:30\l"]; +node0892 -- node0893 +node0893[label="id:893\lwg:23\l"]; +node0894[label="id:894\lwg:14\l"]; +node0894 -- node0895 +node0894 -- node0896 +node0895[label="id:895\lwg:8\l"]; +node0896[label="id:896\lwg:44\l"]; +node0896 -- node0897 +node0897[label="id:897\lwg:48\l"]; +node0898[label="id:898\lwg:22\l"]; +node0899[label="id:899\lwg:10\l"]; +node0899 -- node0900 +node0899 -- node0902 +node0900[label="id:900\lwg:49\l"]; +node0900 -- node0901 +node0901[label="id:901\lwg:20\l"]; +node0902[label="id:902\lwg:31\l"]; +node0903[label="id:903\lwg:13\l"]; +node0904[label="id:904\lwg:18\l"]; +node0904 -- node0905 +node0904 -- node0932 +node0904 -- node0978 +node0904 -- node1063 +node0904 -- node1125 +node0905[label="id:905\lwg:4\l"]; +node0905 -- node0906 +node0905 -- node0911 +node0905 -- node0928 +node0905 -- node0929 +node0905 -- node0930 +node0906[label="id:906\lwg:20\l"]; +node0906 -- node0907 +node0907[label="id:907\lwg:24\l"]; +node0907 -- node0908 +node0907 -- node0909 +node0907 -- node0910 +node0908[label="id:908\lwg:16\l"]; +node0909[label="id:909\lwg:16\l"]; +node0910[label="id:910\lwg:11\l"]; +node0911[label="id:911\lwg:39\l"]; +node0911 -- node0912 +node0911 -- node0913 +node0911 -- node0919 +node0911 -- node0922 +node0912[label="id:912\lwg:12\l"]; +node0913[label="id:913\lwg:17\l"]; +node0913 -- node0914 +node0914[label="id:914\lwg:50\l"]; +node0914 -- node0915 +node0914 -- node0917 +node0915[label="id:915\lwg:7\l"]; +node0915 -- node0916 +node0916[label="id:916\lwg:20\l"]; +node0917[label="id:917\lwg:40\l"]; +node0917 -- node0918 +node0918[label="id:918\lwg:23\l"]; +node0919[label="id:919\lwg:46\l"]; +node0919 -- node0920 +node0920[label="id:920\lwg:39\l"]; +node0920 -- node0921 +node0921[label="id:921\lwg:8\l"]; +node0922[label="id:922\lwg:24\l"]; +node0922 -- node0923 +node0923[label="id:923\lwg:11\l"]; +node0923 -- node0924 +node0923 -- node0926 +node0924[label="id:924\lwg:29\l"]; +node0924 -- node0925 +node0925[label="id:925\lwg:20\l"]; +node0926[label="id:926\lwg:2\l"]; +node0926 -- node0927 +node0927[label="id:927\lwg:48\l"]; +node0928[label="id:928\lwg:45\l"]; +node0929[label="id:929\lwg:1\l"]; +node0930[label="id:930\lwg:43\l"]; +node0930 -- node0931 +node0931[label="id:931\lwg:47\l"]; +node0932[label="id:932\lwg:34\l"]; +node0932 -- node0933 +node0932 -- node0934 +node0932 -- node0935 +node0932 -- node0959 +node0932 -- node0975 +node0933[label="id:933\lwg:18\l"]; +node0934[label="id:934\lwg:41\l"]; +node0935[label="id:935\lwg:47\l"]; +node0935 -- node0936 +node0935 -- node0942 +node0935 -- node0950 +node0935 -- node0954 +node0936[label="id:936\lwg:15\l"]; +node0936 -- node0937 +node0936 -- node0939 +node0936 -- node0940 +node0937[label="id:937\lwg:41\l"]; +node0937 -- node0938 +node0938[label="id:938\lwg:35\l"]; +node0939[label="id:939\lwg:30\l"]; +node0940[label="id:940\lwg:30\l"]; +node0940 -- node0941 +node0941[label="id:941\lwg:6\l"]; +node0942[label="id:942\lwg:7\l"]; +node0942 -- node0943 +node0942 -- node0946 +node0942 -- node0947 +node0943[label="id:943\lwg:1\l"]; +node0943 -- node0944 +node0943 -- node0945 +node0944[label="id:944\lwg:20\l"]; +node0945[label="id:945\lwg:49\l"]; +node0946[label="id:946\lwg:9\l"]; +node0947[label="id:947\lwg:30\l"]; +node0947 -- node0948 +node0948[label="id:948\lwg:34\l"]; +node0948 -- node0949 +node0949[label="id:949\lwg:50\l"]; +node0950[label="id:950\lwg:13\l"]; +node0950 -- node0951 +node0950 -- node0953 +node0951[label="id:951\lwg:6\l"]; +node0951 -- node0952 +node0952[label="id:952\lwg:2\l"]; +node0953[label="id:953\lwg:17\l"]; +node0954[label="id:954\lwg:1\l"]; +node0954 -- node0955 +node0955[label="id:955\lwg:50\l"]; +node0955 -- node0956 +node0955 -- node0958 +node0956[label="id:956\lwg:47\l"]; +node0956 -- node0957 +node0957[label="id:957\lwg:15\l"]; +node0958[label="id:958\lwg:10\l"]; +node0959[label="id:959\lwg:7\l"]; +node0959 -- node0960 +node0959 -- node0962 +node0959 -- node0963 +node0959 -- node0965 +node0960[label="id:960\lwg:17\l"]; +node0960 -- node0961 +node0961[label="id:961\lwg:45\l"]; +node0962[label="id:962\lwg:4\l"]; +node0963[label="id:963\lwg:21\l"]; +node0963 -- node0964 +node0964[label="id:964\lwg:22\l"]; +node0965[label="id:965\lwg:14\l"]; +node0965 -- node0966 +node0965 -- node0968 +node0965 -- node0972 +node0966[label="id:966\lwg:17\l"]; +node0966 -- node0967 +node0967[label="id:967\lwg:13\l"]; +node0968[label="id:968\lwg:18\l"]; +node0968 -- node0969 +node0968 -- node0970 +node0969[label="id:969\lwg:5\l"]; +node0970[label="id:970\lwg:27\l"]; +node0970 -- node0971 +node0971[label="id:971\lwg:2\l"]; +node0972[label="id:972\lwg:14\l"]; +node0972 -- node0973 +node0973[label="id:973\lwg:27\l"]; +node0973 -- node0974 +node0974[label="id:974\lwg:35\l"]; +node0975[label="id:975\lwg:8\l"]; +node0975 -- node0976 +node0975 -- node0977 +node0976[label="id:976\lwg:42\l"]; +node0977[label="id:977\lwg:30\l"]; +node0978[label="id:978\lwg:30\l"]; +node0978 -- node0979 +node0978 -- node0998 +node0978 -- node1006 +node0978 -- node1029 +node0978 -- node1051 +node0979[label="id:979\lwg:37\l"]; +node0979 -- node0980 +node0979 -- node0990 +node0979 -- node0994 +node0979 -- node0996 +node0980[label="id:980\lwg:21\l"]; +node0980 -- node0981 +node0980 -- node0983 +node0980 -- node0985 +node0981[label="id:981\lwg:37\l"]; +node0981 -- node0982 +node0982[label="id:982\lwg:20\l"]; +node0983[label="id:983\lwg:9\l"]; +node0983 -- node0984 +node0984[label="id:984\lwg:32\l"]; +node0985[label="id:985\lwg:11\l"]; +node0985 -- node0986 +node0985 -- node0988 +node0986[label="id:986\lwg:23\l"]; +node0986 -- node0987 +node0987[label="id:987\lwg:30\l"]; +node0988[label="id:988\lwg:31\l"]; +node0988 -- node0989 +node0989[label="id:989\lwg:13\l"]; +node0990[label="id:990\lwg:42\l"]; +node0990 -- node0991 +node0990 -- node0992 +node0991[label="id:991\lwg:18\l"]; +node0992[label="id:992\lwg:26\l"]; +node0992 -- node0993 +node0993[label="id:993\lwg:31\l"]; +node0994[label="id:994\lwg:48\l"]; +node0994 -- node0995 +node0995[label="id:995\lwg:9\l"]; +node0996[label="id:996\lwg:18\l"]; +node0996 -- node0997 +node0997[label="id:997\lwg:8\l"]; +node0998[label="id:998\lwg:50\l"]; +node0998 -- node0999 +node0998 -- node1002 +node0998 -- node1005 +node0999[label="id:999\lwg:29\l"]; +node0999 -- node1000 +node1000[label="id:1000\lwg:31\l"]; +node1000 -- node1001 +node1001[label="id:1001\lwg:38\l"]; +node1002[label="id:1002\lwg:2\l"]; +node1002 -- node1003 +node1002 -- node1004 +node1003[label="id:1003\lwg:43\l"]; +node1004[label="id:1004\lwg:28\l"]; +node1005[label="id:1005\lwg:49\l"]; +node1006[label="id:1006\lwg:28\l"]; +node1006 -- node1007 +node1006 -- node1016 +node1006 -- node1025 +node1007[label="id:1007\lwg:2\l"]; +node1007 -- node1008 +node1007 -- node1012 +node1007 -- node1013 +node1008[label="id:1008\lwg:16\l"]; +node1008 -- node1009 +node1008 -- node1011 +node1009[label="id:1009\lwg:11\l"]; +node1009 -- node1010 +node1010[label="id:1010\lwg:2\l"]; +node1011[label="id:1011\lwg:34\l"]; +node1012[label="id:1012\lwg:17\l"]; +node1013[label="id:1013\lwg:9\l"]; +node1013 -- node1014 +node1014[label="id:1014\lwg:9\l"]; +node1014 -- node1015 +node1015[label="id:1015\lwg:48\l"]; +node1016[label="id:1016\lwg:26\l"]; +node1016 -- node1017 +node1016 -- node1020 +node1017[label="id:1017\lwg:46\l"]; +node1017 -- node1018 +node1018[label="id:1018\lwg:7\l"]; +node1018 -- node1019 +node1019[label="id:1019\lwg:14\l"]; +node1020[label="id:1020\lwg:44\l"]; +node1020 -- node1021 +node1020 -- node1023 +node1021[label="id:1021\lwg:3\l"]; +node1021 -- node1022 +node1022[label="id:1022\lwg:34\l"]; +node1023[label="id:1023\lwg:26\l"]; +node1023 -- node1024 +node1024[label="id:1024\lwg:40\l"]; +node1025[label="id:1025\lwg:16\l"]; +node1025 -- node1026 +node1025 -- node1027 +node1025 -- node1028 +node1026[label="id:1026\lwg:8\l"]; +node1027[label="id:1027\lwg:12\l"]; +node1028[label="id:1028\lwg:42\l"]; +node1029[label="id:1029\lwg:42\l"]; +node1029 -- node1030 +node1029 -- node1038 +node1029 -- node1039 +node1029 -- node1046 +node1030[label="id:1030\lwg:9\l"]; +node1030 -- node1031 +node1030 -- node1035 +node1031[label="id:1031\lwg:45\l"]; +node1031 -- node1032 +node1031 -- node1033 +node1032[label="id:1032\lwg:28\l"]; +node1033[label="id:1033\lwg:16\l"]; +node1033 -- node1034 +node1034[label="id:1034\lwg:31\l"]; +node1035[label="id:1035\lwg:20\l"]; +node1035 -- node1036 +node1036[label="id:1036\lwg:44\l"]; +node1036 -- node1037 +node1037[label="id:1037\lwg:49\l"]; +node1038[label="id:1038\lwg:28\l"]; +node1039[label="id:1039\lwg:28\l"]; +node1039 -- node1040 +node1039 -- node1041 +node1039 -- node1042 +node1040[label="id:1040\lwg:12\l"]; +node1041[label="id:1041\lwg:11\l"]; +node1042[label="id:1042\lwg:43\l"]; +node1042 -- node1043 +node1042 -- node1045 +node1043[label="id:1043\lwg:45\l"]; +node1043 -- node1044 +node1044[label="id:1044\lwg:44\l"]; +node1045[label="id:1045\lwg:41\l"]; +node1046[label="id:1046\lwg:30\l"]; +node1046 -- node1047 +node1046 -- node1048 +node1046 -- node1049 +node1047[label="id:1047\lwg:38\l"]; +node1048[label="id:1048\lwg:31\l"]; +node1049[label="id:1049\lwg:45\l"]; +node1049 -- node1050 +node1050[label="id:1050\lwg:35\l"]; +node1051[label="id:1051\lwg:39\l"]; +node1051 -- node1052 +node1051 -- node1053 +node1051 -- node1059 +node1051 -- node1062 +node1052[label="id:1052\lwg:38\l"]; +node1053[label="id:1053\lwg:9\l"]; +node1053 -- node1054 +node1053 -- node1057 +node1054[label="id:1054\lwg:12\l"]; +node1054 -- node1055 +node1055[label="id:1055\lwg:35\l"]; +node1055 -- node1056 +node1056[label="id:1056\lwg:32\l"]; +node1057[label="id:1057\lwg:44\l"]; +node1057 -- node1058 +node1058[label="id:1058\lwg:17\l"]; +node1059[label="id:1059\lwg:15\l"]; +node1059 -- node1060 +node1060[label="id:1060\lwg:26\l"]; +node1060 -- node1061 +node1061[label="id:1061\lwg:14\l"]; +node1062[label="id:1062\lwg:43\l"]; +node1063[label="id:1063\lwg:18\l"]; +node1063 -- node1064 +node1063 -- node1080 +node1063 -- node1095 +node1063 -- node1110 +node1064[label="id:1064\lwg:8\l"]; +node1064 -- node1065 +node1064 -- node1071 +node1065[label="id:1065\lwg:36\l"]; +node1065 -- node1066 +node1065 -- node1067 +node1065 -- node1070 +node1066[label="id:1066\lwg:28\l"]; +node1067[label="id:1067\lwg:26\l"]; +node1067 -- node1068 +node1068[label="id:1068\lwg:12\l"]; +node1068 -- node1069 +node1069[label="id:1069\lwg:32\l"]; +node1070[label="id:1070\lwg:24\l"]; +node1071[label="id:1071\lwg:46\l"]; +node1071 -- node1072 +node1071 -- node1076 +node1072[label="id:1072\lwg:12\l"]; +node1072 -- node1073 +node1072 -- node1074 +node1073[label="id:1073\lwg:34\l"]; +node1074[label="id:1074\lwg:28\l"]; +node1074 -- node1075 +node1075[label="id:1075\lwg:42\l"]; +node1076[label="id:1076\lwg:6\l"]; +node1076 -- node1077 +node1076 -- node1078 +node1077[label="id:1077\lwg:14\l"]; +node1078[label="id:1078\lwg:9\l"]; +node1078 -- node1079 +node1079[label="id:1079\lwg:23\l"]; +node1080[label="id:1080\lwg:45\l"]; +node1080 -- node1081 +node1080 -- node1091 +node1081[label="id:1081\lwg:14\l"]; +node1081 -- node1082 +node1081 -- node1084 +node1081 -- node1087 +node1082[label="id:1082\lwg:33\l"]; +node1082 -- node1083 +node1083[label="id:1083\lwg:41\l"]; +node1084[label="id:1084\lwg:25\l"]; +node1084 -- node1085 +node1084 -- node1086 +node1085[label="id:1085\lwg:18\l"]; +node1086[label="id:1086\lwg:41\l"]; +node1087[label="id:1087\lwg:8\l"]; +node1087 -- node1088 +node1087 -- node1090 +node1088[label="id:1088\lwg:3\l"]; +node1088 -- node1089 +node1089[label="id:1089\lwg:35\l"]; +node1090[label="id:1090\lwg:40\l"]; +node1091[label="id:1091\lwg:38\l"]; +node1091 -- node1092 +node1092[label="id:1092\lwg:34\l"]; +node1092 -- node1093 +node1092 -- node1094 +node1093[label="id:1093\lwg:44\l"]; +node1094[label="id:1094\lwg:32\l"]; +node1095[label="id:1095\lwg:12\l"]; +node1095 -- node1096 +node1095 -- node1099 +node1096[label="id:1096\lwg:27\l"]; +node1096 -- node1097 +node1097[label="id:1097\lwg:1\l"]; +node1097 -- node1098 +node1098[label="id:1098\lwg:16\l"]; +node1099[label="id:1099\lwg:6\l"]; +node1099 -- node1100 +node1099 -- node1104 +node1099 -- node1105 +node1100[label="id:1100\lwg:16\l"]; +node1100 -- node1101 +node1100 -- node1103 +node1101[label="id:1101\lwg:40\l"]; +node1101 -- node1102 +node1102[label="id:1102\lwg:38\l"]; +node1103[label="id:1103\lwg:13\l"]; +node1104[label="id:1104\lwg:39\l"]; +node1105[label="id:1105\lwg:23\l"]; +node1105 -- node1106 +node1105 -- node1108 +node1106[label="id:1106\lwg:27\l"]; +node1106 -- node1107 +node1107[label="id:1107\lwg:26\l"]; +node1108[label="id:1108\lwg:10\l"]; +node1108 -- node1109 +node1109[label="id:1109\lwg:6\l"]; +node1110[label="id:1110\lwg:39\l"]; +node1110 -- node1111 +node1110 -- node1121 +node1111[label="id:1111\lwg:22\l"]; +node1111 -- node1112 +node1111 -- node1115 +node1111 -- node1117 +node1112[label="id:1112\lwg:44\l"]; +node1112 -- node1113 +node1112 -- node1114 +node1113[label="id:1113\lwg:28\l"]; +node1114[label="id:1114\lwg:16\l"]; +node1115[label="id:1115\lwg:1\l"]; +node1115 -- node1116 +node1116[label="id:1116\lwg:9\l"]; +node1117[label="id:1117\lwg:42\l"]; +node1117 -- node1118 +node1117 -- node1120 +node1118[label="id:1118\lwg:41\l"]; +node1118 -- node1119 +node1119[label="id:1119\lwg:38\l"]; +node1120[label="id:1120\lwg:4\l"]; +node1121[label="id:1121\lwg:11\l"]; +node1121 -- node1122 +node1122[label="id:1122\lwg:23\l"]; +node1122 -- node1123 +node1123[label="id:1123\lwg:42\l"]; +node1123 -- node1124 +node1124[label="id:1124\lwg:9\l"]; +node1125[label="id:1125\lwg:27\l"]; +node1125 -- node1126 +node1125 -- node1147 +node1125 -- node1156 +node1125 -- node1165 +node1126[label="id:1126\lwg:16\l"]; +node1126 -- node1127 +node1126 -- node1134 +node1126 -- node1137 +node1126 -- node1141 +node1127[label="id:1127\lwg:17\l"]; +node1127 -- node1128 +node1127 -- node1133 +node1128[label="id:1128\lwg:23\l"]; +node1128 -- node1129 +node1128 -- node1131 +node1129[label="id:1129\lwg:20\l"]; +node1129 -- node1130 +node1130[label="id:1130\lwg:31\l"]; +node1131[label="id:1131\lwg:24\l"]; +node1131 -- node1132 +node1132[label="id:1132\lwg:12\l"]; +node1133[label="id:1133\lwg:41\l"]; +node1134[label="id:1134\lwg:22\l"]; +node1134 -- node1135 +node1135[label="id:1135\lwg:34\l"]; +node1135 -- node1136 +node1136[label="id:1136\lwg:42\l"]; +node1137[label="id:1137\lwg:7\l"]; +node1137 -- node1138 +node1138[label="id:1138\lwg:34\l"]; +node1138 -- node1139 +node1139[label="id:1139\lwg:48\l"]; +node1139 -- node1140 +node1140[label="id:1140\lwg:46\l"]; +node1141[label="id:1141\lwg:43\l"]; +node1141 -- node1142 +node1141 -- node1143 +node1142[label="id:1142\lwg:27\l"]; +node1143[label="id:1143\lwg:23\l"]; +node1143 -- node1144 +node1143 -- node1145 +node1144[label="id:1144\lwg:7\l"]; +node1145[label="id:1145\lwg:40\l"]; +node1145 -- node1146 +node1146[label="id:1146\lwg:14\l"]; +node1147[label="id:1147\lwg:32\l"]; +node1147 -- node1148 +node1147 -- node1149 +node1148[label="id:1148\lwg:29\l"]; +node1149[label="id:1149\lwg:30\l"]; +node1149 -- node1150 +node1149 -- node1151 +node1149 -- node1154 +node1150[label="id:1150\lwg:1\l"]; +node1151[label="id:1151\lwg:24\l"]; +node1151 -- node1152 +node1152[label="id:1152\lwg:9\l"]; +node1152 -- node1153 +node1153[label="id:1153\lwg:8\l"]; +node1154[label="id:1154\lwg:31\l"]; +node1154 -- node1155 +node1155[label="id:1155\lwg:35\l"]; +node1156[label="id:1156\lwg:33\l"]; +node1156 -- node1157 +node1157[label="id:1157\lwg:40\l"]; +node1157 -- node1158 +node1157 -- node1161 +node1157 -- node1162 +node1158[label="id:1158\lwg:40\l"]; +node1158 -- node1159 +node1159[label="id:1159\lwg:9\l"]; +node1159 -- node1160 +node1160[label="id:1160\lwg:7\l"]; +node1161[label="id:1161\lwg:37\l"]; +node1162[label="id:1162\lwg:12\l"]; +node1162 -- node1163 +node1163[label="id:1163\lwg:48\l"]; +node1163 -- node1164 +node1164[label="id:1164\lwg:39\l"]; +node1165[label="id:1165\lwg:41\l"]; +node1165 -- node1166 +node1166[label="id:1166\lwg:42\l"]; +node1166 -- node1167 +node1166 -- node1170 +node1167[label="id:1167\lwg:35\l"]; +node1167 -- node1168 +node1168[label="id:1168\lwg:48\l"]; +node1168 -- node1169 +node1169[label="id:1169\lwg:43\l"]; +node1170[label="id:1170\lwg:50\l"]; +node1170 -- node1171 +node1170 -- node1172 +node1171[label="id:1171\lwg:7\l"]; +node1172[label="id:1172\lwg:8\l"]; +node1173[label="id:1173\lwg:43\l"]; +node1173 -- node1174 +node1173 -- node1394 +node1173 -- node1597 +node1173 -- node1633 +node1173 -- node1737 +node1173 -- node1840 +node1173 -- node1870 +node1174[label="id:1174\lwg:13\l"]; +node1174 -- node1175 +node1174 -- node1200 +node1174 -- node1238 +node1174 -- node1264 +node1174 -- node1296 +node1174 -- node1387 +node1175[label="id:1175\lwg:45\l"]; +node1175 -- node1176 +node1175 -- node1177 +node1175 -- node1178 +node1176[label="id:1176\lwg:1\l"]; +node1177[label="id:1177\lwg:43\l"]; +node1178[label="id:1178\lwg:48\l"]; +node1178 -- node1179 +node1178 -- node1191 +node1178 -- node1193 +node1178 -- node1196 +node1179[label="id:1179\lwg:6\l"]; +node1179 -- node1180 +node1179 -- node1184 +node1179 -- node1187 +node1180[label="id:1180\lwg:19\l"]; +node1180 -- node1181 +node1180 -- node1182 +node1181[label="id:1181\lwg:31\l"]; +node1182[label="id:1182\lwg:15\l"]; +node1182 -- node1183 +node1183[label="id:1183\lwg:11\l"]; +node1184[label="id:1184\lwg:8\l"]; +node1184 -- node1185 +node1184 -- node1186 +node1185[label="id:1185\lwg:44\l"]; +node1186[label="id:1186\lwg:35\l"]; +node1187[label="id:1187\lwg:43\l"]; +node1187 -- node1188 +node1187 -- node1189 +node1188[label="id:1188\lwg:49\l"]; +node1189[label="id:1189\lwg:44\l"]; +node1189 -- node1190 +node1190[label="id:1190\lwg:39\l"]; +node1191[label="id:1191\lwg:34\l"]; +node1191 -- node1192 +node1192[label="id:1192\lwg:19\l"]; +node1193[label="id:1193\lwg:7\l"]; +node1193 -- node1194 +node1194[label="id:1194\lwg:17\l"]; +node1194 -- node1195 +node1195[label="id:1195\lwg:8\l"]; +node1196[label="id:1196\lwg:11\l"]; +node1196 -- node1197 +node1196 -- node1199 +node1197[label="id:1197\lwg:46\l"]; +node1197 -- node1198 +node1198[label="id:1198\lwg:4\l"]; +node1199[label="id:1199\lwg:40\l"]; +node1200[label="id:1200\lwg:14\l"]; +node1200 -- node1201 +node1200 -- node1202 +node1200 -- node1221 +node1200 -- node1237 +node1201[label="id:1201\lwg:21\l"]; +node1202[label="id:1202\lwg:37\l"]; +node1202 -- node1203 +node1202 -- node1213 +node1202 -- node1214 +node1203[label="id:1203\lwg:43\l"]; +node1203 -- node1204 +node1203 -- node1208 +node1203 -- node1209 +node1204[label="id:1204\lwg:1\l"]; +node1204 -- node1205 +node1204 -- node1207 +node1205[label="id:1205\lwg:50\l"]; +node1205 -- node1206 +node1206[label="id:1206\lwg:25\l"]; +node1207[label="id:1207\lwg:31\l"]; +node1208[label="id:1208\lwg:8\l"]; +node1209[label="id:1209\lwg:13\l"]; +node1209 -- node1210 +node1209 -- node1211 +node1210[label="id:1210\lwg:2\l"]; +node1211[label="id:1211\lwg:11\l"]; +node1211 -- node1212 +node1212[label="id:1212\lwg:11\l"]; +node1213[label="id:1213\lwg:40\l"]; +node1214[label="id:1214\lwg:16\l"]; +node1214 -- node1215 +node1214 -- node1218 +node1214 -- node1219 +node1215[label="id:1215\lwg:30\l"]; +node1215 -- node1216 +node1216[label="id:1216\lwg:16\l"]; +node1216 -- node1217 +node1217[label="id:1217\lwg:30\l"]; +node1218[label="id:1218\lwg:17\l"]; +node1219[label="id:1219\lwg:40\l"]; +node1219 -- node1220 +node1220[label="id:1220\lwg:9\l"]; +node1221[label="id:1221\lwg:7\l"]; +node1221 -- node1222 +node1221 -- node1231 +node1221 -- node1232 +node1222[label="id:1222\lwg:24\l"]; +node1222 -- node1223 +node1222 -- node1227 +node1223[label="id:1223\lwg:30\l"]; +node1223 -- node1224 +node1223 -- node1225 +node1224[label="id:1224\lwg:29\l"]; +node1225[label="id:1225\lwg:9\l"]; +node1225 -- node1226 +node1226[label="id:1226\lwg:15\l"]; +node1227[label="id:1227\lwg:45\l"]; +node1227 -- node1228 +node1227 -- node1229 +node1228[label="id:1228\lwg:28\l"]; +node1229[label="id:1229\lwg:42\l"]; +node1229 -- node1230 +node1230[label="id:1230\lwg:16\l"]; +node1231[label="id:1231\lwg:22\l"]; +node1232[label="id:1232\lwg:24\l"]; +node1232 -- node1233 +node1232 -- node1235 +node1232 -- node1236 +node1233[label="id:1233\lwg:38\l"]; +node1233 -- node1234 +node1234[label="id:1234\lwg:24\l"]; +node1235[label="id:1235\lwg:9\l"]; +node1236[label="id:1236\lwg:17\l"]; +node1237[label="id:1237\lwg:21\l"]; +node1238[label="id:1238\lwg:7\l"]; +node1238 -- node1239 +node1238 -- node1253 +node1238 -- node1263 +node1239[label="id:1239\lwg:25\l"]; +node1239 -- node1240 +node1239 -- node1241 +node1239 -- node1242 +node1239 -- node1249 +node1240[label="id:1240\lwg:43\l"]; +node1241[label="id:1241\lwg:18\l"]; +node1242[label="id:1242\lwg:4\l"]; +node1242 -- node1243 +node1242 -- node1247 +node1243[label="id:1243\lwg:35\l"]; +node1243 -- node1244 +node1243 -- node1245 +node1244[label="id:1244\lwg:49\l"]; +node1245[label="id:1245\lwg:26\l"]; +node1245 -- node1246 +node1246[label="id:1246\lwg:50\l"]; +node1247[label="id:1247\lwg:49\l"]; +node1247 -- node1248 +node1248[label="id:1248\lwg:50\l"]; +node1249[label="id:1249\lwg:13\l"]; +node1249 -- node1250 +node1250[label="id:1250\lwg:14\l"]; +node1250 -- node1251 +node1251[label="id:1251\lwg:11\l"]; +node1251 -- node1252 +node1252[label="id:1252\lwg:39\l"]; +node1253[label="id:1253\lwg:22\l"]; +node1253 -- node1254 +node1253 -- node1255 +node1254[label="id:1254\lwg:32\l"]; +node1255[label="id:1255\lwg:35\l"]; +node1255 -- node1256 +node1255 -- node1261 +node1255 -- node1262 +node1256[label="id:1256\lwg:31\l"]; +node1256 -- node1257 +node1256 -- node1259 +node1257[label="id:1257\lwg:36\l"]; +node1257 -- node1258 +node1258[label="id:1258\lwg:15\l"]; +node1259[label="id:1259\lwg:17\l"]; +node1259 -- node1260 +node1260[label="id:1260\lwg:1\l"]; +node1261[label="id:1261\lwg:30\l"]; +node1262[label="id:1262\lwg:40\l"]; +node1263[label="id:1263\lwg:24\l"]; +node1264[label="id:1264\lwg:18\l"]; +node1264 -- node1265 +node1264 -- node1289 +node1264 -- node1292 +node1264 -- node1295 +node1265[label="id:1265\lwg:16\l"]; +node1265 -- node1266 +node1265 -- node1277 +node1265 -- node1281 +node1266[label="id:1266\lwg:10\l"]; +node1266 -- node1267 +node1266 -- node1270 +node1266 -- node1273 +node1267[label="id:1267\lwg:14\l"]; +node1267 -- node1268 +node1268[label="id:1268\lwg:10\l"]; +node1268 -- node1269 +node1269[label="id:1269\lwg:48\l"]; +node1270[label="id:1270\lwg:35\l"]; +node1270 -- node1271 +node1271[label="id:1271\lwg:20\l"]; +node1271 -- node1272 +node1272[label="id:1272\lwg:33\l"]; +node1273[label="id:1273\lwg:50\l"]; +node1273 -- node1274 +node1273 -- node1275 +node1274[label="id:1274\lwg:26\l"]; +node1275[label="id:1275\lwg:15\l"]; +node1275 -- node1276 +node1276[label="id:1276\lwg:9\l"]; +node1277[label="id:1277\lwg:27\l"]; +node1277 -- node1278 +node1278[label="id:1278\lwg:26\l"]; +node1278 -- node1279 +node1279[label="id:1279\lwg:39\l"]; +node1279 -- node1280 +node1280[label="id:1280\lwg:38\l"]; +node1281[label="id:1281\lwg:27\l"]; +node1281 -- node1282 +node1281 -- node1285 +node1281 -- node1288 +node1282[label="id:1282\lwg:33\l"]; +node1282 -- node1283 +node1283[label="id:1283\lwg:50\l"]; +node1283 -- node1284 +node1284[label="id:1284\lwg:28\l"]; +node1285[label="id:1285\lwg:38\l"]; +node1285 -- node1286 +node1286[label="id:1286\lwg:28\l"]; +node1286 -- node1287 +node1287[label="id:1287\lwg:30\l"]; +node1288[label="id:1288\lwg:11\l"]; +node1289[label="id:1289\lwg:12\l"]; +node1289 -- node1290 +node1290[label="id:1290\lwg:49\l"]; +node1290 -- node1291 +node1291[label="id:1291\lwg:15\l"]; +node1292[label="id:1292\lwg:24\l"]; +node1292 -- node1293 +node1292 -- node1294 +node1293[label="id:1293\lwg:8\l"]; +node1294[label="id:1294\lwg:43\l"]; +node1295[label="id:1295\lwg:44\l"]; +node1296[label="id:1296\lwg:2\l"]; +node1296 -- node1297 +node1296 -- node1324 +node1296 -- node1348 +node1296 -- node1366 +node1296 -- node1372 +node1297[label="id:1297\lwg:33\l"]; +node1297 -- node1298 +node1297 -- node1306 +node1297 -- node1307 +node1297 -- node1313 +node1298[label="id:1298\lwg:11\l"]; +node1298 -- node1299 +node1298 -- node1302 +node1298 -- node1303 +node1299[label="id:1299\lwg:32\l"]; +node1299 -- node1300 +node1299 -- node1301 +node1300[label="id:1300\lwg:29\l"]; +node1301[label="id:1301\lwg:4\l"]; +node1302[label="id:1302\lwg:28\l"]; +node1303[label="id:1303\lwg:22\l"]; +node1303 -- node1304 +node1304[label="id:1304\lwg:17\l"]; +node1304 -- node1305 +node1305[label="id:1305\lwg:30\l"]; +node1306[label="id:1306\lwg:13\l"]; +node1307[label="id:1307\lwg:26\l"]; +node1307 -- node1308 +node1307 -- node1309 +node1307 -- node1310 +node1308[label="id:1308\lwg:39\l"]; +node1309[label="id:1309\lwg:36\l"]; +node1310[label="id:1310\lwg:31\l"]; +node1310 -- node1311 +node1311[label="id:1311\lwg:14\l"]; +node1311 -- node1312 +node1312[label="id:1312\lwg:1\l"]; +node1313[label="id:1313\lwg:21\l"]; +node1313 -- node1314 +node1313 -- node1318 +node1313 -- node1323 +node1314[label="id:1314\lwg:28\l"]; +node1314 -- node1315 +node1314 -- node1317 +node1315[label="id:1315\lwg:4\l"]; +node1315 -- node1316 +node1316[label="id:1316\lwg:23\l"]; +node1317[label="id:1317\lwg:17\l"]; +node1318[label="id:1318\lwg:42\l"]; +node1318 -- node1319 +node1318 -- node1321 +node1319[label="id:1319\lwg:41\l"]; +node1319 -- node1320 +node1320[label="id:1320\lwg:25\l"]; +node1321[label="id:1321\lwg:29\l"]; +node1321 -- node1322 +node1322[label="id:1322\lwg:14\l"]; +node1323[label="id:1323\lwg:24\l"]; +node1324[label="id:1324\lwg:37\l"]; +node1324 -- node1325 +node1324 -- node1334 +node1324 -- node1340 +node1325[label="id:1325\lwg:34\l"]; +node1325 -- node1326 +node1325 -- node1329 +node1326[label="id:1326\lwg:38\l"]; +node1326 -- node1327 +node1326 -- node1328 +node1327[label="id:1327\lwg:2\l"]; +node1328[label="id:1328\lwg:47\l"]; +node1329[label="id:1329\lwg:4\l"]; +node1329 -- node1330 +node1329 -- node1332 +node1330[label="id:1330\lwg:28\l"]; +node1330 -- node1331 +node1331[label="id:1331\lwg:33\l"]; +node1332[label="id:1332\lwg:15\l"]; +node1332 -- node1333 +node1333[label="id:1333\lwg:1\l"]; +node1334[label="id:1334\lwg:43\l"]; +node1334 -- node1335 +node1334 -- node1337 +node1335[label="id:1335\lwg:20\l"]; +node1335 -- node1336 +node1336[label="id:1336\lwg:13\l"]; +node1337[label="id:1337\lwg:5\l"]; +node1337 -- node1338 +node1338[label="id:1338\lwg:2\l"]; +node1338 -- node1339 +node1339[label="id:1339\lwg:31\l"]; +node1340[label="id:1340\lwg:38\l"]; +node1340 -- node1341 +node1340 -- node1344 +node1340 -- node1346 +node1341[label="id:1341\lwg:8\l"]; +node1341 -- node1342 +node1342[label="id:1342\lwg:14\l"]; +node1342 -- node1343 +node1343[label="id:1343\lwg:18\l"]; +node1344[label="id:1344\lwg:34\l"]; +node1344 -- node1345 +node1345[label="id:1345\lwg:35\l"]; +node1346[label="id:1346\lwg:29\l"]; +node1346 -- node1347 +node1347[label="id:1347\lwg:12\l"]; +node1348[label="id:1348\lwg:22\l"]; +node1348 -- node1349 +node1348 -- node1355 +node1348 -- node1360 +node1348 -- node1361 +node1349[label="id:1349\lwg:3\l"]; +node1349 -- node1350 +node1349 -- node1352 +node1349 -- node1353 +node1350[label="id:1350\lwg:7\l"]; +node1350 -- node1351 +node1351[label="id:1351\lwg:32\l"]; +node1352[label="id:1352\lwg:20\l"]; +node1353[label="id:1353\lwg:48\l"]; +node1353 -- node1354 +node1354[label="id:1354\lwg:17\l"]; +node1355[label="id:1355\lwg:12\l"]; +node1355 -- node1356 +node1356[label="id:1356\lwg:43\l"]; +node1356 -- node1357 +node1356 -- node1358 +node1357[label="id:1357\lwg:33\l"]; +node1358[label="id:1358\lwg:33\l"]; +node1358 -- node1359 +node1359[label="id:1359\lwg:18\l"]; +node1360[label="id:1360\lwg:22\l"]; +node1361[label="id:1361\lwg:29\l"]; +node1361 -- node1362 +node1362[label="id:1362\lwg:23\l"]; +node1362 -- node1363 +node1362 -- node1364 +node1363[label="id:1363\lwg:47\l"]; +node1364[label="id:1364\lwg:6\l"]; +node1364 -- node1365 +node1365[label="id:1365\lwg:9\l"]; +node1366[label="id:1366\lwg:23\l"]; +node1366 -- node1367 +node1366 -- node1370 +node1366 -- node1371 +node1367[label="id:1367\lwg:32\l"]; +node1367 -- node1368 +node1368[label="id:1368\lwg:27\l"]; +node1368 -- node1369 +node1369[label="id:1369\lwg:17\l"]; +node1370[label="id:1370\lwg:8\l"]; +node1371[label="id:1371\lwg:48\l"]; +node1372[label="id:1372\lwg:3\l"]; +node1372 -- node1373 +node1372 -- node1379 +node1372 -- node1382 +node1372 -- node1386 +node1373[label="id:1373\lwg:8\l"]; +node1373 -- node1374 +node1373 -- node1376 +node1374[label="id:1374\lwg:32\l"]; +node1374 -- node1375 +node1375[label="id:1375\lwg:4\l"]; +node1376[label="id:1376\lwg:32\l"]; +node1376 -- node1377 +node1377[label="id:1377\lwg:7\l"]; +node1377 -- node1378 +node1378[label="id:1378\lwg:24\l"]; +node1379[label="id:1379\lwg:1\l"]; +node1379 -- node1380 +node1379 -- node1381 +node1380[label="id:1380\lwg:6\l"]; +node1381[label="id:1381\lwg:45\l"]; +node1382[label="id:1382\lwg:50\l"]; +node1382 -- node1383 +node1383[label="id:1383\lwg:26\l"]; +node1383 -- node1384 +node1384[label="id:1384\lwg:9\l"]; +node1384 -- node1385 +node1385[label="id:1385\lwg:22\l"]; +node1386[label="id:1386\lwg:25\l"]; +node1387[label="id:1387\lwg:18\l"]; +node1387 -- node1388 +node1388[label="id:1388\lwg:2\l"]; +node1388 -- node1389 +node1388 -- node1392 +node1388 -- node1393 +node1389[label="id:1389\lwg:14\l"]; +node1389 -- node1390 +node1389 -- node1391 +node1390[label="id:1390\lwg:3\l"]; +node1391[label="id:1391\lwg:38\l"]; +node1392[label="id:1392\lwg:49\l"]; +node1393[label="id:1393\lwg:40\l"]; +node1394[label="id:1394\lwg:1\l"]; +node1394 -- node1395 +node1394 -- node1455 +node1394 -- node1503 +node1394 -- node1547 +node1395[label="id:1395\lwg:7\l"]; +node1395 -- node1396 +node1395 -- node1411 +node1395 -- node1412 +node1395 -- node1447 +node1396[label="id:1396\lwg:3\l"]; +node1396 -- node1397 +node1396 -- node1402 +node1397[label="id:1397\lwg:38\l"]; +node1397 -- node1398 +node1398[label="id:1398\lwg:30\l"]; +node1398 -- node1399 +node1398 -- node1400 +node1399[label="id:1399\lwg:32\l"]; +node1400[label="id:1400\lwg:9\l"]; +node1400 -- node1401 +node1401[label="id:1401\lwg:6\l"]; +node1402[label="id:1402\lwg:25\l"]; +node1402 -- node1403 +node1402 -- node1406 +node1403[label="id:1403\lwg:14\l"]; +node1403 -- node1404 +node1404[label="id:1404\lwg:50\l"]; +node1404 -- node1405 +node1405[label="id:1405\lwg:8\l"]; +node1406[label="id:1406\lwg:44\l"]; +node1406 -- node1407 +node1406 -- node1409 +node1407[label="id:1407\lwg:39\l"]; +node1407 -- node1408 +node1408[label="id:1408\lwg:44\l"]; +node1409[label="id:1409\lwg:19\l"]; +node1409 -- node1410 +node1410[label="id:1410\lwg:22\l"]; +node1411[label="id:1411\lwg:4\l"]; +node1412[label="id:1412\lwg:27\l"]; +node1412 -- node1413 +node1412 -- node1421 +node1412 -- node1432 +node1412 -- node1437 +node1413[label="id:1413\lwg:29\l"]; +node1413 -- node1414 +node1413 -- node1418 +node1414[label="id:1414\lwg:7\l"]; +node1414 -- node1415 +node1414 -- node1417 +node1415[label="id:1415\lwg:47\l"]; +node1415 -- node1416 +node1416[label="id:1416\lwg:15\l"]; +node1417[label="id:1417\lwg:50\l"]; +node1418[label="id:1418\lwg:28\l"]; +node1418 -- node1419 +node1418 -- node1420 +node1419[label="id:1419\lwg:16\l"]; +node1420[label="id:1420\lwg:40\l"]; +node1421[label="id:1421\lwg:33\l"]; +node1421 -- node1422 +node1421 -- node1423 +node1421 -- node1428 +node1422[label="id:1422\lwg:23\l"]; +node1423[label="id:1423\lwg:30\l"]; +node1423 -- node1424 +node1423 -- node1426 +node1424[label="id:1424\lwg:3\l"]; +node1424 -- node1425 +node1425[label="id:1425\lwg:11\l"]; +node1426[label="id:1426\lwg:23\l"]; +node1426 -- node1427 +node1427[label="id:1427\lwg:2\l"]; +node1428[label="id:1428\lwg:6\l"]; +node1428 -- node1429 +node1428 -- node1431 +node1429[label="id:1429\lwg:10\l"]; +node1429 -- node1430 +node1430[label="id:1430\lwg:44\l"]; +node1431[label="id:1431\lwg:30\l"]; +node1432[label="id:1432\lwg:13\l"]; +node1432 -- node1433 +node1433[label="id:1433\lwg:1\l"]; +node1433 -- node1434 +node1433 -- node1436 +node1434[label="id:1434\lwg:42\l"]; +node1434 -- node1435 +node1435[label="id:1435\lwg:18\l"]; +node1436[label="id:1436\lwg:41\l"]; +node1437[label="id:1437\lwg:19\l"]; +node1437 -- node1438 +node1437 -- node1442 +node1438[label="id:1438\lwg:23\l"]; +node1438 -- node1439 +node1438 -- node1441 +node1439[label="id:1439\lwg:30\l"]; +node1439 -- node1440 +node1440[label="id:1440\lwg:45\l"]; +node1441[label="id:1441\lwg:3\l"]; +node1442[label="id:1442\lwg:6\l"]; +node1442 -- node1443 +node1442 -- node1445 +node1443[label="id:1443\lwg:22\l"]; +node1443 -- node1444 +node1444[label="id:1444\lwg:38\l"]; +node1445[label="id:1445\lwg:28\l"]; +node1445 -- node1446 +node1446[label="id:1446\lwg:42\l"]; +node1447[label="id:1447\lwg:40\l"]; +node1447 -- node1448 +node1448[label="id:1448\lwg:37\l"]; +node1448 -- node1449 +node1448 -- node1450 +node1448 -- node1453 +node1449[label="id:1449\lwg:45\l"]; +node1450[label="id:1450\lwg:8\l"]; +node1450 -- node1451 +node1451[label="id:1451\lwg:14\l"]; +node1451 -- node1452 +node1452[label="id:1452\lwg:16\l"]; +node1453[label="id:1453\lwg:13\l"]; +node1453 -- node1454 +node1454[label="id:1454\lwg:29\l"]; +node1455[label="id:1455\lwg:17\l"]; +node1455 -- node1456 +node1455 -- node1474 +node1455 -- node1481 +node1456[label="id:1456\lwg:34\l"]; +node1456 -- node1457 +node1456 -- node1462 +node1456 -- node1472 +node1457[label="id:1457\lwg:45\l"]; +node1457 -- node1458 +node1457 -- node1461 +node1458[label="id:1458\lwg:27\l"]; +node1458 -- node1459 +node1459[label="id:1459\lwg:7\l"]; +node1459 -- node1460 +node1460[label="id:1460\lwg:1\l"]; +node1461[label="id:1461\lwg:46\l"]; +node1462[label="id:1462\lwg:42\l"]; +node1462 -- node1463 +node1462 -- node1468 +node1462 -- node1470 +node1463[label="id:1463\lwg:47\l"]; +node1463 -- node1464 +node1463 -- node1466 +node1464[label="id:1464\lwg:27\l"]; +node1464 -- node1465 +node1465[label="id:1465\lwg:10\l"]; +node1466[label="id:1466\lwg:9\l"]; +node1466 -- node1467 +node1467[label="id:1467\lwg:33\l"]; +node1468[label="id:1468\lwg:5\l"]; +node1468 -- node1469 +node1469[label="id:1469\lwg:16\l"]; +node1470[label="id:1470\lwg:41\l"]; +node1470 -- node1471 +node1471[label="id:1471\lwg:8\l"]; +node1472[label="id:1472\lwg:5\l"]; +node1472 -- node1473 +node1473[label="id:1473\lwg:19\l"]; +node1474[label="id:1474\lwg:22\l"]; +node1474 -- node1475 +node1474 -- node1479 +node1475[label="id:1475\lwg:48\l"]; +node1475 -- node1476 +node1475 -- node1478 +node1476[label="id:1476\lwg:10\l"]; +node1476 -- node1477 +node1477[label="id:1477\lwg:16\l"]; +node1478[label="id:1478\lwg:30\l"]; +node1479[label="id:1479\lwg:33\l"]; +node1479 -- node1480 +node1480[label="id:1480\lwg:9\l"]; +node1481[label="id:1481\lwg:41\l"]; +node1481 -- node1482 +node1481 -- node1489 +node1481 -- node1501 +node1482[label="id:1482\lwg:16\l"]; +node1482 -- node1483 +node1482 -- node1488 +node1483[label="id:1483\lwg:42\l"]; +node1483 -- node1484 +node1483 -- node1486 +node1484[label="id:1484\lwg:22\l"]; +node1484 -- node1485 +node1485[label="id:1485\lwg:7\l"]; +node1486[label="id:1486\lwg:44\l"]; +node1486 -- node1487 +node1487[label="id:1487\lwg:39\l"]; +node1488[label="id:1488\lwg:20\l"]; +node1489[label="id:1489\lwg:33\l"]; +node1489 -- node1490 +node1489 -- node1493 +node1489 -- node1497 +node1490[label="id:1490\lwg:32\l"]; +node1490 -- node1491 +node1491[label="id:1491\lwg:14\l"]; +node1491 -- node1492 +node1492[label="id:1492\lwg:27\l"]; +node1493[label="id:1493\lwg:46\l"]; +node1493 -- node1494 +node1493 -- node1496 +node1494[label="id:1494\lwg:45\l"]; +node1494 -- node1495 +node1495[label="id:1495\lwg:15\l"]; +node1496[label="id:1496\lwg:23\l"]; +node1497[label="id:1497\lwg:19\l"]; +node1497 -- node1498 +node1497 -- node1499 +node1498[label="id:1498\lwg:31\l"]; +node1499[label="id:1499\lwg:14\l"]; +node1499 -- node1500 +node1500[label="id:1500\lwg:21\l"]; +node1501[label="id:1501\lwg:17\l"]; +node1501 -- node1502 +node1502[label="id:1502\lwg:38\l"]; +node1503[label="id:1503\lwg:14\l"]; +node1503 -- node1504 +node1503 -- node1511 +node1503 -- node1522 +node1503 -- node1537 +node1503 -- node1546 +node1504[label="id:1504\lwg:13\l"]; +node1504 -- node1505 +node1505[label="id:1505\lwg:49\l"]; +node1505 -- node1506 +node1505 -- node1507 +node1505 -- node1509 +node1506[label="id:1506\lwg:31\l"]; +node1507[label="id:1507\lwg:39\l"]; +node1507 -- node1508 +node1508[label="id:1508\lwg:43\l"]; +node1509[label="id:1509\lwg:18\l"]; +node1509 -- node1510 +node1510[label="id:1510\lwg:14\l"]; +node1511[label="id:1511\lwg:41\l"]; +node1511 -- node1512 +node1511 -- node1518 +node1511 -- node1519 +node1512[label="id:1512\lwg:40\l"]; +node1512 -- node1513 +node1512 -- node1514 +node1513[label="id:1513\lwg:29\l"]; +node1514[label="id:1514\lwg:22\l"]; +node1514 -- node1515 +node1514 -- node1517 +node1515[label="id:1515\lwg:28\l"]; +node1515 -- node1516 +node1516[label="id:1516\lwg:14\l"]; +node1517[label="id:1517\lwg:8\l"]; +node1518[label="id:1518\lwg:50\l"]; +node1519[label="id:1519\lwg:9\l"]; +node1519 -- node1520 +node1519 -- node1521 +node1520[label="id:1520\lwg:22\l"]; +node1521[label="id:1521\lwg:7\l"]; +node1522[label="id:1522\lwg:20\l"]; +node1522 -- node1523 +node1522 -- node1534 +node1523[label="id:1523\lwg:13\l"]; +node1523 -- node1524 +node1523 -- node1525 +node1523 -- node1529 +node1524[label="id:1524\lwg:32\l"]; +node1525[label="id:1525\lwg:2\l"]; +node1525 -- node1526 +node1525 -- node1527 +node1526[label="id:1526\lwg:16\l"]; +node1527[label="id:1527\lwg:35\l"]; +node1527 -- node1528 +node1528[label="id:1528\lwg:2\l"]; +node1529[label="id:1529\lwg:32\l"]; +node1529 -- node1530 +node1529 -- node1532 +node1530[label="id:1530\lwg:7\l"]; +node1530 -- node1531 +node1531[label="id:1531\lwg:20\l"]; +node1532[label="id:1532\lwg:3\l"]; +node1532 -- node1533 +node1533[label="id:1533\lwg:22\l"]; +node1534[label="id:1534\lwg:2\l"]; +node1534 -- node1535 +node1535[label="id:1535\lwg:15\l"]; +node1535 -- node1536 +node1536[label="id:1536\lwg:38\l"]; +node1537[label="id:1537\lwg:27\l"]; +node1537 -- node1538 +node1537 -- node1541 +node1537 -- node1545 +node1538[label="id:1538\lwg:19\l"]; +node1538 -- node1539 +node1538 -- node1540 +node1539[label="id:1539\lwg:23\l"]; +node1540[label="id:1540\lwg:22\l"]; +node1541[label="id:1541\lwg:46\l"]; +node1541 -- node1542 +node1541 -- node1543 +node1541 -- node1544 +node1542[label="id:1542\lwg:20\l"]; +node1543[label="id:1543\lwg:46\l"]; +node1544[label="id:1544\lwg:45\l"]; +node1545[label="id:1545\lwg:48\l"]; +node1546[label="id:1546\lwg:36\l"]; +node1547[label="id:1547\lwg:22\l"]; +node1547 -- node1548 +node1547 -- node1555 +node1547 -- node1576 +node1547 -- node1596 +node1548[label="id:1548\lwg:48\l"]; +node1548 -- node1549 +node1548 -- node1550 +node1549[label="id:1549\lwg:42\l"]; +node1550[label="id:1550\lwg:22\l"]; +node1550 -- node1551 +node1550 -- node1553 +node1551[label="id:1551\lwg:23\l"]; +node1551 -- node1552 +node1552[label="id:1552\lwg:31\l"]; +node1553[label="id:1553\lwg:20\l"]; +node1553 -- node1554 +node1554[label="id:1554\lwg:43\l"]; +node1555[label="id:1555\lwg:50\l"]; +node1555 -- node1556 +node1555 -- node1558 +node1555 -- node1566 +node1556[label="id:1556\lwg:19\l"]; +node1556 -- node1557 +node1557[label="id:1557\lwg:4\l"]; +node1558[label="id:1558\lwg:30\l"]; +node1558 -- node1559 +node1558 -- node1560 +node1558 -- node1563 +node1559[label="id:1559\lwg:13\l"]; +node1560[label="id:1560\lwg:26\l"]; +node1560 -- node1561 +node1561[label="id:1561\lwg:27\l"]; +node1561 -- node1562 +node1562[label="id:1562\lwg:33\l"]; +node1563[label="id:1563\lwg:1\l"]; +node1563 -- node1564 +node1564[label="id:1564\lwg:43\l"]; +node1564 -- node1565 +node1565[label="id:1565\lwg:30\l"]; +node1566[label="id:1566\lwg:1\l"]; +node1566 -- node1567 +node1566 -- node1570 +node1566 -- node1573 +node1567[label="id:1567\lwg:27\l"]; +node1567 -- node1568 +node1568[label="id:1568\lwg:5\l"]; +node1568 -- node1569 +node1569[label="id:1569\lwg:32\l"]; +node1570[label="id:1570\lwg:39\l"]; +node1570 -- node1571 +node1571[label="id:1571\lwg:14\l"]; +node1571 -- node1572 +node1572[label="id:1572\lwg:31\l"]; +node1573[label="id:1573\lwg:49\l"]; +node1573 -- node1574 +node1574[label="id:1574\lwg:19\l"]; +node1574 -- node1575 +node1575[label="id:1575\lwg:35\l"]; +node1576[label="id:1576\lwg:26\l"]; +node1576 -- node1577 +node1576 -- node1578 +node1576 -- node1587 +node1577[label="id:1577\lwg:9\l"]; +node1578[label="id:1578\lwg:9\l"]; +node1578 -- node1579 +node1578 -- node1583 +node1578 -- node1584 +node1579[label="id:1579\lwg:37\l"]; +node1579 -- node1580 +node1579 -- node1581 +node1580[label="id:1580\lwg:4\l"]; +node1581[label="id:1581\lwg:16\l"]; +node1581 -- node1582 +node1582[label="id:1582\lwg:22\l"]; +node1583[label="id:1583\lwg:37\l"]; +node1584[label="id:1584\lwg:39\l"]; +node1584 -- node1585 +node1584 -- node1586 +node1585[label="id:1585\lwg:27\l"]; +node1586[label="id:1586\lwg:4\l"]; +node1587[label="id:1587\lwg:38\l"]; +node1587 -- node1588 +node1587 -- node1591 +node1587 -- node1594 +node1588[label="id:1588\lwg:9\l"]; +node1588 -- node1589 +node1589[label="id:1589\lwg:47\l"]; +node1589 -- node1590 +node1590[label="id:1590\lwg:50\l"]; +node1591[label="id:1591\lwg:23\l"]; +node1591 -- node1592 +node1591 -- node1593 +node1592[label="id:1592\lwg:44\l"]; +node1593[label="id:1593\lwg:33\l"]; +node1594[label="id:1594\lwg:41\l"]; +node1594 -- node1595 +node1595[label="id:1595\lwg:6\l"]; +node1596[label="id:1596\lwg:39\l"]; +node1597[label="id:1597\lwg:1\l"]; +node1597 -- node1598 +node1597 -- node1632 +node1598[label="id:1598\lwg:17\l"]; +node1598 -- node1599 +node1598 -- node1618 +node1598 -- node1623 +node1599[label="id:1599\lwg:39\l"]; +node1599 -- node1600 +node1599 -- node1601 +node1599 -- node1609 +node1599 -- node1617 +node1600[label="id:1600\lwg:10\l"]; +node1601[label="id:1601\lwg:36\l"]; +node1601 -- node1602 +node1601 -- node1605 +node1602[label="id:1602\lwg:9\l"]; +node1602 -- node1603 +node1602 -- node1604 +node1603[label="id:1603\lwg:2\l"]; +node1604[label="id:1604\lwg:12\l"]; +node1605[label="id:1605\lwg:46\l"]; +node1605 -- node1606 +node1605 -- node1607 +node1606[label="id:1606\lwg:30\l"]; +node1607[label="id:1607\lwg:37\l"]; +node1607 -- node1608 +node1608[label="id:1608\lwg:2\l"]; +node1609[label="id:1609\lwg:26\l"]; +node1609 -- node1610 +node1609 -- node1614 +node1610[label="id:1610\lwg:44\l"]; +node1610 -- node1611 +node1610 -- node1612 +node1611[label="id:1611\lwg:39\l"]; +node1612[label="id:1612\lwg:6\l"]; +node1612 -- node1613 +node1613[label="id:1613\lwg:47\l"]; +node1614[label="id:1614\lwg:30\l"]; +node1614 -- node1615 +node1614 -- node1616 +node1615[label="id:1615\lwg:28\l"]; +node1616[label="id:1616\lwg:4\l"]; +node1617[label="id:1617\lwg:7\l"]; +node1618[label="id:1618\lwg:37\l"]; +node1618 -- node1619 +node1619[label="id:1619\lwg:30\l"]; +node1619 -- node1620 +node1620[label="id:1620\lwg:7\l"]; +node1620 -- node1621 +node1620 -- node1622 +node1621[label="id:1621\lwg:10\l"]; +node1622[label="id:1622\lwg:46\l"]; +node1623[label="id:1623\lwg:11\l"]; +node1623 -- node1624 +node1623 -- node1625 +node1623 -- node1631 +node1624[label="id:1624\lwg:21\l"]; +node1625[label="id:1625\lwg:42\l"]; +node1625 -- node1626 +node1625 -- node1630 +node1626[label="id:1626\lwg:23\l"]; +node1626 -- node1627 +node1626 -- node1629 +node1627[label="id:1627\lwg:49\l"]; +node1627 -- node1628 +node1628[label="id:1628\lwg:23\l"]; +node1629[label="id:1629\lwg:1\l"]; +node1630[label="id:1630\lwg:32\l"]; +node1631[label="id:1631\lwg:47\l"]; +node1632[label="id:1632\lwg:45\l"]; +node1633[label="id:1633\lwg:48\l"]; +node1633 -- node1634 +node1633 -- node1671 +node1633 -- node1695 +node1633 -- node1736 +node1634[label="id:1634\lwg:13\l"]; +node1634 -- node1635 +node1634 -- node1639 +node1634 -- node1670 +node1635[label="id:1635\lwg:33\l"]; +node1635 -- node1636 +node1635 -- node1637 +node1635 -- node1638 +node1636[label="id:1636\lwg:6\l"]; +node1637[label="id:1637\lwg:7\l"]; +node1638[label="id:1638\lwg:43\l"]; +node1639[label="id:1639\lwg:2\l"]; +node1639 -- node1640 +node1639 -- node1649 +node1639 -- node1661 +node1639 -- node1667 +node1640[label="id:1640\lwg:10\l"]; +node1640 -- node1641 +node1640 -- node1644 +node1641[label="id:1641\lwg:31\l"]; +node1641 -- node1642 +node1642[label="id:1642\lwg:29\l"]; +node1642 -- node1643 +node1643[label="id:1643\lwg:10\l"]; +node1644[label="id:1644\lwg:26\l"]; +node1644 -- node1645 +node1644 -- node1647 +node1645[label="id:1645\lwg:6\l"]; +node1645 -- node1646 +node1646[label="id:1646\lwg:42\l"]; +node1647[label="id:1647\lwg:43\l"]; +node1647 -- node1648 +node1648[label="id:1648\lwg:7\l"]; +node1649[label="id:1649\lwg:22\l"]; +node1649 -- node1650 +node1649 -- node1653 +node1649 -- node1658 +node1650[label="id:1650\lwg:20\l"]; +node1650 -- node1651 +node1651[label="id:1651\lwg:39\l"]; +node1651 -- node1652 +node1652[label="id:1652\lwg:48\l"]; +node1653[label="id:1653\lwg:28\l"]; +node1653 -- node1654 +node1653 -- node1656 +node1654[label="id:1654\lwg:17\l"]; +node1654 -- node1655 +node1655[label="id:1655\lwg:7\l"]; +node1656[label="id:1656\lwg:27\l"]; +node1656 -- node1657 +node1657[label="id:1657\lwg:7\l"]; +node1658[label="id:1658\lwg:17\l"]; +node1658 -- node1659 +node1659[label="id:1659\lwg:9\l"]; +node1659 -- node1660 +node1660[label="id:1660\lwg:30\l"]; +node1661[label="id:1661\lwg:48\l"]; +node1661 -- node1662 +node1661 -- node1663 +node1662[label="id:1662\lwg:18\l"]; +node1663[label="id:1663\lwg:11\l"]; +node1663 -- node1664 +node1663 -- node1666 +node1664[label="id:1664\lwg:33\l"]; +node1664 -- node1665 +node1665[label="id:1665\lwg:44\l"]; +node1666[label="id:1666\lwg:38\l"]; +node1667[label="id:1667\lwg:27\l"]; +node1667 -- node1668 +node1667 -- node1669 +node1668[label="id:1668\lwg:30\l"]; +node1669[label="id:1669\lwg:27\l"]; +node1670[label="id:1670\lwg:38\l"]; +node1671[label="id:1671\lwg:21\l"]; +node1671 -- node1672 +node1671 -- node1689 +node1672[label="id:1672\lwg:21\l"]; +node1672 -- node1673 +node1672 -- node1674 +node1672 -- node1679 +node1672 -- node1680 +node1673[label="id:1673\lwg:21\l"]; +node1674[label="id:1674\lwg:49\l"]; +node1674 -- node1675 +node1674 -- node1678 +node1675[label="id:1675\lwg:31\l"]; +node1675 -- node1676 +node1676[label="id:1676\lwg:46\l"]; +node1676 -- node1677 +node1677[label="id:1677\lwg:2\l"]; +node1678[label="id:1678\lwg:20\l"]; +node1679[label="id:1679\lwg:41\l"]; +node1680[label="id:1680\lwg:48\l"]; +node1680 -- node1681 +node1680 -- node1683 +node1680 -- node1684 +node1681[label="id:1681\lwg:6\l"]; +node1681 -- node1682 +node1682[label="id:1682\lwg:18\l"]; +node1683[label="id:1683\lwg:20\l"]; +node1684[label="id:1684\lwg:42\l"]; +node1684 -- node1685 +node1684 -- node1687 +node1685[label="id:1685\lwg:44\l"]; +node1685 -- node1686 +node1686[label="id:1686\lwg:32\l"]; +node1687[label="id:1687\lwg:46\l"]; +node1687 -- node1688 +node1688[label="id:1688\lwg:45\l"]; +node1689[label="id:1689\lwg:40\l"]; +node1689 -- node1690 +node1689 -- node1691 +node1690[label="id:1690\lwg:49\l"]; +node1691[label="id:1691\lwg:22\l"]; +node1691 -- node1692 +node1692[label="id:1692\lwg:50\l"]; +node1692 -- node1693 +node1692 -- node1694 +node1693[label="id:1693\lwg:11\l"]; +node1694[label="id:1694\lwg:41\l"]; +node1695[label="id:1695\lwg:24\l"]; +node1695 -- node1696 +node1695 -- node1712 +node1695 -- node1729 +node1695 -- node1730 +node1696[label="id:1696\lwg:38\l"]; +node1696 -- node1697 +node1696 -- node1699 +node1696 -- node1709 +node1697[label="id:1697\lwg:23\l"]; +node1697 -- node1698 +node1698[label="id:1698\lwg:16\l"]; +node1699[label="id:1699\lwg:4\l"]; +node1699 -- node1700 +node1699 -- node1703 +node1699 -- node1706 +node1700[label="id:1700\lwg:41\l"]; +node1700 -- node1701 +node1701[label="id:1701\lwg:38\l"]; +node1701 -- node1702 +node1702[label="id:1702\lwg:13\l"]; +node1703[label="id:1703\lwg:25\l"]; +node1703 -- node1704 +node1703 -- node1705 +node1704[label="id:1704\lwg:3\l"]; +node1705[label="id:1705\lwg:1\l"]; +node1706[label="id:1706\lwg:38\l"]; +node1706 -- node1707 +node1707[label="id:1707\lwg:47\l"]; +node1707 -- node1708 +node1708[label="id:1708\lwg:1\l"]; +node1709[label="id:1709\lwg:9\l"]; +node1709 -- node1710 +node1709 -- node1711 +node1710[label="id:1710\lwg:13\l"]; +node1711[label="id:1711\lwg:31\l"]; +node1712[label="id:1712\lwg:16\l"]; +node1712 -- node1713 +node1712 -- node1716 +node1712 -- node1720 +node1712 -- node1725 +node1713[label="id:1713\lwg:7\l"]; +node1713 -- node1714 +node1714[label="id:1714\lwg:47\l"]; +node1714 -- node1715 +node1715[label="id:1715\lwg:41\l"]; +node1716[label="id:1716\lwg:10\l"]; +node1716 -- node1717 +node1717[label="id:1717\lwg:11\l"]; +node1717 -- node1718 +node1718[label="id:1718\lwg:13\l"]; +node1718 -- node1719 +node1719[label="id:1719\lwg:33\l"]; +node1720[label="id:1720\lwg:6\l"]; +node1720 -- node1721 +node1720 -- node1722 +node1721[label="id:1721\lwg:18\l"]; +node1722[label="id:1722\lwg:11\l"]; +node1722 -- node1723 +node1723[label="id:1723\lwg:34\l"]; +node1723 -- node1724 +node1724[label="id:1724\lwg:24\l"]; +node1725[label="id:1725\lwg:5\l"]; +node1725 -- node1726 +node1726[label="id:1726\lwg:28\l"]; +node1726 -- node1727 +node1727[label="id:1727\lwg:37\l"]; +node1727 -- node1728 +node1728[label="id:1728\lwg:39\l"]; +node1729[label="id:1729\lwg:29\l"]; +node1730[label="id:1730\lwg:8\l"]; +node1730 -- node1731 +node1731[label="id:1731\lwg:26\l"]; +node1731 -- node1732 +node1732[label="id:1732\lwg:48\l"]; +node1732 -- node1733 +node1732 -- node1734 +node1733[label="id:1733\lwg:42\l"]; +node1734[label="id:1734\lwg:26\l"]; +node1734 -- node1735 +node1735[label="id:1735\lwg:27\l"]; +node1736[label="id:1736\lwg:11\l"]; +node1737[label="id:1737\lwg:25\l"]; +node1737 -- node1738 +node1737 -- node1765 +node1737 -- node1774 +node1737 -- node1806 +node1738[label="id:1738\lwg:9\l"]; +node1738 -- node1739 +node1738 -- node1743 +node1739[label="id:1739\lwg:35\l"]; +node1739 -- node1740 +node1739 -- node1742 +node1740[label="id:1740\lwg:2\l"]; +node1740 -- node1741 +node1741[label="id:1741\lwg:21\l"]; +node1742[label="id:1742\lwg:26\l"]; +node1743[label="id:1743\lwg:26\l"]; +node1743 -- node1744 +node1743 -- node1755 +node1743 -- node1764 +node1744[label="id:1744\lwg:4\l"]; +node1744 -- node1745 +node1744 -- node1749 +node1744 -- node1753 +node1745[label="id:1745\lwg:3\l"]; +node1745 -- node1746 +node1745 -- node1747 +node1746[label="id:1746\lwg:25\l"]; +node1747[label="id:1747\lwg:29\l"]; +node1747 -- node1748 +node1748[label="id:1748\lwg:16\l"]; +node1749[label="id:1749\lwg:34\l"]; +node1749 -- node1750 +node1749 -- node1751 +node1750[label="id:1750\lwg:48\l"]; +node1751[label="id:1751\lwg:25\l"]; +node1751 -- node1752 +node1752[label="id:1752\lwg:5\l"]; +node1753[label="id:1753\lwg:32\l"]; +node1753 -- node1754 +node1754[label="id:1754\lwg:9\l"]; +node1755[label="id:1755\lwg:48\l"]; +node1755 -- node1756 +node1755 -- node1757 +node1755 -- node1760 +node1756[label="id:1756\lwg:7\l"]; +node1757[label="id:1757\lwg:43\l"]; +node1757 -- node1758 +node1758[label="id:1758\lwg:28\l"]; +node1758 -- node1759 +node1759[label="id:1759\lwg:48\l"]; +node1760[label="id:1760\lwg:25\l"]; +node1760 -- node1761 +node1760 -- node1763 +node1761[label="id:1761\lwg:44\l"]; +node1761 -- node1762 +node1762[label="id:1762\lwg:29\l"]; +node1763[label="id:1763\lwg:23\l"]; +node1764[label="id:1764\lwg:47\l"]; +node1765[label="id:1765\lwg:39\l"]; +node1765 -- node1766 +node1766[label="id:1766\lwg:17\l"]; +node1766 -- node1767 +node1766 -- node1771 +node1766 -- node1773 +node1767[label="id:1767\lwg:4\l"]; +node1767 -- node1768 +node1768[label="id:1768\lwg:15\l"]; +node1768 -- node1769 +node1768 -- node1770 +node1769[label="id:1769\lwg:37\l"]; +node1770[label="id:1770\lwg:3\l"]; +node1771[label="id:1771\lwg:37\l"]; +node1771 -- node1772 +node1772[label="id:1772\lwg:3\l"]; +node1773[label="id:1773\lwg:42\l"]; +node1774[label="id:1774\lwg:2\l"]; +node1774 -- node1775 +node1774 -- node1805 +node1775[label="id:1775\lwg:16\l"]; +node1775 -- node1776 +node1775 -- node1789 +node1775 -- node1791 +node1776[label="id:1776\lwg:40\l"]; +node1776 -- node1777 +node1776 -- node1781 +node1776 -- node1786 +node1777[label="id:1777\lwg:29\l"]; +node1777 -- node1778 +node1777 -- node1779 +node1778[label="id:1778\lwg:35\l"]; +node1779[label="id:1779\lwg:17\l"]; +node1779 -- node1780 +node1780[label="id:1780\lwg:9\l"]; +node1781[label="id:1781\lwg:27\l"]; +node1781 -- node1782 +node1781 -- node1784 +node1782[label="id:1782\lwg:22\l"]; +node1782 -- node1783 +node1783[label="id:1783\lwg:50\l"]; +node1784[label="id:1784\lwg:18\l"]; +node1784 -- node1785 +node1785[label="id:1785\lwg:13\l"]; +node1786[label="id:1786\lwg:22\l"]; +node1786 -- node1787 +node1786 -- node1788 +node1787[label="id:1787\lwg:32\l"]; +node1788[label="id:1788\lwg:33\l"]; +node1789[label="id:1789\lwg:9\l"]; +node1789 -- node1790 +node1790[label="id:1790\lwg:12\l"]; +node1791[label="id:1791\lwg:13\l"]; +node1791 -- node1792 +node1791 -- node1797 +node1791 -- node1802 +node1792[label="id:1792\lwg:34\l"]; +node1792 -- node1793 +node1792 -- node1795 +node1793[label="id:1793\lwg:22\l"]; +node1793 -- node1794 +node1794[label="id:1794\lwg:43\l"]; +node1795[label="id:1795\lwg:1\l"]; +node1795 -- node1796 +node1796[label="id:1796\lwg:46\l"]; +node1797[label="id:1797\lwg:32\l"]; +node1797 -- node1798 +node1797 -- node1800 +node1798[label="id:1798\lwg:10\l"]; +node1798 -- node1799 +node1799[label="id:1799\lwg:5\l"]; +node1800[label="id:1800\lwg:22\l"]; +node1800 -- node1801 +node1801[label="id:1801\lwg:1\l"]; +node1802[label="id:1802\lwg:21\l"]; +node1802 -- node1803 +node1802 -- node1804 +node1803[label="id:1803\lwg:21\l"]; +node1804[label="id:1804\lwg:8\l"]; +node1805[label="id:1805\lwg:38\l"]; +node1806[label="id:1806\lwg:4\l"]; +node1806 -- node1807 +node1806 -- node1808 +node1806 -- node1824 +node1806 -- node1833 +node1807[label="id:1807\lwg:24\l"]; +node1808[label="id:1808\lwg:44\l"]; +node1808 -- node1809 +node1808 -- node1818 +node1808 -- node1820 +node1808 -- node1821 +node1809[label="id:1809\lwg:8\l"]; +node1809 -- node1810 +node1809 -- node1813 +node1810[label="id:1810\lwg:36\l"]; +node1810 -- node1811 +node1811[label="id:1811\lwg:40\l"]; +node1811 -- node1812 +node1812[label="id:1812\lwg:37\l"]; +node1813[label="id:1813\lwg:1\l"]; +node1813 -- node1814 +node1813 -- node1816 +node1814[label="id:1814\lwg:7\l"]; +node1814 -- node1815 +node1815[label="id:1815\lwg:27\l"]; +node1816[label="id:1816\lwg:26\l"]; +node1816 -- node1817 +node1817[label="id:1817\lwg:22\l"]; +node1818[label="id:1818\lwg:12\l"]; +node1818 -- node1819 +node1819[label="id:1819\lwg:3\l"]; +node1820[label="id:1820\lwg:23\l"]; +node1821[label="id:1821\lwg:41\l"]; +node1821 -- node1822 +node1822[label="id:1822\lwg:42\l"]; +node1822 -- node1823 +node1823[label="id:1823\lwg:18\l"]; +node1824[label="id:1824\lwg:13\l"]; +node1824 -- node1825 +node1824 -- node1826 +node1824 -- node1827 +node1824 -- node1831 +node1825[label="id:1825\lwg:22\l"]; +node1826[label="id:1826\lwg:36\l"]; +node1827[label="id:1827\lwg:34\l"]; +node1827 -- node1828 +node1828[label="id:1828\lwg:37\l"]; +node1828 -- node1829 +node1829[label="id:1829\lwg:22\l"]; +node1829 -- node1830 +node1830[label="id:1830\lwg:40\l"]; +node1831[label="id:1831\lwg:22\l"]; +node1831 -- node1832 +node1832[label="id:1832\lwg:29\l"]; +node1833[label="id:1833\lwg:15\l"]; +node1833 -- node1834 +node1833 -- node1838 +node1834[label="id:1834\lwg:35\l"]; +node1834 -- node1835 +node1835[label="id:1835\lwg:12\l"]; +node1835 -- node1836 +node1836[label="id:1836\lwg:8\l"]; +node1836 -- node1837 +node1837[label="id:1837\lwg:38\l"]; +node1838[label="id:1838\lwg:21\l"]; +node1838 -- node1839 +node1839[label="id:1839\lwg:38\l"]; +node1840[label="id:1840\lwg:33\l"]; +node1840 -- node1841 +node1841[label="id:1841\lwg:35\l"]; +node1841 -- node1842 +node1842[label="id:1842\lwg:27\l"]; +node1842 -- node1843 +node1842 -- node1853 +node1842 -- node1858 +node1842 -- node1863 +node1843[label="id:1843\lwg:44\l"]; +node1843 -- node1844 +node1843 -- node1846 +node1843 -- node1849 +node1844[label="id:1844\lwg:3\l"]; +node1844 -- node1845 +node1845[label="id:1845\lwg:7\l"]; +node1846[label="id:1846\lwg:14\l"]; +node1846 -- node1847 +node1847[label="id:1847\lwg:11\l"]; +node1847 -- node1848 +node1848[label="id:1848\lwg:20\l"]; +node1849[label="id:1849\lwg:34\l"]; +node1849 -- node1850 +node1849 -- node1851 +node1850[label="id:1850\lwg:45\l"]; +node1851[label="id:1851\lwg:16\l"]; +node1851 -- node1852 +node1852[label="id:1852\lwg:2\l"]; +node1853[label="id:1853\lwg:6\l"]; +node1853 -- node1854 +node1853 -- node1856 +node1854[label="id:1854\lwg:11\l"]; +node1854 -- node1855 +node1855[label="id:1855\lwg:6\l"]; +node1856[label="id:1856\lwg:4\l"]; +node1856 -- node1857 +node1857[label="id:1857\lwg:14\l"]; +node1858[label="id:1858\lwg:10\l"]; +node1858 -- node1859 +node1859[label="id:1859\lwg:44\l"]; +node1859 -- node1860 +node1859 -- node1861 +node1860[label="id:1860\lwg:23\l"]; +node1861[label="id:1861\lwg:7\l"]; +node1861 -- node1862 +node1862[label="id:1862\lwg:31\l"]; +node1863[label="id:1863\lwg:31\l"]; +node1863 -- node1864 +node1863 -- node1869 +node1864[label="id:1864\lwg:46\l"]; +node1864 -- node1865 +node1864 -- node1867 +node1865[label="id:1865\lwg:9\l"]; +node1865 -- node1866 +node1866[label="id:1866\lwg:13\l"]; +node1867[label="id:1867\lwg:46\l"]; +node1867 -- node1868 +node1868[label="id:1868\lwg:30\l"]; +node1869[label="id:1869\lwg:37\l"]; +node1870[label="id:1870\lwg:46\l"]; +} \ No newline at end of file diff --git a/BE_OpenMP_2021/.vscode/settings.json b/BE_OpenMP_2021/.vscode/settings.json new file mode 100644 index 0000000..9792498 --- /dev/null +++ b/BE_OpenMP_2021/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.formatOnSave": false +} \ No newline at end of file diff --git a/BE_OpenMP_2021/Makefile b/BE_OpenMP_2021/Makefile new file mode 100644 index 0000000..7ffa55e --- /dev/null +++ b/BE_OpenMP_2021/Makefile @@ -0,0 +1,13 @@ +clean: + (cd butterfly; make clean) + (cd neural_network; make clean) + (cd norm2; make clean) + (cd pipelining; make clean) + (cd tree_bottomup; make clean) + + + + + + + diff --git a/BE_OpenMP_2021/butterfly/Makefile b/BE_OpenMP_2021/butterfly/Makefile new file mode 100644 index 0000000..53dfbb6 --- /dev/null +++ b/BE_OpenMP_2021/butterfly/Makefile @@ -0,0 +1,31 @@ +CC = gcc +LINK = $(CC) + +CFLAGS = -O3 -fopenmp -Wunknown-pragmas +# CFLAGS = -g -fopenmp +LDFLAGS = $(CFLAGS) +LIBS = -lm + +OBJS = aux.o main.o + +main: $(OBJS) + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + + + + + + +clean: + (rm -f *.o main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< + + + + diff --git a/BE_OpenMP_2021/butterfly/aux.c b/BE_OpenMP_2021/butterfly/aux.c new file mode 100644 index 0000000..7d25f7b --- /dev/null +++ b/BE_OpenMP_2021/butterfly/aux.c @@ -0,0 +1,72 @@ +#include "aux.h" + +void generate_array(int n, int **array, int *res){ + + int i; + + *res = 0; + + *array = (int*)malloc(n*sizeof(int)); + + for(i=0; i +#include +#include +#include +#include +#include + +#define MIN(a,b) (((a)<(b))?(a):(b)) + + +int operator(int a, int b); +void generate_array(int n, int **array, int *res); +void mysleep(double t); +long usecs (); +void check_result(int n, int *array, int res); + + diff --git a/BE_OpenMP_2021/butterfly/main.c b/BE_OpenMP_2021/butterfly/main.c new file mode 100644 index 0000000..311c29b --- /dev/null +++ b/BE_OpenMP_2021/butterfly/main.c @@ -0,0 +1,146 @@ +#include "aux.h" + +void butterfly_seq(int n, int l, int *array); +void butterfly_par(int n, int l, int *array); + +int main(int argc, char **argv) +{ + long t_start, t_end; + int i, n, l, res; + int *array_seq, *array_par; + + if (argc == 2) + { + l = atoi(argv[1]); + } + else + { + printf("Usage:\n\n ./main l\n\nwhere l defines the size of the array n=2^l.\n"); + return 1; + } + + n = pow(2, l); + + printf("\nGenerating an array with %d elements\n", n); + generate_array(n, &array_seq, &res); + + array_par = (int *)malloc(n * sizeof(int)); + for (i = 0; i < n; i++) + array_par[i] = array_seq[i]; + + if (n <= 32) + { + printf("array_seq=["); + for (i = 0; i < n; i++) + { + printf("%d ", array_seq[i]); + } + printf("]\n"); + } + printf("The expected result is : %d\n\n\n\n", res); + + t_start = usecs(); + butterfly_seq(n, l, array_seq); + t_end = usecs(); + + printf("Sequential time : %8.2f msec.\n", ((double)t_end - t_start) / 1000.0); + + if (n <= 32) + { + printf("The result of the sequential reduction is\n"); + printf("array_seq=["); + for (i = 0; i < n; i++) + printf("%d ", array_seq[i]); + printf("]\n"); + } + printf("\n\n\n"); + + t_start = usecs(); + butterfly_par(n, l, array_par); + t_end = usecs(); + + printf("Parallel time : %8.2f msec.\n", ((double)t_end - t_start) / 1000.0); + + if (n <= 32) + { + printf("The result of the parallel reduction is\n"); + printf("array_par=["); + for (i = 0; i < n; i++) + printf("%d ", array_par[i]); + printf("]\n\n"); + } + + check_result(n, array_par, res); +} + +void butterfly_seq(int n, int l, int *array) +{ + + int p, i, j, s; + + p = 0; + + while (p < l) + { + s = pow(2, p); + for (i = 0; i < n; i += 2 * s) + { + for (j = 0; j < s; j++) + { + int r = operator(array[i + j], array[i + j + s]); + array[i + j] = r; + array[i + j + s] = r; + } + } + p += 1; + } +} + +// void butterfly_par(int n, int l, int *array){ + +// int p, i, j, s; + +// p = 0; + +// while(p +#include +#include +#include +#include +#include "aux.h" + +int ISEED[4] = {0,0,0,1}; +int IONE=1; +char NoTran = 'N'; +double DONE=1.0, DMONE=-1.0; +double alpha=1.0, beta=0.0; + +void init_data(layer **L, data **Ds, data **Dpl, data **Dpt, int n, int m, int l){ + + int i, j, lay, mm; + + *L = (layer*) malloc(l*sizeof(layer)); + *Ds = (data*) malloc((l+1)*sizeof(data)); + *Dpl = (data*) malloc((l+1)*sizeof(data)); + *Dpt = (data*) malloc((l+1)*sizeof(data)); + + + mm = m*m; + + + for(lay=0; lay mx) + mx = fabs((X1[i].b)[k]-(X2[i].b)[k])/fabs((X1[i].b)[k]); + } + } + + printf("The maximum difference on coefficients is %e\n",mx); + +} + + + +long usecs (){ + struct timeval t; + + gettimeofday(&t,NULL); + return t.tv_sec*1000000+t.tv_usec; +} diff --git a/BE_OpenMP_2021/neural_network/aux.h b/BE_OpenMP_2021/neural_network/aux.h new file mode 100644 index 0000000..f578aef --- /dev/null +++ b/BE_OpenMP_2021/neural_network/aux.h @@ -0,0 +1,30 @@ +struct { + double *b; +} typedef block; + +struct { + block **W, *b; +} typedef layer; + +struct { + block *X; +} typedef data; + + + +void block_mult(block a, block b, block c, int nb); +void block_bias_act(block a, block b, int nb); +void init_data(layer **L, data **Ds, data **Dpl, data **Dpt, int n, int nb, int l); +long usecs (); +void compare_output(block *X1, block *, int n, int nb); + +void dgemm_ (char *TRANSA, char *TRANSB, + int *M, int *N, int *K, + double *ALPHA, + double *A, int *LDA, + double *B, int *LDB, + double *BETA, + double *C, int *LDC); + +void dlarnv_(int *idist, int *iseed, int *n, double *x); +void dcopy_(int *n, double *x, int *ix, double *y, int *iy); diff --git a/BE_OpenMP_2021/neural_network/main.c b/BE_OpenMP_2021/neural_network/main.c new file mode 100644 index 0000000..5399002 --- /dev/null +++ b/BE_OpenMP_2021/neural_network/main.c @@ -0,0 +1,129 @@ +#include +#include +#include +#include +#include +#include "omp.h" +#include "aux.h" + +void sequential_nn(layer *Layers, data *D, int n, int m, int L); +void parallel_nn_loops(layer *Layers, data *D, int n, int m, int L); +void parallel_nn_tasks(layer *Layers, data *D, int n, int m, int L); + +int main(int argc, char **argv) +{ + int n, m, N, L; + long t_start, t_end; + layer *Layers; + data *Datas_s, *Datas_pl, *Datas_pt; + + // Command line arguments + if (argc == 4) + { + n = atoi(argv[1]); /* size of layer matrix n */ + m = atoi(argv[2]); /* size of batch */ + L = atoi(argv[3]); /* number of layers in the network */ + } + else + { + printf("Usage:\n\n ./main n m L\n\nsuch that nxm is the size of the layers and L is the number of layers and m is the batch size.\n"); + return 1; + } + + N = (n / m); + + init_data(&Layers, &Datas_s, &Datas_pl, &Datas_pt, N, m, L); + + /* Sequential version */ + t_start = usecs(); + sequential_nn(Layers, Datas_s, N, m, L); + t_end = usecs(); + printf("Sequential time : %8.2f msec.\n", ((double)t_end - t_start) / 1000.0); + + /* Parallel with loops */ + t_start = usecs(); + parallel_nn_loops(Layers, Datas_pl, N, m, L); + t_end = usecs(); + printf("Parallel loops time : %8.2f msec. ", ((double)t_end - t_start) / 1000.0); + /* Comprare the two resulting outputs */ + compare_output(Datas_s[L].X, Datas_pl[L].X, N, m); + + /* Parallel with tasks */ + t_start = usecs(); + parallel_nn_tasks(Layers, Datas_pt, N, m, L); + t_end = usecs(); + printf("Parallel tasks time : %8.2f msec. ", ((double)t_end - t_start) / 1000.0); + /* Comprare the two resulting outputs */ + compare_output(Datas_s[L].X, Datas_pt[L].X, N, m); + + return 0; +} + +void sequential_nn(layer *Layers, data *Datas, int N, int m, int L) +{ + int i, j, k, l; + + for (l = 0; l < L; l++) + { + for (i = 0; i < N; i++) + for (j = 0; j < N; j++) + { + block_mult(Layers[l].W[i][j], Datas[l].X[j], Datas[l + 1].X[i], m); + } + + for (i = 0; i < N; i++) + block_bias_act(Layers[l].b[i], Datas[l + 1].X[i], m); + } +} + +void parallel_nn_loops(layer *Layers, data *Datas, int N, int m, int L) +{ + int i, j, l; + +#pragma omp parallel private(i, j, l) + + for (l = 0; l < L; l++) + { + +#pragma omp for + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + block_mult(Layers[l].W[i][j], Datas[l].X[j], Datas[l + 1].X[i], m); + } + } + +#pragma omp for + for (i = 0; i < N; i++) + { + block_bias_act(Layers[l].b[i], Datas[l + 1].X[i], m); + } + + } +} + +void parallel_nn_tasks(layer *Layers, data *Datas, int N, int m, int L) +{ + int i, j, l; + +#pragma omp parallel +#pragma omp master + + for (l = 0; l < L; l++) + { + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { +#pragma omp task firstprivate(i, j, l) depend(in: Datas[l].X[j]) depend(inout: Datas[l + 1].X[i]) + block_mult(Layers[l].W[i][j], Datas[l].X[j], Datas[l + 1].X[i], m); + } + for (i = 0; i < N; i++) + { +#pragma omp task firstprivate(i, l) depend(inout: Datas[l + 1].X[i]) + block_bias_act(Layers[l].b[i], Datas[l + 1].X[i], m); + } + } + } +} diff --git a/BE_OpenMP_2021/neural_network/subject.pdf b/BE_OpenMP_2021/neural_network/subject.pdf new file mode 100644 index 0000000..aa047aa Binary files /dev/null and b/BE_OpenMP_2021/neural_network/subject.pdf differ diff --git a/BE_OpenMP_2021/norm2/Makefile b/BE_OpenMP_2021/norm2/Makefile new file mode 100644 index 0000000..4ae3d4a --- /dev/null +++ b/BE_OpenMP_2021/norm2/Makefile @@ -0,0 +1,31 @@ +CC = gcc +LINK = $(CC) + +CFLAGS = -O3 -fopenmp +# CFLAGS = -g -fopenmp +LDFLAGS = $(CFLAGS) +LIBS = -lm + +OBJS = main.o + +main: $(OBJS) + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + + + + + + +clean: + (rm -f *.o main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< + + + + diff --git a/BE_OpenMP_2021/norm2/main.c b/BE_OpenMP_2021/norm2/main.c new file mode 100644 index 0000000..71fe087 --- /dev/null +++ b/BE_OpenMP_2021/norm2/main.c @@ -0,0 +1,139 @@ +#include +#include +#include +#include +#include + +long usecs (){ + struct timeval t; + + gettimeofday(&t,NULL); + return t.tv_sec*1000000+t.tv_usec; +} + +double dnorm2_seq(double *x, int n); +double dnorm2_par_red(double *x, int n); +double dnorm2_par_nored(double *x, int n); + + +int main(int argc, char *argv[]){ + + int n, i; + double *x; + double n2_seq, n2_par_red, n2_par_nored; + long t_start,t_end; + + + if(argc!=2){ + printf("Wrong number of arguments.\n Usage:\n\n\ +./main n \n\n where n is the size of the vector x whose 2-norm has to be computed.\n"); + return 1; + } + + + sscanf(argv[1],"%d",&n); + + + x = (double*)malloc(sizeof(double)*n); + + for(i=0; i 1e-10) { + printf("The parallel version with reduction is numerically wrong! \n"); + } else { + printf("The parallel version with reduction is numerically okay!\n"); + } + + if(fabs(n2_seq-n2_par_nored)/n2_seq > 1e-10) { + printf("The parallel version without reduction is numerically wrong!\n"); + } else { + printf("The parallel version without reduction is numerically okay!\n"); + } + + return 0; + +} + + + +double dnorm2_seq(double *x, int n){ + int i; + double res; + + res = 0.0; + + for(i=0; i +#include +#include +#include +#include +#include "aux.h" +#include "omp.h" + + +long usecs (){ + struct timeval t; + + gettimeofday(&t,NULL); + return t.tv_sec*1000000+t.tv_usec; +} + + + +void mysleep(double sec){ + + long s, e; + s=0; e=0; + s = usecs(); + while(((double) e-s)/1000000 < sec) + { + e = usecs(); + } + return; +} + + +void init_data(data **datas, resource **resources, int ndatas, int nsteps){ + + int d, s; + + *datas = (data*) malloc(ndatas*sizeof(data)); + *resources = (resource*) malloc(nsteps*sizeof(resource)); + + for (d=0; dbusy == -9){ + r->busy = omp_get_thread_num(); + if(r->i != s) { + printf("Error!!! trying to use resource %d for step %d.\n",r->i,s); + r->busy = -9; + return; + } + + if(datas[d].i == s-1){ + t = 0.2/((double)r->nr); + mysleep(t); + datas[d].i = s; + datas[d].v = datas[d].v*2 + s; + } else { + printf("Error!!! trying step %d on data %d but step %d is not done.\n",s,d,s-1); + r->busy = -9; + return; + } + r->busy = -9; + } else { + printf("Error!!! trying to use resource %d but it is busy.\n",r->i); + } + +} + + +void check_result(data *datas, int ndatas, int nsteps){ + + int d, s; + long v; + + + for (d=0; d +#include +#include +#include +#include +#include "omp.h" +#include "aux.h" + +void pipeline(data *datas, resource *resources, int ndatas, int nsteps); + + +int main(int argc, char **argv){ + int n, i, s, d, ndatas, nsteps; + long t_start, t_end; + data *datas; + resource *resources; + + // Command line arguments + if ( argc == 3 ) { + ndatas = atoi(argv[1]); /* num of datas */ + nsteps = atoi(argv[2]); /* num of steps */ + } else { + printf("Usage:\n\n ./main ndatas nsteps\n where ndatas is the number of data and nsteps the number of steps.\n"); + return 1; + } + + init_data(&datas, &resources, ndatas, nsteps); + + /* Process all the data */ + t_start = usecs(); + pipeline(datas, resources, ndatas, nsteps); + t_end = usecs(); + printf("Execution time : %8.2f msec.\n",((double)t_end-t_start)/1000.0); + + + check_result(datas, ndatas, nsteps); + + return 0; + +} + + + +void pipeline(data *datas, resource *resources, int ndatas, int nsteps){ + + int d, s; + + omp_lock_t *locks = malloc(sizeof(omp_lock_t)*nsteps); + for (s = 0; s < nsteps; s++) + { + omp_init_lock(locks+s); + } + + /* Loop over all the data */ +#pragma omp parallel for private(s) + for (d=0; dparent = parent; + curr->id = *id; + *id = *id - 1; + nnodes = nnodes -1; + unsigned nc = (rand()%NCHILDREN) +2; + nc = MIN(nc,nnodes); + curr->data = rand()%100 +1; + res += curr->data; + + if(nc==0) { + leaves[*nleaves] = curr; + *nleaves += 1; + } + + if(curr->parent==NULL){ + /* printf("Node %5d -- nc %d parent N\n",curr->id, nc); */ + } else { + /* printf("Node %5d -- nc %d parent %d\n",curr->id, nc, curr->parent->id); */ + if(fp!=NULL) + fprintf(fp, "%d -- %d \n", curr->parent->id, curr->id); + } + + + for(i=0; iparent!=NULL){ */ + /* printf("%d -- Visiting node %d %d\n",omp_get_thread_num(), node->id, node->parent->visited); */ + /* } else { */ + /* printf("%d -- Visiting node %d\n",omp_get_thread_num(), node->id); */ + /* } */ +#pragma omp atomic update + tot_visited++; +#pragma omp atomic update + check_res += node->data; + mysleep(0.0001); + return ; +} + + +void check_result(){ + if((tot_visited==to_be_visited) && (check_res==res)){ + printf("The result is CORRECT\n"); + } else { + printf("The result is WRONG!!!! %d %lu %lu\n",tot_visited,res,check_res); + } +} diff --git a/BE_OpenMP_2021/tree_bottomup/aux.h b/BE_OpenMP_2021/tree_bottomup/aux.h new file mode 100644 index 0000000..beae21f --- /dev/null +++ b/BE_OpenMP_2021/tree_bottomup/aux.h @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include + +#define NCHILDREN 2 +#define MIN(a,b) (((a)<(b))?(a):(b)) + + +struct node{ + unsigned id; + unsigned long data; + struct node *parent; +}; + +void generate_node(struct node *parent, int nnodes, int *id, struct node **leaves, int *nleaves, FILE *fp); +void process_node(struct node *node); +long usecs (); +void check_result(); +void generate_tree(int nnodes, struct node ***leaves, int *nleaves); + + diff --git a/BE_OpenMP_2021/tree_bottomup/main.c b/BE_OpenMP_2021/tree_bottomup/main.c new file mode 100644 index 0000000..d40558d --- /dev/null +++ b/BE_OpenMP_2021/tree_bottomup/main.c @@ -0,0 +1,65 @@ +#include "aux.h" + + +void bottom_up(int nleaves, struct node **leaves, int nnodes); + +int main(int argc, char **argv){ + long t_start, t_end; + int nnodes, nleaves; + struct node **leaves; + + // Command line argument: number of nodes in the tree + if ( argc == 2 ) { + nnodes = atoi(argv[1]); + } else { + printf("Usage:\n\n ./main n\n\nwhere n is the number of nodes in the tree.\n"); + return 1; + } + + printf("\nGenerating a tree with %d nodes\n\n",nnodes); + generate_tree(nnodes, &leaves, &nleaves); + + t_start = usecs(); + bottom_up(nleaves, leaves, nnodes); + t_end = usecs(); + + printf("Parallel time : %8.2f msec.\n\n",((double)t_end-t_start)/1000.0); + + check_result(); + +} + + +/* You can change the number and type of arguments if needed. */ +/* Just don't forget to update the interface declaration above. */ +void bottom_up(int nleaves, struct node **leaves, int nnodes){ + + int l, i, v; + struct node *curr; + int *visited = malloc(sizeof(int) * nnodes); + +#pragma omp paralell for private(curr, v) + for (l = 0; l < nleaves; l++) + { + curr = leaves[l]; + + while (curr) { +#pragma omp atomic capture + v = visited[curr->id-1]++; + + if (v>0) + { + break + } + else { + process_node(curr); + curr = curr->parent; + } + } + } +} + + + + + diff --git a/BE_OpenMP_2021/tree_bottomup/subject.pdf b/BE_OpenMP_2021/tree_bottomup/subject.pdf new file mode 100644 index 0000000..ca4d9cd Binary files /dev/null and b/BE_OpenMP_2021/tree_bottomup/subject.pdf differ diff --git a/BE_OpenMP_2022/Makefile b/BE_OpenMP_2022/Makefile new file mode 100644 index 0000000..f6a7b4b --- /dev/null +++ b/BE_OpenMP_2022/Makefile @@ -0,0 +1,13 @@ +clean: + (cd norm1; make clean) + (cd server; make clean) + (cd sched; make clean) + (cd sparse_nn; make clean) + (cd ring; make clean) + + + + + + + diff --git a/BE_OpenMP_2022/norm1/Makefile b/BE_OpenMP_2022/norm1/Makefile new file mode 100644 index 0000000..53dfbb6 --- /dev/null +++ b/BE_OpenMP_2022/norm1/Makefile @@ -0,0 +1,31 @@ +CC = gcc +LINK = $(CC) + +CFLAGS = -O3 -fopenmp -Wunknown-pragmas +# CFLAGS = -g -fopenmp +LDFLAGS = $(CFLAGS) +LIBS = -lm + +OBJS = aux.o main.o + +main: $(OBJS) + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + + + + + + +clean: + (rm -f *.o main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< + + + + diff --git a/BE_OpenMP_2022/norm1/aux.c b/BE_OpenMP_2022/norm1/aux.c new file mode 100644 index 0000000..d5fd494 --- /dev/null +++ b/BE_OpenMP_2022/norm1/aux.c @@ -0,0 +1,54 @@ +#include "aux.h" + +#define timelim 2.0 + + +long usecs (){ + struct timeval t; + + gettimeofday(&t,NULL); + return t.tv_sec*1000000+t.tv_usec; +} + +void mysleep(double sec){ + + long s, e; + s=0; e=0; + s = usecs(); + while(((double) e-s)/1000000 < sec) + { + e = usecs(); + } + return; +} + + + +void func1(int i, int n){ + double x = timelim/((double)n); + mysleep(x); + +}; + + +void func2(int i, int n){ + /* double x = 2.0*((double)rand() / (double)RAND_MAX) * timelim / ((double)(n)); */ + /* mysleep(x); */ + + double x = 2.0*timelim/ ((double)(n*n)); + + mysleep(((double)(i+1))*x); + +}; + + + +void func3(int i, int n){ + + double x = 2.0*timelim/ ((double)(n*n)); + + mysleep(((double)(n-i))*x); + +}; + + diff --git a/BE_OpenMP_2022/norm1/aux.h b/BE_OpenMP_2022/norm1/aux.h new file mode 100644 index 0000000..1b8e2c4 --- /dev/null +++ b/BE_OpenMP_2022/norm1/aux.h @@ -0,0 +1,12 @@ +#include +#include +#include +#include + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +long usecs (); +void func1(int i, int n); +void func2(int i, int n); +void func3(int i, int n); diff --git a/BE_OpenMP_2022/norm1/main.c b/BE_OpenMP_2022/norm1/main.c new file mode 100644 index 0000000..b496662 --- /dev/null +++ b/BE_OpenMP_2022/norm1/main.c @@ -0,0 +1,178 @@ +#include "aux.h" +#include "omp.h" + +double norm1(double **A, int m, int n); +double norm1_colmajor(double **A, int m, int n); +double norm1_rowmajor(double **A, int m, int n); + +int main(int argc, char **argv) +{ + long t_start, t_end; + int m, n, i, j; + double nrm, nrmrm, nrmcm; + double **A; + + // Command line argument: matrix size + if (argc == 3) + { + m = atoi(argv[1]); /* the number of matrix rows */ + n = atoi(argv[2]); /* the number of matrix cols */ + } + else + { + printf("Usage:\n\n ./main n m\n\nwhere m and n are the number of rows and cols in the matrix\n"); + return 1; + } + + A = (double **)malloc(m * sizeof(double *)); + for (i = 0; i < m; i++) + { + A[i] = (double *)malloc(n * sizeof(double)); + + for (j = 0; j < n; j++) + { + A[i][j] = ((double)rand() / (double)RAND_MAX); + } + } + + /* warm up */ + nrm = norm1(A, m, n); + + t_start = usecs(); + nrm = norm1(A, m, n); + t_end = usecs() - t_start; + printf("Sequential -- norm:%8.4f time (usecs):%6ld\n", nrm, t_end); + + t_start = usecs(); + nrmcm = norm1_colmajor(A, m, n); + t_end = usecs() - t_start; + printf("Col-major -- norm:%8.4f time (usecs):%6ld\n", nrmcm, t_end); + + t_start = usecs(); + nrmrm = norm1_rowmajor(A, m, n); + t_end = usecs() - t_start; + printf("Row-major -- norm:%8.4f time (usecs):%6ld\n", nrmrm, t_end); + + printf("\n"); + + return 0; +} + +double norm1(double **A, int m, int n) +{ + int i, j; + double nrm, tmp; + nrm = 0.0; + + for (j = 0; j < n; j++) + { + tmp = 0.0; + for (i = 0; i < m; i++) + { + tmp += fabs(A[i][j]); + } + if (tmp > nrm) + nrm = tmp; + } + + return nrm; +} + +double norm1_colmajor(double **A, int m, int n) +{ + int i, j; + double nrm = 0.0; + double tmp; + +#pragma omp parallel private(i, j, tmp) shared(nrm) + +#pragma omp for + for (j = 0; j < n; j++) + { + tmp = 0.0; + for (i = 0; i < m; i++) + { + tmp += fabs(A[i][j]); + } + + if (tmp > nrm) + { +#pragma omp atomic write + nrm = tmp; + } + } + + return nrm; +} + +double norm1_rowmajor(double **A, int m, int n) +{ + int i, j; + double nrm, *tmp; + + nrm = 0.0; + tmp = (double *)malloc(n * sizeof(double)); + for (j = 0; j < n; j++) + { + tmp[j] = 0.0; + } + +#pragma omp parallel private(i, j) shared(tmp) + +#pragma omp for + for (i = 0; i < m; i++) + { + for (j = 0; j < n; j++) + { +#pragma omp atomic update + tmp[j] += fabs(A[i][j]); + } + } + +#pragma omp single + { + for (int k = 0; k < n; k++) + { + if (tmp[k] > nrm) + { + nrm = tmp[k]; + } + } + + free(tmp); + } + + return nrm; +} + +/* + +Résultats: n=100000 m=1000 + +threads = 1: +Sequential -- norm:50277.9944 time (usecs):770322 +Col-major -- norm:50277.9944 time (usecs):766831 +Row-major -- norm:50277.9944 time (usecs):775600 + +threads = 2: +Sequential -- norm:50277.9944 time (usecs):745682 +Col-major -- norm:50277.9944 time (usecs):394515 +Row-major -- norm:50277.9944 time (usecs):954254 + +threads = 4: +Sequential -- norm:50277.9944 time (usecs):747250 +Col-major -- norm:50277.9944 time (usecs):296826 +Row-major -- norm:50277.9944 time (usecs):559891 + +threads = 30: +Sequential -- norm:50277.9944 time (usecs):748683 +Col-major -- norm:50277.9944 time (usecs):253433 +Row-major -- norm:50277.9944 time (usecs):436225 + + +On observe que col-major est la plus rapide. +Cela est surement dû au atomic update nécéssaire dans la boucle for. +Une version meilleur serait de créer une liste tmp par thread, et de ensuite les sommer à la fin, +mais une ébauche non finis est disponible dans le fichier main.c.broken. + +*/ \ No newline at end of file diff --git a/BE_OpenMP_2022/norm1/main.c.broken b/BE_OpenMP_2022/norm1/main.c.broken new file mode 100644 index 0000000..94d8b47 --- /dev/null +++ b/BE_OpenMP_2022/norm1/main.c.broken @@ -0,0 +1,194 @@ +#include "aux.h" +#include "omp.h" +#define MAX_THREADS 30 + +double norm1(double **A, int m, int n); +double norm1_colmajor(double **A, int m, int n); +double norm1_rowmajor(double **A, int m, int n); + +int main(int argc, char **argv) +{ + long t_start, t_end; + int m, n, i, j; + double nrm, nrmrm, nrmcm; + double **A; + + // Command line argument: matrix size + if (argc == 3) + { + m = atoi(argv[1]); /* the number of matrix rows */ + n = atoi(argv[2]); /* the number of matrix cols */ + } + else + { + printf("Usage:\n\n ./main n m\n\nwhere m and n are the number of rows and cols in the matrix\n"); + return 1; + } + + A = (double **)malloc(m * sizeof(double *)); + for (i = 0; i < m; i++) + { + A[i] = (double *)malloc(n * sizeof(double)); + + for (j = 0; j < n; j++) + { + A[i][j] = ((double)rand() / (double)RAND_MAX); + } + } + + /* warm up */ + nrm = norm1(A, m, n); + + t_start = usecs(); + nrm = norm1(A, m, n); + t_end = usecs() - t_start; + printf("Sequential -- norm:%8.4f time (usecs):%6ld\n", nrm, t_end); + + t_start = usecs(); + nrmcm = norm1_colmajor(A, m, n); + t_end = usecs() - t_start; + printf("Col-major -- norm:%8.4f time (usecs):%6ld\n", nrmcm, t_end); + + t_start = usecs(); + nrmrm = norm1_rowmajor(A, m, n); + t_end = usecs() - t_start; + printf("Row-major -- norm:%8.4f time (usecs):%6ld\n", nrmrm, t_end); + + printf("\n"); + + return 0; +} + +double norm1(double **A, int m, int n) +{ + int i, j; + double nrm, tmp; + nrm = 0.0; + + for (j = 0; j < n; j++) + { + tmp = 0.0; + for (i = 0; i < m; i++) + { + tmp += fabs(A[i][j]); + } + if (tmp > nrm) + nrm = tmp; + } + + return nrm; +} + +double norm1_colmajor(double **A, int m, int n) +{ + int i, j; + double nrm = 0.0; + double tmp; + +#pragma omp parallel private(i, j, tmp) shared(nrm) + +#pragma omp for + for (j = 0; j < n; j++) + { + tmp = 0.0; + for (i = 0; i < m; i++) + { + tmp += fabs(A[i][j]); + } + + if (tmp > nrm) + { +#pragma omp atomic write + nrm = tmp; + } + } + + return nrm; +} + +double norm1_rowmajor(double **A, int m, int n) +{ + int i, j; + double nrm, **tmp, *tmp_sum; + + nrm = 0.0; + + tmp = (double **)malloc(m * sizeof(double *)); + for (i = 0; i < m; i++) + { + tmp[i] = (double *)malloc(MAX_THREADS * sizeof(double)); + + for (j = 0; j < MAX_THREADS; j++) + { + tmp[i][j] = 0.0; + } + } + +#pragma omp parallel private(i, j) shared(tmp) + +#pragma omp for + for (i = 0; i < m; i++) + { + for (j = 0; j < n; j++) + { +#pragma omp atomic update + tmp[j][omp_get_thread_num()] += fabs(A[i][j]); + } + } + +#pragma omp single + { + + for (i = 0; i < m; i++) + { + for (j = 0; j < MAX_THREADS; j++) + { + tmp_sum[i] = tmp[i][j]; + } + } + + for (int k = 0; k < n; k++) + { + if (tmp_sum[k] > nrm) + { + nrm = tmp_sum[k]; + } + } + + free(tmp_sum); + } + + return nrm; +} + +/* + +Résultats: n=100000 m=1000 + +threads = 1: +Sequential -- norm:50277.9944 time (usecs):770322 +Col-major -- norm:50277.9944 time (usecs):766831 +Row-major -- norm:50277.9944 time (usecs):775600 + +threads = 2: +Sequential -- norm:50277.9944 time (usecs):745682 +Col-major -- norm:50277.9944 time (usecs):394515 +Row-major -- norm:50277.9944 time (usecs):954254 + +threads = 4: +Sequential -- norm:50277.9944 time (usecs):747250 +Col-major -- norm:50277.9944 time (usecs):296826 +Row-major -- norm:50277.9944 time (usecs):559891 + +threads = 30: +Sequential -- norm:50277.9944 time (usecs):748683 +Col-major -- norm:50277.9944 time (usecs):253433 +Row-major -- norm:50277.9944 time (usecs):436225 + + +On observe que col-major est la plus rapide. +Cela est surement dû au atomic update nécéssaire dans la boucle for. +Une version meilleur serait de créer une liste tmp par thread, et de ensuite les sommer à la fin, +une ébauche non finis est disponible dans le fichier main.c.broken + +*/ \ No newline at end of file diff --git a/BE_OpenMP_2022/norm1/subject.pdf b/BE_OpenMP_2022/norm1/subject.pdf new file mode 100644 index 0000000..526047d Binary files /dev/null and b/BE_OpenMP_2022/norm1/subject.pdf differ diff --git a/BE_OpenMP_2022/pack.sh b/BE_OpenMP_2022/pack.sh new file mode 100755 index 0000000..a2d99d3 --- /dev/null +++ b/BE_OpenMP_2022/pack.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +make clean; +mkdir $USER +cp -r norm1 ring sparse_nn server sched $USER; +cd $USER; find . -not \( -name "*.c" -or -name "*.c.broken" -or -name "Makefile" -or -name "*.h" -or -type d \) | xargs rm; cd ..; +tar zcvf $USER.tgz $USER; +rm -rf $USER; diff --git a/BE_OpenMP_2022/ring/Makefile b/BE_OpenMP_2022/ring/Makefile new file mode 100644 index 0000000..53dfbb6 --- /dev/null +++ b/BE_OpenMP_2022/ring/Makefile @@ -0,0 +1,31 @@ +CC = gcc +LINK = $(CC) + +CFLAGS = -O3 -fopenmp -Wunknown-pragmas +# CFLAGS = -g -fopenmp +LDFLAGS = $(CFLAGS) +LIBS = -lm + +OBJS = aux.o main.o + +main: $(OBJS) + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + + + + + + +clean: + (rm -f *.o main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< + + + + diff --git a/BE_OpenMP_2022/ring/aux.c b/BE_OpenMP_2022/ring/aux.c new file mode 100644 index 0000000..93f013b --- /dev/null +++ b/BE_OpenMP_2022/ring/aux.c @@ -0,0 +1,66 @@ +#include "aux.h" +#include "omp.h" + +#define timelim 2.0 + +long usecs() +{ + struct timeval t; + + gettimeofday(&t, NULL); + return t.tv_sec * 1000000 + t.tv_usec; +} + +void mysleep(double sec) +{ + + long s, e; + s = 0; + e = 0; + s = usecs(); + while (((double)e - s) / 1000000 < sec) + { + e = usecs(); + } + return; +} + +void process(Token *token) +{ + + token->data = token->data * 2 + omp_get_thread_num(); + mysleep(0.2); + // printf(" -- Thread:%2d\n", omp_get_thread_num()); + printf(" -- Thread:%2d %3d\n", omp_get_thread_num(), token->data); + return; +} + +void init(Token *token, int L, int T) +{ + + token->data = 0; + + return; +} + +void check(Token *token, int L, int T) +{ + + int data = 0; + int l, t; + + for (l = 0; l < L; l++) + for (t = 0; t < T; t++) + data = data * 2 + t; + + if (data == token->data) + { + printf("The result is good %3d %3d\n", data, token->data); + } + else + { + printf("The result is wrong %3d %3d\n", data, token->data); + } + + return; +} diff --git a/BE_OpenMP_2022/ring/aux.h b/BE_OpenMP_2022/ring/aux.h new file mode 100644 index 0000000..b595a8a --- /dev/null +++ b/BE_OpenMP_2022/ring/aux.h @@ -0,0 +1,18 @@ +#include +#include +#include +#include + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +long usecs (); + + +typedef struct tokenstruct{ + int data; +} Token; + +void check(Token *token, int L, int T); +void init(Token *token, int L, int T); +void process(Token *token); diff --git a/BE_OpenMP_2022/ring/main.c b/BE_OpenMP_2022/ring/main.c new file mode 100644 index 0000000..825cb0a --- /dev/null +++ b/BE_OpenMP_2022/ring/main.c @@ -0,0 +1,46 @@ +#include "aux.h" +#include "omp.h" + +int main(int argc, char **argv) +{ + long t_start, t_end; + int l, t, L, T; + Token token; + + if (argc == 3) + { + L = atoi(argv[1]); /* number of loops */ + T = atoi(argv[2]); /* number of threads */ + } + else + { + printf("Usage:\n\n ./main L T\n\nsuch that L is the number of loops and T the number of threads to use.\n"); + return 1; + } + + init(&token, L, T); + + for (l = 0; l < L; l++) + { +#pragma omp parallel for ordered + for (int i = 0; i < omp_get_num_threads(); i++) + { + // printf("Loop %2d, %d\n", l, i); +#pragma omp ordered + process(&token); + } + } + +#pragma omp single + + check(&token, L, T); + + return 0; +} + +/* + +Commentaire: +je triche un peu en utilisant "ordered". Mais cela simplifie grandement l'exercice. + +*/ diff --git a/BE_OpenMP_2022/ring/subject.pdf b/BE_OpenMP_2022/ring/subject.pdf new file mode 100644 index 0000000..4cb1b64 Binary files /dev/null and b/BE_OpenMP_2022/ring/subject.pdf differ diff --git a/BE_OpenMP_2022/sched/Makefile b/BE_OpenMP_2022/sched/Makefile new file mode 100644 index 0000000..53dfbb6 --- /dev/null +++ b/BE_OpenMP_2022/sched/Makefile @@ -0,0 +1,31 @@ +CC = gcc +LINK = $(CC) + +CFLAGS = -O3 -fopenmp -Wunknown-pragmas +# CFLAGS = -g -fopenmp +LDFLAGS = $(CFLAGS) +LIBS = -lm + +OBJS = aux.o main.o + +main: $(OBJS) + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + + + + + + +clean: + (rm -f *.o main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< + + + + diff --git a/BE_OpenMP_2022/sched/aux.c b/BE_OpenMP_2022/sched/aux.c new file mode 100644 index 0000000..d5fd494 --- /dev/null +++ b/BE_OpenMP_2022/sched/aux.c @@ -0,0 +1,54 @@ +#include "aux.h" + +#define timelim 2.0 + + +long usecs (){ + struct timeval t; + + gettimeofday(&t,NULL); + return t.tv_sec*1000000+t.tv_usec; +} + +void mysleep(double sec){ + + long s, e; + s=0; e=0; + s = usecs(); + while(((double) e-s)/1000000 < sec) + { + e = usecs(); + } + return; +} + + + +void func1(int i, int n){ + double x = timelim/((double)n); + mysleep(x); + +}; + + +void func2(int i, int n){ + /* double x = 2.0*((double)rand() / (double)RAND_MAX) * timelim / ((double)(n)); */ + /* mysleep(x); */ + + double x = 2.0*timelim/ ((double)(n*n)); + + mysleep(((double)(i+1))*x); + +}; + + + +void func3(int i, int n){ + + double x = 2.0*timelim/ ((double)(n*n)); + + mysleep(((double)(n-i))*x); + +}; + + diff --git a/BE_OpenMP_2022/sched/aux.h b/BE_OpenMP_2022/sched/aux.h new file mode 100644 index 0000000..1b8e2c4 --- /dev/null +++ b/BE_OpenMP_2022/sched/aux.h @@ -0,0 +1,12 @@ +#include +#include +#include +#include + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +long usecs (); +void func1(int i, int n); +void func2(int i, int n); +void func3(int i, int n); diff --git a/BE_OpenMP_2022/sched/main.c b/BE_OpenMP_2022/sched/main.c new file mode 100644 index 0000000..a857caf --- /dev/null +++ b/BE_OpenMP_2022/sched/main.c @@ -0,0 +1,184 @@ +#include "aux.h" +#include "omp.h" +#define MAX_THREADS 30 + +void loop1(int n) +{ + long t_start, t_end; + double time_it; + double times[MAX_THREADS]; + int i, nb_threads; + + double load = 0.0; + +#pragma omp parallel + +#pragma omp for schedule(static) + for (i = 0; i < n; i++) + { + t_start = usecs(); + func1(i, n); + time_it = (double)(usecs() - t_start); + load += time_it; + times[omp_get_thread_num()] += time_it; + if (n <= 20) + { + printf("Iteration %6d of loop 1 took %.2f usecs (executed by thread: %2d, load: %f)\n", i, time_it, omp_get_thread_num(), times[omp_get_thread_num()]); + } + } + +#pragma omp master + { + double min = *times; + double max = *times; + + for (int j = 0; j < MAX_THREADS; j++) + { + if (times[j] > max) + { + max = times[j]; + } + if (times[j] < min && times[j] >= 0.001) + { + min = times[j]; + } + } + + printf("rapport: %f, min: %f, max: %f\n\n", max / min, min, max); + } +} + +void loop2(int n) +{ + long t_start, t_end; + double time_it, load; + double times[MAX_THREADS]; + int i; + + load = 0.0; + +#pragma omp parallel + +#pragma omp for schedule(dynamic) + for (i = 0; i < n; i++) + { + t_start = usecs(); + func2(i, n); + time_it = (double)(usecs() - t_start); + load += time_it; + times[omp_get_thread_num()] += time_it; + if (n <= 20) + { + printf("Iteration %6d of loop 2 took %.2f usecs (executed by thread: %2d, load: %f)\n", i, time_it, omp_get_thread_num(), times[omp_get_thread_num()]); + } + } + +#pragma omp master + { + double min = *times; + double max = *times; + + for (int j = 0; j < MAX_THREADS; j++) + { + if (times[j] > max) + { + max = times[j]; + } + if (times[j] < min && times[j] >= 0.001) + { + min = times[j]; + } + } + + printf("rapport: %f, min: %f, max: %f\n\n", max / min, min, max); + } +} + +void loop3(int n) +{ + long t_start, t_end; + double time_it, load; + double times[MAX_THREADS]; + int i; + + load = 0.0; + +#pragma omp parallel + +#pragma omp for schedule(guided) + for (i = 0; i < n; i++) + { + t_start = usecs(); + func3(i, n); + time_it = (double)(usecs() - t_start); + load += time_it; + times[omp_get_thread_num()] += time_it; + if (n <= 20) + printf("Iteration %6d of loop 3 took %.2f usecs (executed by thread: %2d, load: %f)\n", i, time_it, omp_get_thread_num(), times[omp_get_thread_num()]); + } + +#pragma omp master + { + double min = *times; + double max = *times; + + for (int j = 0; j < MAX_THREADS; j++) + { + if (times[j] > max) + { + max = times[j]; + } + if (times[j] < min && times[j] >= 0.001) + { + min = times[j]; + } + } + + printf("rapport: %f, min: %f, max: %f\n\n", max / min, min, max); + } +} + +int main(int argc, char **argv) +{ + int i, j, n; + + // Command line argument + if (argc == 2) + { + n = atoi(argv[1]); /* the number of loop iterations */ + } + else + { + printf("Usage:\n\n ./main n \n\nwhere n is the number of iterations in the loops\n"); + return 1; + } + + printf("\n"); + + loop1(n); + + printf("\n"); + + loop2(n); + + printf("\n"); + + loop3(n); + + printf("\n"); + + return 0; +} + +/* + +Commentaires: + +loop1 : les time_it sont pratiquement tous les mêmes, on sélectionne le scheduling static +loop2 : les time_it sont pratiquement tous très différents, on sélectionne le scheduling dynamic +loop3 : les time_it sont "croissants", on sélectionne le scheduling guided, pour être static au début puis dynamic à la fin + + +pour de grandes valeurs de n, on observer que le rapport tend vers 1 pour chacun des loops. + +*/ \ No newline at end of file diff --git a/BE_OpenMP_2022/sched/subject.pdf b/BE_OpenMP_2022/sched/subject.pdf new file mode 100644 index 0000000..e3315b2 Binary files /dev/null and b/BE_OpenMP_2022/sched/subject.pdf differ diff --git a/BE_OpenMP_2022/server/Makefile b/BE_OpenMP_2022/server/Makefile new file mode 100644 index 0000000..2017221 --- /dev/null +++ b/BE_OpenMP_2022/server/Makefile @@ -0,0 +1,31 @@ +CC = gcc +LINK = $(CC) + +# CFLAGS = -O3 -fopenmp -Wunknown-pragmas +CFLAGS = -g -fopenmp +LDFLAGS = $(CFLAGS) +LIBS = -lm + +OBJS = aux.o main.o + +main: $(OBJS) + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + + + + + + +clean: + (rm -f *.o main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< + + + + diff --git a/BE_OpenMP_2022/server/aux.c b/BE_OpenMP_2022/server/aux.c new file mode 100644 index 0000000..320067e --- /dev/null +++ b/BE_OpenMP_2022/server/aux.c @@ -0,0 +1,93 @@ +#include "aux.h" + + +Request reqs[nreq]; +int rc; + +long usecs (){ + struct timeval t; + + gettimeofday(&t,NULL); + return t.tv_sec*1000000+t.tv_usec; +} + +void mysleep(double sec){ + + long s, e; + s=0; e=0; + s = usecs(); + while(((double) e-s)/1000000 < sec) + { + e = usecs(); + } + return; +} + + +void init(Stack *bins){ + + int i; + + for(i=0; idata); + + res.type = req->type; + res.data = req->data; + res.id = req->id ; + +} + + +void check(Stack *stacks){ + + int cnts[ntypes]; + int i; + + for(i=0; i %2d %2d\n",cnts[i],stacks[i].head); */ + if(stacks[i].head!=cnts[i]-1){ + printf("Result is wrong :-(\n"); + return; + } + } + + printf("Result is correct :-)\n"); + return; + +} diff --git a/BE_OpenMP_2022/server/aux.h b/BE_OpenMP_2022/server/aux.h new file mode 100644 index 0000000..7384835 --- /dev/null +++ b/BE_OpenMP_2022/server/aux.h @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +#define timelim 1 +#define nreq 100000 +#define ntypes 4 + + +typedef struct requeststruct{ + int type; + int id; + double data; +} Request; + +typedef struct resultstruct{ + int type; + int id; + double data; +} Result; + + +typedef struct stackstruct{ + int head; + Result results[nreq]; +} Stack; + + + +long usecs (); + +void init(Stack *bins); +Request receive(); +Result process(Request *req); +void check(Stack *stacks); diff --git a/BE_OpenMP_2022/server/main.c b/BE_OpenMP_2022/server/main.c new file mode 100644 index 0000000..ae3771a --- /dev/null +++ b/BE_OpenMP_2022/server/main.c @@ -0,0 +1,67 @@ +#include "aux.h" +#include "omp.h" + +int main(int argc, char **argv) +{ + long t_start; + double time; + int i, j, n; + Stack stacks[ntypes]; + Request req; + int head; + + init(stacks); + + t_start = usecs(); + +#pragma omp parallel shared(stacks) + { +#pragma omp single + { + for (;;) + { + + req = receive(); + + // printf("Received request %d\n",req.id); + if (req.type != -1) + { + +#pragma omp task firstprivate(req) + { + // printf("Thread %d, processing request %d\n", omp_get_thread_num(), req.id); + Result result = process(&req); + // on fait un atomic update car l'on a que un seul stacks pour tous les threads (normalement ?) +#pragma omp atomic update + stacks[req.type].head += 1; + stacks[req.type].results[stacks[req.type].head] = result; + } + } + else + { + break; + } + } + } + } + + time = (double)(usecs() - t_start) / 1000000.0; + printf("Finished. Execution time:%.2f \n", time); + + check(stacks); + + return 0; +} + +/* + +Résultats: + +nb_threads = 1 : Execution time: 1.19 +nb_threads = 2 : Execution time: 0.63 +nb_threads = 4 : Execution time: 0.34 +nb_threads = 6 : Execution time: 0.22 +nb_threads = 8 : Execution time: 0.17 +nb_threads = 10 : Execution time: 0.15 + +*/ \ No newline at end of file diff --git a/BE_OpenMP_2022/server/subject.pdf b/BE_OpenMP_2022/server/subject.pdf new file mode 100644 index 0000000..c9455e8 Binary files /dev/null and b/BE_OpenMP_2022/server/subject.pdf differ diff --git a/BE_OpenMP_2022/sparse_nn/Makefile b/BE_OpenMP_2022/sparse_nn/Makefile new file mode 100644 index 0000000..474e3dc --- /dev/null +++ b/BE_OpenMP_2022/sparse_nn/Makefile @@ -0,0 +1,27 @@ +CC = gcc +LINK = $(CC) + +CFLAGS = -O3 -fopenmp -Wunknown-pragmas +# CFLAGS = -g -fopenmp +LDFLAGS = $(CFLAGS) +LIBS = -lm $(LBLAS) -lm + +OBJS = aux.o main.o + +main: $(OBJS) + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + + +clean: + (rm -f *.o main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< + + + + diff --git a/BE_OpenMP_2022/sparse_nn/aux.c b/BE_OpenMP_2022/sparse_nn/aux.c new file mode 100644 index 0000000..dd18aa9 --- /dev/null +++ b/BE_OpenMP_2022/sparse_nn/aux.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include "aux.h" + +#define maxs 0.2 +#define mins 0.1 + +int ISEED[4] = {0,0,0,1}; +int IONE=1; +char NoTran = 'N'; +double DONE=1.0, DMONE=-1.0; + + +void mysleep(double sec){ + + long s, e; + s=0; e=0; + s = usecs(); + while(((double) e-s)/1000000 < sec) + { + e = usecs(); + } + return; +} + + +void init(layer *layers, int n, int L){ + + int l, i, m, minm, maxm; + + minm = (int)((double)(n*n)*mins); + maxm = (int)((double)(n*n)*(maxs-mins)); + + for(l=0; l max) + max = (layers_s[L-1].neu[i].nv-layers_p[L-1].neu[i].nv)/layers_s[L-1].neu[i].nv; + /* printf("%.2e\n",(layers_s[L-1].neu[i].nv-layers_p[L-1].neu[i].nv)/layers_s[L-1].neu[i].nv); */ + } + + if(max>1e-12) { + printf("Result is wrong :-(\n"); + } else { + printf("Result is correct :-)\n"); + } +} + + + +long usecs (){ + struct timeval t; + + gettimeofday(&t,NULL); + return t.tv_sec*1000000+t.tv_usec; +} diff --git a/BE_OpenMP_2022/sparse_nn/aux.h b/BE_OpenMP_2022/sparse_nn/aux.h new file mode 100644 index 0000000..56fe1a2 --- /dev/null +++ b/BE_OpenMP_2022/sparse_nn/aux.h @@ -0,0 +1,22 @@ + +struct { + int i, j; + double sv; +} typedef synapse; + +struct { + double nv; +} typedef neuron; + + +struct { + int m; + synapse *syn; + neuron *neu; +} typedef layer; + +void init(layer *layers, int n, int L); +double update(double nin, double v); +void copy_nn(layer *layers_in, layer *layers_out, int n, int L); +long usecs (); +void check_result(layer *layers_s, layer *layers_p, int n, int L); diff --git a/BE_OpenMP_2022/sparse_nn/main.c b/BE_OpenMP_2022/sparse_nn/main.c new file mode 100644 index 0000000..fbe3243 --- /dev/null +++ b/BE_OpenMP_2022/sparse_nn/main.c @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include +#include "omp.h" +#include "aux.h" + +void sequential_nn(layer *layers, int n, int L); +void parallel_nn_loops(layer *layers, int n, int L); +void parallel_nn_tasks(layer *layers, int n, int L); + +int main(int argc, char **argv) +{ + int n, m, N, L, i; + long t_start, t_end; + layer *layers_se, *layers_pl, *layers_pt; + + // Command line arguments + if (argc == 3) + { + n = atoi(argv[1]); /* size of layers */ + L = atoi(argv[2]); /* number of layers in the network */ + } + else + { + printf("Usage:\n\n ./main n L\n\nsuch that n is the size of the layers and L is the number of layers.\n"); + return 1; + } + + layers_se = (layer *)malloc(sizeof(layer) * L); + layers_pl = (layer *)malloc(sizeof(layer) * L); + layers_pt = (layer *)malloc(sizeof(layer) * L); + + init(layers_se, n, L); + copy_nn(layers_se, layers_pl, n, L); + copy_nn(layers_se, layers_pt, n, L); + + t_start = usecs(); + sequential_nn(layers_se, n, L); + t_end = usecs(); + printf("Sequential time : %8.2f msec.\n", ((double)t_end - t_start) / 1000.0); + + t_start = usecs(); + parallel_nn_loops(layers_pl, n, L); + t_end = usecs(); + printf("Parallel loops time : %8.2f msec. ", ((double)t_end - t_start) / 1000.0); + + check_result(layers_se, layers_pl, n, L); + + t_start = usecs(); + parallel_nn_tasks(layers_pt, n, L); + t_end = usecs(); + printf("Parallel tasks time : %8.2f msec. ", ((double)t_end - t_start) / 1000.0); + + check_result(layers_se, layers_pt, n, L); + + return 0; +} + +void sequential_nn(layer *layers, int n, int L) +{ + int i, j, l, s; + + for (l = 0; l < L - 1; l++) + { + // printf("layer %2d m:%2d\n", l, layers[l].m); + for (s = 0; s < layers[l].m; s++) + { + i = layers[l].syn[s].i; + j = layers[l].syn[s].j; + // printf("layer %2d i:%2d j:%2d, bidule: %f\n", l, i, j, update(layers[l].neu[i].nv, layers[l].syn[s].sv)); + layers[l + 1].neu[j].nv += update(layers[l].neu[i].nv, layers[l].syn[s].sv); + } + } +} + +void parallel_nn_loops(layer *layers, int n, int L) +{ + int i, j, l, s; + +#pragma omp parallel private(i, j, l, s) + + for (l = 0; l < L - 1; l++) + { +// printf("layer %2d m:%2d\n", l, layers[l].m); +#pragma omp for + for (s = 0; s < layers[l].m; s++) + { + i = layers[l].syn[s].i; + j = layers[l].syn[s].j; + // printf("layer %2d i:%2d j:%2d\n", l, i, j); + layers[l + 1].neu[j].nv += update(layers[l].neu[i].nv, layers[l].syn[s].sv); + } + } +} + +void parallel_nn_tasks(layer *layers, int n, int L) +{ + int i, j, l, s; + +#pragma omp parallel private(i, j, l, s) + +#pragma omp single + + for (l = 0; l < L - 1; l++) + { + // printf("layer %2d m:%2d\n", l, layers[l].m); + for (s = 0; s < layers[l].m; s++) + { + i = layers[l].syn[s].i; + j = layers[l].syn[s].j; +#pragma omp task firstprivate(i, j, l, s) depend(in:layers[l].neu[i].nv) depend(out:layers[l + 1].neu[j].nv) + { + layers[l + 1].neu[j].nv += update(layers[l].neu[i].nv, layers[l].syn[s].sv); + } + } + } +} + +/* + +Résultats: n=10, L=10, host=tanche.enseeiht.fr + +threads = 1: +Sequential time : 674.12 msec. +Parallel loops time : 674.15 msec. Result is correct :-) +Parallel tasks time : 674.24 msec. Result is correct :-) + +threads = 2: +Sequential time : 674.10 msec. +Parallel loops time : 386.93 msec. Result is correct :-) +Parallel tasks time : 339.44 msec. Result is correct :-) + +threads = 4: +Sequential time : 674.11 msec. +Parallel loops time : 213.75 msec. Result is correct :-) +Parallel tasks time : 177.86 msec. Result is correct :-) + +threads = 10: +Sequential time : 674.10 msec. +Parallel loops time : 115.60 msec. Result is correct :-) +Parallel tasks time : 120.10 msec. Result is correct :-) + +threads = 20: +Sequential time : 674.16 msec. +Parallel loops time : 82.55 msec. Result is correct :-) +Parallel tasks time : 108.47 msec. Result is correct :-) + +threads = 30: +Sequential time : 674.08 msec. +Parallel loops time : 85.55 msec. Result is correct :-) +Parallel tasks time : 108.53 msec. Result is correct :-) + + +Commentaires: +On observe un accélération notable de notre puissance de calcul. +Notre temps de calcul est environ divisé par le nombre de threads. +On observe tout de même un rendement décroissant s'il l'on augmente trop le nombre de threads, +et si la taille de nos données est limité, si on augmentre notre charge de calcul alors on retrouve notre avantage : + +threads = 30, n=50, L=5: +Sequential time : 7808.44 msec. +Parallel loops time : 346.61 msec. Result is correct :-) +Parallel tasks time : 296.00 msec. Result is correct :-) + +*/ \ No newline at end of file diff --git a/BE_OpenMP_2022/sparse_nn/subject.pdf b/BE_OpenMP_2022/sparse_nn/subject.pdf new file mode 100644 index 0000000..0840bd9 Binary files /dev/null and b/BE_OpenMP_2022/sparse_nn/subject.pdf differ diff --git a/BE_OpenMP_2022/subject.pdf b/BE_OpenMP_2022/subject.pdf new file mode 100644 index 0000000..b09d8f1 Binary files /dev/null and b/BE_OpenMP_2022/subject.pdf differ diff --git a/TP1/.vscode/settings.json b/TP1/.vscode/settings.json new file mode 100644 index 0000000..ac85aeb --- /dev/null +++ b/TP1/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "editor.formatOnSave": false, + "svg.preview.background": "custom", + "remote.autoForwardPorts": false +} \ No newline at end of file diff --git a/TP1/Makefile b/TP1/Makefile new file mode 100644 index 0000000..82e8c60 --- /dev/null +++ b/TP1/Makefile @@ -0,0 +1,26 @@ +CC = gcc +FC = gfortran +LINK = $(FC) + +FCFLAGS = -O3 -fopenmp +CFLAGS = -O3 -fopenmp -Wunknown-pragmas +LDFLAGS = $(FCFLAGS) +LBLAS = /mnt/n7fs/ens/tp_abuttari/acml-4.4.0/gfortran64/lib/libacml.a -lm + +OBJS = aux.o auxf.o lu_seq.o lu_par_loop.o lu_par_dag.o kernels.o main.o trace.o + +main: clean $(OBJS) + $(LINK) $(LDFLAGS) -o $@ $(OBJS) $(LBLAS) + +main_dbg: + ($(MAKE) clean main CDEFS=-DDBG) + +clean: + (rm -f *.o *.svg main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< diff --git a/TP1/aux.c b/TP1/aux.c new file mode 100644 index 0000000..52499c7 --- /dev/null +++ b/TP1/aux.c @@ -0,0 +1,10 @@ +#include +#include +#include + +long usecs (){ + struct timeval t; + + gettimeofday(&t,NULL); + return t.tv_sec*1000000+t.tv_usec; +} diff --git a/TP1/auxf.f90 b/TP1/auxf.f90 new file mode 100644 index 0000000..f8abd99 --- /dev/null +++ b/TP1/auxf.f90 @@ -0,0 +1,28 @@ +function dnrm2_c(n, x, incx) bind(c) + use iso_c_binding + + integer(c_int), value :: n, incx + real(c_double) :: x(n), dnrm2_c + + real(kind(1.d0)) :: dnrm2 + + dnrm2_c = dnrm2(n, x(1), incx) + + return + +end function dnrm2_c + + +function dnrmf_c(m, n, a, lda) bind(c) + + use iso_c_binding + + integer(c_int), value :: m, n, lda + real(c_double) :: a(lda,n), dnrmf_c + + real(kind(1.d0)) :: dlange, w + + + dnrmf_c = dlange('F', m, n, a(1,1), lda, w) + +end function dnrmf_c diff --git a/TP1/common.h b/TP1/common.h new file mode 100644 index 0000000..cd06f82 --- /dev/null +++ b/TP1/common.h @@ -0,0 +1,41 @@ +typedef struct infostruct{ + int B; // The size of block-columns + int NB; // The number of block-columns in a matrix + int N; // The total size of the matrix N=B*NB + int *ipiv; // Permutation vector for numerical pivoting +} info_type; + + +typedef double** Matrix; + +/* typedef struct matstruct{ */ + /* double **BC; // Permutation vector for numerical pivoting */ +/* } Matrix; */ + + +typedef enum {PNL = 0, UPD, END, NONE} Type; + +void dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv, int *info); +void dtrsm_(char *side, char *uplo, char *transa, char *diag, + int *m, int *n, const double *alpha, const double *A, int *lda, + double *B, int *ldb); +void dlaswp_(int *n, double * a, int *lda, int *k1, int *k2, int *ipiv, int *incx); +void dlarnv_(int *idist, int *iseed, int *n, double *x); +void dgetrs_(char *t, int *n, int *nrhs, double *A, int *lda, int *ipiv, double *x, int *incx, int *info); +void dgemv_(char *t, int *m, int *n, const double *alpha, const double *A, int *lda, const double *x, int *incx, const double *beta, double *y, int *incy); +double dnrm2_c(int n, double *x, int incx); +double dnrmf_c(int m, int n, double *A, int lda); + +void dgemm_(char *ta, char *tb, int *m, int *n, int *k, const double *alpha, const double *A, int *lda, const double *B, int *ldB, const double *beta, const double *c, int *ldc); + +void panel(double *P, int k, info_type info ); +void update(double *P, double *U, int k, int j, info_type info); +void backperm(Matrix A, info_type info); +void checkres(double *A, double *Acpy, info_type info); + +long usecs (); + + +void lu_seq (Matrix A, info_type info); +void lu_par_loop (Matrix A, info_type info); +void lu_par_dag (Matrix A, info_type info); diff --git a/TP1/kernels.c b/TP1/kernels.c new file mode 100644 index 0000000..0f1d9ce --- /dev/null +++ b/TP1/kernels.c @@ -0,0 +1,114 @@ +#include "trace.h" +#include "common.h" +#include +#include +#include + +void panel(double *P, int k, info_type info){ + + int m, ld, err, np, i; + + i = k*info.B; + np = info.B; + m = info.N-i; + ld = info.N; +#if defined(DBG) + printf("%2d -- panel : %d\n",omp_get_thread_num(),k); +#endif + trace_event_start(PNL); + dgetrf_(&m, &np, P+i, &ld, info.ipiv+i, &err); + trace_event_stop(PNL); +} + + +void update(double *P, double *U, int k, int j, info_type info){ + + int m, mu, nu, np, ld, err, i; + char NoTran = 'N', Lower='L', Unit='U', Left='L'; + int IONE=1, IMONE=-1, IZERO=0; + double DONE=(double)1.0, DMONE=-1.0, DZERO=0.0; + + i = k*info.B; + np = info.B; + nu = info.B; + + m = info.N-i; + mu = m-np; + ld = info.N; + +#if defined(DBG) + printf("%2d -- update: %d %d\n",omp_get_thread_num(),k,j); +#endif + trace_event_start(UPD); + dlaswp_(&nu, U+i, &ld, &IONE, &np, info.ipiv+i, &IONE); + dtrsm_ (&Left, &Lower, &NoTran, &Unit, + &np, &nu, + &DONE, + P+i, &ld, + U+i, &ld); + dgemm_ (&NoTran, &NoTran, + &mu, &nu, &np, + &DMONE, + P+i+np, &ld, + U+i, &ld, + &DONE, + U+i+np, &ld); + trace_event_stop(UPD); + + return; +} + + +void backperm(Matrix A, info_type info){ + + int i, j, ld, ipb, ipo; + int IONE=1; + + ld = info.N; + + trace_event_start(END); + for(i=info.B; i +#include +#include "trace.h" +#include "common.h" +#include + +/* This struct defines a task; it can be a panel (Task.type==PNL), an + update (Task.type==UPD) or a termination message + (Task.type==END). If Task.type==PNL, then the panel operation has + to be executed on column Task.p. If Task.type==UPD the the update + operation has to be executed on column Task.u using column + Task.p.*/ +typedef struct taskstruct{ + Type type; + int p; + int u; +} Task; + +/* This struct defines a progress table (see details below). */ +typedef struct prog_table_struct{ + int NB; + int *table; +} ProgTable; + + + +Task fetch_task( ProgTable ptable ); + + + +/* This routine performs a parallel LU factorization based on the + dependencies among operations. These dependencies are represented + in a progress table of the type ProgTable above. This progress + table is nothing more than an array of size NB (number of + block-columns in the matrix) where each coefficient tracks the + status of a block-column. Precisely, ProgTabl.table[j]=i means that + block-column j is up-to-date with respect to the panel operation i, + i.e., the operation update(i,j) has bee executed. Equivalently + ProgTable[i]=i means that the operation panel(i) has been already + executed. Two main rules define the order in which operations have + to be executed: + + 1) panel(i) can only be executed after update(0,i), + update(1,i),...,update(i-1,i), i.e., only if ProgTable[i]=i-1. + + 2) update(i,j) can only be executed after panel(i) and after + update(1,i),...,update(i-1,i), i.e., only if ProgTable[j]=i-1 + and ProgTable[i]=i. + + This code works as follows: each thread enters an "endless" loop + where at each iteration it performs the following steps: + + 1) calls the fetch_task. This routine analyses the progress table + looking for operations to perform according to the rules above + + 2) if one operation is found, the corresponding action is executed + and the progress table is updated accordingly. Note that in a + sequential execution there will always be an operation ready for + being executed whereas in parallel this may not be the case. + + Threads exit from the loop when all operations are performed, i.e., + wher ProgTable[NB]=NB (i.e., panel(NB) has been performed). + + The initial code is sequential. OpenMP directives have to be added + in the two routines below to parallelize it. + +*/ + + +void lu_par_dag(Matrix A, info_type info){ + + ProgTable ptable; + Task task; + int i; + + ptable.table = (int*)malloc(info.NB*sizeof(int)); + ptable.NB = info.NB; + for(i=0; i + + +/* This routine performs the LU factorization of a square matrix by + block-columns */ + +void lu_par_loop(Matrix A, info_type info){ + + int i, j; + + /* Initialize the tracing system */ + trace_init(); + + /* openMP magic stuff */ + #pragma omp parallel private(i) + + for(i=0; i +#include +#include +#include +#include +#include "common.h" + + + + +int main(int argc, char **argv){ + + int N, NB, B, NN; + double flops, nrm2, nrmf; + double *Acpy1, *Acpy2, *x, *b; + Matrix A; + info_type info; + long t_start,t_end; + int err, nth, i, j; + int ISEED[4] = {0,0,0,1}; + int IONE=1; + char NoTran = 'N', *nt; + double DONE=1.0, DMONE=-1.0; + + + if(argc != 3){ + printf("Usage:\n\n./main B NB\n\nwhere B is the size of block-columns and \n\ +NB is the number of block-columns the matrix is made of.\n"); + return 1; + } + + + B = atoi(argv[1]); /* block size */ + NB = atoi(argv[2]); /* dimension in blocks */ + N = B*NB; + NN = N*N; + + nt = getenv("OMP_NUM_THREADS"); + + flops = ((double)2.0*(double) N)*((double) N)*((double) N)/3.0; + + Acpy1 = (double *)malloc(NN*sizeof(double)); + Acpy2 = (double *)malloc(NN*sizeof(double)); + info.ipiv = (int *)malloc(N*sizeof(int)); + + dlarnv_(&IONE, ISEED, &NN, Acpy1); + + info.B = B; + info.NB = NB; + info.N = N; + + printf("Matrix size: %d\n",N); + + A = (double **)malloc(info.NB*sizeof(double*)); + /* get pointers to block-columns */ + for (j=0; j + + +Event events[MAXTHREADS][MAXEVENTS]; +int nevents[MAXTHREADS]; + + +void trace_init(){ + int i; + +#pragma omp master + { + /* strcpy(colors[0], "#d38d5f"); */ + /* strcpy(colors[1], "#ffdd55"); */ + /* strcpy(colors[2], "#8dd35f"); */ + /* strcpy(colors[3], "#80b3ff"); */ + /* strcpy(colors[4], "#e580ff"); */ + + for(i=0; i 0) nth=i+1; + + /* scale_x = 1000.0; */ + /* scale_y = ((double)(nth+1)) *30000 / ((double)(t_stop-t_zero)); */ + + scale_x = ((double)(t_stop-t_zero))/1000.0; + scale_y = 0.1; + + + + pFile = fopen (fname,"w"); + fprintf(pFile,"\n", + ((double)t_stop-t_zero)*1.06/scale_x, ((double)nth+1)*1.05/scale_y+8); + + for(t=0; t\n", + (double)(ev.t_start-t_zero)/scale_x, + ((double)t)/scale_y, + ((double)(ev.t_stop-ev.t_start))/scale_x, + ((double)1.0)/scale_y, + colors[ev.type]); + } + + } + + + + fprintf(pFile, "\n", + ((double)nth+1)*1.01/scale_y, + ((double)t_stop-t_zero)*1.02/scale_x, + ((double)nth+1)*1.01/scale_y); + + for(t=0; tThread %d\n", + ((double)t_stop-t_zero)*1.01/scale_x, ((double)t+0.8)/scale_y, t); + } + + fprintf(pFile,"Time (usec.)\n",((double)nth+1)*1.05/scale_y+7); + + for(x=((double)t_stop-t_zero)/scale_x/10.0; x<=((double)t_stop-t_zero)/scale_x; x+=((double)t_stop-t_zero)/scale_x/10.0){ + fprintf(pFile, "\n", + x,((double)nth+1)*1.01/scale_y-1, x, ((double)nth+1)*1.01/scale_y+1); + fprintf(pFile," %.0f \n", + x,((double)nth+1)*1.01/scale_y+7,x*scale_x); + } + + + fprintf(pFile,"\n"); + } +} diff --git a/TP1/trace.h b/TP1/trace.h new file mode 100644 index 0000000..83a75aa --- /dev/null +++ b/TP1/trace.h @@ -0,0 +1,22 @@ +#include +#include + +long t_zero; + +#define MAXEVENTS 10000 +#define MAXTHREADS 48 + +long usecs (); + + +typedef struct event_struct{ + int type; + long t_start, t_stop; +} Event; + + +void trace_init(); +void trace_event_start(int type); +void trace_event_stop(int type); +void trace_dump(char *); + diff --git a/TP1/trace_par_dag.svg b/TP1/trace_par_dag.svg new file mode 100644 index 0000000..831576b --- /dev/null +++ b/TP1/trace_par_dag.svg @@ -0,0 +1,520 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Thread 0 +Thread 1 +Thread 2 +Thread 3 +Thread 4 +Thread 5 +Thread 6 +Thread 7 +Thread 8 +Thread 9 +Thread 10 +Thread 11 +Thread 12 +Thread 13 +Thread 14 +Thread 15 +Thread 16 +Thread 17 +Thread 18 +Thread 19 +Thread 20 +Thread 21 +Thread 22 +Thread 23 +Thread 24 +Thread 25 +Thread 26 +Thread 27 +Thread 28 +Thread 29 +Time (usec.) + + 47226 + + 94451 + + 141677 + + 188902 + + 236128 + + 283354 + + 330579 + + 377805 + + 425030 + + 472256 + diff --git a/TP1/trace_par_loop.svg b/TP1/trace_par_loop.svg new file mode 100644 index 0000000..39f05ab --- /dev/null +++ b/TP1/trace_par_loop.svg @@ -0,0 +1,519 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Thread 0 +Thread 1 +Thread 2 +Thread 3 +Thread 4 +Thread 5 +Thread 6 +Thread 7 +Thread 8 +Thread 9 +Thread 10 +Thread 11 +Thread 12 +Thread 13 +Thread 14 +Thread 15 +Thread 16 +Thread 17 +Thread 18 +Thread 19 +Thread 20 +Thread 21 +Thread 22 +Thread 23 +Thread 24 +Thread 25 +Thread 26 +Thread 27 +Thread 28 +Time (usec.) + + 39399 + + 78797 + + 118196 + + 157595 + + 196994 + + 236392 + + 275791 + + 315190 + + 354588 + + 393987 + diff --git a/TP1/trace_seq.svg b/TP1/trace_seq.svg new file mode 100644 index 0000000..ad3cd80 --- /dev/null +++ b/TP1/trace_seq.svg @@ -0,0 +1,491 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Thread 0 +Time (usec.) + + 210290 + + 420581 + + 630871 + + 841161 + + 1051452 + + 1261742 + + 1472032 + + 1682322 + + 1892613 + + 2102903 + diff --git a/TP2/.vscode/settings.json b/TP2/.vscode/settings.json new file mode 100644 index 0000000..9792498 --- /dev/null +++ b/TP2/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.formatOnSave": false +} \ No newline at end of file diff --git a/TP2/Makefile b/TP2/Makefile new file mode 100644 index 0000000..7f0bee2 --- /dev/null +++ b/TP2/Makefile @@ -0,0 +1,30 @@ +CC = gcc +LINK = $(CC) + +CFLAGS = -O3 -fopenmp -Wunknown-pragmas +LDFLAGS = $(CFLAGS) +LIBS = -lm + +OBJS = treetrav_seq.o treetrav_par.o main.o + +main: $(OBJS) + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + + + + + + +clean: + (rm -f *.o main) + + + +%.o: %.c + $(CC) $(CFLAGS) $(CINCLUDES) $(INCLUDES) $(CDEFS) $(PREC) -c $< +%.o: %.f90 + $(FC) $(FCFLAGS) $(FINCLUDES) $(INCLUDES) $(FDEFS) $(DEFINE_PREPEND)$(PREC) -c $< + + + + diff --git a/TP2/main.c b/TP2/main.c new file mode 100644 index 0000000..c5263ff --- /dev/null +++ b/TP2/main.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include +#include +#include "omp.h" +#include "treetrav.h" + +long usecs (){ + struct timeval t; + + gettimeofday(&t,NULL); + return t.tv_sec*1000000+t.tv_usec; +} + + + +int main(int argc, char **argv){ + + int l, nth, i; + TreeNode *root; + long t_start, t_end, save; + + + if(argc!=3){ + printf("Wrong number of arguments.\n Usage:\n\n\ +./main l nthreads\n\n where l is the number of levels\n\ +and nthreads is the number of threads to use in the parallel code.\n"); + return 1; + } + + + l = atoi(argv[1]); /* levels in the tree */ + nth = atoi(argv[2]); /* the number of threads */ + + + treeinit(&root, l, 0); + printf("\n\nSequential tree traversal\n"); + t_start = usecs(); + /* Do the sequential tree traversal */ + treetraverse_seq(root); + t_end = usecs(); + printf("root->v : %ld\n",root->v); + printf("time : %8.2f msec.\n",((double)t_end-t_start)/1000.0); + printf("counts: "); + for(i=0; iv; + + /* Destroy and reinit the tree */ + treedestroy(root); + + treeinit(&root, l, 0); + printf("\n\nParallel tree traversal with %2d threads\n",nth); + t_start = usecs(); + /* Do the parallel tree traversal */ + treetraverse_par(root, nth); + t_end = usecs(); + printf("root->v : %ld\n",root->v); + printf("time : %8.2f msec.\n",((double)t_end-t_start)/1000.0); + printf("counts: "); + for(i=0; iv != save){ + printf("\nERROR: The computed value is not correct!!! Seq=%ld != Par=%ld\n", + save,root->v); + } else { + printf("\nThe result is correct\n"); + } + + return 0; +} diff --git a/TP2/subject.pdf b/TP2/subject.pdf new file mode 100644 index 0000000..1c880a1 Binary files /dev/null and b/TP2/subject.pdf differ diff --git a/TP2/treetrav.h b/TP2/treetrav.h new file mode 100644 index 0000000..dab7806 --- /dev/null +++ b/TP2/treetrav.h @@ -0,0 +1,29 @@ +typedef struct treenode{ + /* Pointers to the left and right children */ + struct treenode *left, *right; + /* The node number */ + int n; + /* The node level in the tree */ + int l; + /* A value associated to the node which is computed during the traversal */ + long v; + /* Some data associated to the node which is used during the traversal */ + double *data; +} TreeNode; + +void treeinit(TreeNode **root, int l, int po); +void treedestroy(TreeNode *root); + +void treetraverse_par(TreeNode *root, int nth); +void treetraverserec_par(TreeNode *root, int depth); + +void treetraverse_seq(TreeNode *root); +void treetraverserec_seq(TreeNode *root); + + +#define MAXTHREADS 16 +#define DATASIZE 4 +#define NIT 100 + + +int countnodes[MAXTHREADS]; diff --git a/TP2/treetrav_par.c b/TP2/treetrav_par.c new file mode 100644 index 0000000..ddd330e --- /dev/null +++ b/TP2/treetrav_par.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include "treetrav.h" +#include "omp.h" + +/* This is simply a wrapper for the recursive tree traversal + routine */ + +/* This nth argument defines the number of threads to be used in the + recursive tree traversal. */ + +void treetraverse_par(TreeNode *root, int nth) +{ + + int depth, i; + + /* To be used in the second part of the excercise */ + depth = 15; + + /* Initialize the counter to 0. MAXTHREADS is the maximum number of + allowed threads. */ + for (i = 0; i < MAXTHREADS; i++) + countnodes[i] = 0; + +#pragma omp parallel +#pragma omp single + + /* Start the tree traversal by calling the recursive routine */ + treetraverserec_par(root, depth); + + return; +} + +/* This recursive routine performs a topological order tree traversal + starting from the root node pointed by *root */ + +/* In the second part of the excercise, the depth argument will be + used to define a layer in the tree below which tasks will be + undeferred and immediately executed; this allows to reduce the + overhead of creating and handling submitted tasks. */ + +void treetraverserec_par(TreeNode *root, int depth) +{ + double sum; + int i, iam, it; + + if (root->l != 1) + {// If this node is not a leaf.. + +#pragma omp task if (root->l > depth) + + // ...visit the left subtree.. + treetraverserec_par(root->left, depth); + +#pragma omp task if (root->l > depth) + + // ...visit the right subtree... + treetraverserec_par(root->right, depth); + +#pragma omp taskwait + + // ...compute root->v as the sum of the v values on the left and right children... + root->v += (root->right)->v + (root->left)->v; + } + + // ...add root->n to root->v... + root->v += root->n; + + // ...do some random work... + for (it = 0; it < NIT; it++) + for (i = 1; i < DATASIZE; i++) + root->data[0] += root->data[i]; + + //...increment the counter of the number of nodes treated by the executing thread. + iam = omp_get_thread_num(); + countnodes[iam] += 1; + + return; +} diff --git a/TP2/treetrav_seq.c b/TP2/treetrav_seq.c new file mode 100644 index 0000000..1376c33 --- /dev/null +++ b/TP2/treetrav_seq.c @@ -0,0 +1,120 @@ +#include +#include +#include +#include "treetrav.h" +#include "omp.h" + +/* This is simply a wrapper for the recursive tree traversal + routine */ +void treetraverse_seq(TreeNode *root){ + + int i; + + /* Initialize the counter to 0. MAXTHREADS is the maximum number of + allowed threads. */ + for(i=0; il != 1){ + /* If this node is not a leaf...*/ + + /* ...visit the left subtree... */ + treetraverserec_seq(root->left); + + /* ...visit the right subtree... */ + treetraverserec_seq(root->right); + + /* ...compute root->v as the sum of the v values on the left and + right children... */ + root->v += (root->right)->v + (root->left)->v; + } + + /* ...add root->n to root->v... */ + root->v += root->n; + + /* ...do some random work... */ + for(it=0; itdata[0] += root->data[i]; + + + /* ...increment the counter of the number of nodes treated by the + executing thread. */ + iam = 0; + countnodes[iam] +=1; + + return; + +} + + + + + + + + + + + + + +/********************************************************************* +Don't touch below this point +*********************************************************************/ + +/* Tree initialization routine */ +void treeinit(TreeNode **root, int l, int po){ + int i; + + *root = (TreeNode*)malloc(sizeof(TreeNode)); + + (*root)->v = 0; + (*root)->l = l; + (*root)->n = po+pow(2,l)-1; + (*root)->data = (double*)malloc(DATASIZE*sizeof(double)); + for (i=0; idata[i] = (double)rand()/RAND_MAX; + + if(l == 1){ + return; + } + + treeinit(&(*root)->left, l-1, po); + treeinit(&(*root)->right, l-1, po+pow(2,l-1)-1); + + return; + +} + + + + +/* Tree cleanup routine */ +void treedestroy(TreeNode *root){ + + if(root->l != 1){ + treedestroy(root->left); + treedestroy(root->right); + } + free(root->data); + free(root); + return; + +}