From: Ian Jackson Date: Sat, 27 Sep 2008 15:26:20 +0000 (+0100) Subject: parallel thing compiles now X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=moebius2.git;a=commitdiff_plain;h=21a2bd20afe0f4673494f4841a5675ca68cbd2d7 parallel thing compiles now --- diff --git a/Makefile b/Makefile index a0b643a..9443d70 100644 --- a/Makefile +++ b/Makefile @@ -80,8 +80,9 @@ output-%: output+%.o mgraph+%.o common.o interpolate-%: interpolate+%.o mgraph+%.o common.o $(CC) $(CFLAGS) -o $@ $^ $(LIBGSL) -minimise-%: energy+%.o graph+%.o mgraph+%.o minimise+%.o half+%.o common.o - $(CXX) $(CXXFLAGS) -o $@ $^ $(LIBGSL) +minimise-%: energy+%.o graph+%.o mgraph+%.o minimise+%.o \ + half+%.o parallel.o common.o + $(CXX) $(CXXFLAGS) -o $@ $^ $(LIBGSL) -lpthread # this ridiculous repetition is due to make being too lame diff --git a/energy.c b/energy.c index 80ac7e8..5aa1c60 100644 --- a/energy.c +++ b/energy.c @@ -5,51 +5,97 @@ #include "common.h" #include "minimise.h" #include "mgraph.h" +#include "parallel.h" double vertex_areas[N], vertex_mean_edge_lengths[N], edge_lengths[N][V6]; static double best_energy= DBL_MAX; static void addcost(double *energy, double tweight, double tcost, int pr); -#define COST(weight, compute) addcost(&energy, (weight), (compute), printing) + +/*---------- main energy computation, weights, etc. ----------*/ + +typedef double CostComputation(const Vertices vertices, int section); + +typedef struct { + double weight; + CostComputation *fn; +} CostContribution; + +static const CostContribution costs[]= { +#define COST(weight, compute) { (weight),(compute) }, + +#if XBITS==3 +#define STOP_EPSILON 1e-6; + COST( 3e2, line_bending_cost) + COST( 1e3, edge_length_variation_cost) + COST( 0.2e3, rim_proximity_cost) + COST( 1e8, noncircular_rim_cost) +#endif + +#if XBITS==4 +#define STOP_EPSILON 1e-5; + COST( 3e2, line_bending_cost) + COST( 3e3, edge_length_variation_cost) + COST( 3.8e1, rim_proximity_cost) // 5e1 is too much + // 2.5e1 is too little + // 0.2e1 grows compared to previous ? + // 0.6e0 shrinks compared to previous ? + COST( 1e12, noncircular_rim_cost) +#endif +}; + +#define NCOSTS ((sizeof(costs)/sizeof(costs[0]))) void energy_init(void) { + stop_epsilon= STOP_EPSILON; +} + +void compute_energy_separately(const struct Vertices *vs, + int section, void *energies_v, void *totals_v) { + double *energies= energies_v; + int ci; + + compute_edge_lengths(vs->a, section); + compute_vertex_areas(vs->a, section); + + for (ci=0; cia, section); } -/*---------- main energy computation and subroutines ----------*/ +/*---------- energy computation machinery ----------*/ + +void compute_energy_combine(const struct Vertices *vertices, + int section, void *energies_v, void *totals_v) { + int ci; + + double *energies= energies_v; + double *totals= totals_v; + + for (ci=0; cia); - compute_vertex_areas(vs->a); - energy= 0; + double totals[NCOSTS], energy; + int ci, printing; printing= printing_check(pr_cost,0); if (printing) printf("%15lld c>e |", evaluations); - if (XBITS==3) { - COST( 3e2, line_bending_cost(vs->a)); - COST( 1e3, edge_length_variation_cost(vs->a)); - COST( 0.2e3, rim_proximity_cost(vs->a)); - COST( 1e8, noncircular_rim_cost(vs->a)); - stop_epsilon= 1e-6; - } else if (XBITS==4) { - COST( 3e2, line_bending_cost(vs->a)); - COST( 3e3, edge_length_variation_cost(vs->a)); - COST( 3.8e1, rim_proximity_cost(vs->a)); // 5e1 is too much - // 2.5e1 is too little - // 0.2e1 grows compared to previous ? - // 0.6e0 shrinks compared to previous ? - COST( 1e12, noncircular_rim_cost(vs->a)); - stop_epsilon= 1e-5; - } else { - abort(); - } + inparallel(vs, + compute_energy_separately, + compute_energy_combine, + sizeof(totals) /* really, size of energies */, + totals); + + energy= 0; + + for (ci=0; ci> YSHIFT; int nominal_edge_distance= y <= Y/2 ? y : Y-1-y; if (nominal_edge_distance==0) continue; @@ -246,12 +292,12 @@ double rim_proximity_cost(const Vertices vertices) { /*---------- noncircular rim cost ----------*/ -double noncircular_rim_cost(const Vertices vertices) { +double noncircular_rim_cost(const Vertices vertices, int section) { int vy,vx,v; double cost= 0.0; double oncircle[3]; - FOR_RIM_VERTEX(vy,vx,v) { + FOR_RIM_VERTEX(vy,vx,v, OUTER) { find_nearest_oncircle(oncircle, vertices[v]); double d2= hypotD2(vertices[v], oncircle); diff --git a/graph.c b/graph.c index f0ce19d..a81de42 100644 --- a/graph.c +++ b/graph.c @@ -4,6 +4,7 @@ #include "mgraph.h" #include "minimise.h" +#include "parallel.h" static int sqdistances[N][N]; @@ -14,7 +15,7 @@ static void breadth_first_search(int start, int sqdistances_r[N]) { int v,e, current, future, dfuture; buf_push= buf_pop= buffer; - FOR_VERTEX(v) d[v]= -1; + FOR_VERTEX(v,INNER) d[v]= -1; d[start]= 0; *buf_push++= start; @@ -31,7 +32,7 @@ static void breadth_first_search(int start, int sqdistances_r[N]) { assert(buf_pop==buf_push); assert(buf_push <= buffer+sizeof(buffer)/sizeof(buffer[0])); - FOR_VERTEX(v) { + FOR_VERTEX(v,INNER) { assert(d[v] >= 0); sqdistances_r[v]= d[v] * d[v]; } @@ -40,10 +41,10 @@ static void breadth_first_search(int start, int sqdistances_r[N]) { // } -void graph_layout_prepare() { +void graph_layout_prepare(void) { int v1; - FOR_VERTEX(v1) + FOR_VERTEX(v1,INNER) breadth_first_search(v1, sqdistances[v1]); alpha= 2; @@ -53,7 +54,7 @@ void graph_layout_prepare() { } -double graph_layout_cost(const Vertices v) { +double graph_layout_cost(const Vertices v, int section) { /* For each (vi,vj) computes shortest path s_ij = |vi..vj| * along edges, and actual distance d_ij = |vi-vj|. * @@ -76,7 +77,7 @@ double graph_layout_cost(const Vertices v) { int v1,v2,e, nedges=0; double totaledgelength=0, meanedgelength, meanedgelength2; - FOR_EDGE(v1,e,v2) { + FOR_EDGE(v1,e,v2,INNER) { totaledgelength += hypotD(v[v1], v[v2]); nedges++; } @@ -85,8 +86,8 @@ double graph_layout_cost(const Vertices v) { meanedgelength2= meanedgelength * meanedgelength; // printf("mean=%g mean^2=%g\n", meanedgelength, meanedgelength2); - FOR_VERTEX(v1) { - FOR_VERTEX(v2) { + FOR_VERTEX(v1,OUTER) { + FOR_VERTEX(v2,INNER) { if (v1 == v2) continue; double d2= hypotD2(v[v1],v[v2]); diff --git a/half.c b/half.c index 5ac69f8..9051c73 100644 --- a/half.c +++ b/half.c @@ -57,7 +57,7 @@ void pmap_dimensions(const struct Vertices *vs) { bad= 0; - FOR_VERTEX(vc) + FOR_VERTEX(vc,INNER) FOR_COORD(kc) { count[vc][kc]= 0; ixfrom[vc][kc]= -1; @@ -96,7 +96,7 @@ void pmap_dimensions(const struct Vertices *vs) { count[v][k]++; ); - FOR_VERTEX(vc) + FOR_VERTEX(vc,INNER) FOR_COORD(kc) { if (count[vc][kc]==1) continue; printf("BAD %03x %d count=%d ixfrom=%d\n", diff --git a/mgraph.h b/mgraph.h index 06c53e2..7f2ab43 100644 --- a/mgraph.h +++ b/mgraph.h @@ -89,8 +89,11 @@ #define V6 6 #define V3 3 -#define FOR_VERTEX(v) \ - for ((v)=0; (v)= 0); int aroung; @@ -315,7 +315,7 @@ static OutVertex *invertex2outvertexcd(v0,side) { static void outfacets(void) { int v0,e,side,aroung; - FOR_VERTEX(v0) { + FOR_VERTEX(v0, INNER) { OutVertex *defs=0, *defs1=0; int rimy=-1; int_map *defs1aroundmap= 0; diff --git a/parallel.c b/parallel.c new file mode 100644 index 0000000..3c94607 --- /dev/null +++ b/parallel.c @@ -0,0 +1,61 @@ +/* + * Parallel processing + */ + +#include + +#include "mgraph.h" +#include "parallel.h" + +typedef struct { + const struct Vertices *vertices; + Computation *separately; + void *gendata; +} ForAllThreads; + +typedef struct { + ForAllThreads *allthreads; + int section; + void *secdata; + pthread_t thread; +} PerThread; + +static void *routine(void *thread_v) { + PerThread *t= thread_v; + ForAllThreads *a= t->allthreads; + + a->separately(a->vertices, t->section, t->secdata, a->gendata); + + return 0; +} + +void inparallel(const struct Vertices *vertices, + Computation *separately, + Computation *combine, + size_t secdatasz, void *gendata) { + typedef struct { unsigned char secdata[secdatasz]; } SecData; + + ForAllThreads allthreads; + SecData secdatas[nsections]; + PerThread threads[nsections]; + + int s, r; + + allthreads.vertices= vertices; + allthreads.separately= separately; + allthreads.gendata= gendata; + + for (s=0; s