From: Ian Jackson Date: Sat, 27 Sep 2008 23:43:00 +0000 (+0100) Subject: fix threading bugs and arrangements X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=moebius2.git;a=commitdiff_plain;h=e7355cdc61d082bc1d25a4d460736680e8d1dba2 fix threading bugs and arrangements --- diff --git a/energy.c b/energy.c index e43eced..ae592cf 100644 --- a/energy.c +++ b/energy.c @@ -23,8 +23,12 @@ typedef struct { } CostContribution; static const CostContribution costs[]= { +#define PRECOMP(compute) { 0,(compute) }, #define COST(weight, compute) { (weight),(compute) }, + PRECOMP(compute_edge_lengths) + PRECOMP(compute_vertex_areas) + #if XBITS==3 #define STOP_EPSILON 1e-6 COST( 3e3, line_bending_cost) @@ -59,51 +63,53 @@ 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); +/*---------- energy computation machinery ----------*/ - for (ci=0; cia, section); -} +typedef struct { + double total; + const CostContribution *cc; +} CostComputationData; -/*---------- energy computation machinery ----------*/ +void compute_energy_separately(const struct Vertices *vs, + int section, void *energy_v, void *ccd_v) { + CostComputationData *ccd= ccd_v; + double *energy= energy_v; + *energy= ccd->cc->fn(vs->a, section); +} 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; citotal += *energy; } double compute_energy(const struct Vertices *vs) { static int bests_unprinted; - double totals[NCOSTS], energy; + double energy; int ci, printing; + CostComputationData ccd; printing= printing_check(pr_cost,0); if (printing) printf("%15lld c>e |", evaluations); - inparallel(vs, - compute_energy_separately, - compute_energy_combine, - sizeof(totals) /* really, size of energies */, - totals); - energy= 0; - for (ci=0; ciweight != 0) + addcost(&energy, costs[ci].weight, ccd.total, printing); + } if (printing) printf("| total %# e |", energy); @@ -143,14 +149,16 @@ static void addcost(double *energy, double tweight, double tcost, int pr) { /*---------- Precomputations ----------*/ -void compute_edge_lengths(const Vertices vertices, int section) { +double compute_edge_lengths(const Vertices vertices, int section) { int v1,e,v2; FOR_EDGE(v1,e,v2, OUTER) edge_lengths[v1][e]= hypotD(vertices[v1],vertices[v2]); + + return 0; } -void compute_vertex_areas(const Vertices vertices, int section) { +double compute_vertex_areas(const Vertices vertices, int section) { int v0,v1,v2, e1,e2; // int k; @@ -178,6 +186,8 @@ void compute_vertex_areas(const Vertices vertices, int section) { vertex_areas[v0]= total / count; vertex_mean_edge_lengths[v0]= edges_total / count; } + + return 0; } /*---------- Edgewise vertex displacement ----------*/ diff --git a/mgraph.h b/mgraph.h index 7f2ab43..2ac57c7 100644 --- a/mgraph.h +++ b/mgraph.h @@ -89,6 +89,11 @@ #define V6 6 #define V3 3 + +/* Loop constructors are macros of the form + * LOOP(v,zero,n, precomp) + * which work much like this one: + */ #define INNER(v,zero,n, precomp) \ for ((v)=(zero); precomp, (v)<(n); (v)++) diff --git a/minimise.h b/minimise.h index c2e13e7..29e3207 100644 --- a/minimise.h +++ b/minimise.h @@ -13,8 +13,10 @@ void energy_init(void); double graph_layout_cost(const Vertices v, int section); void graph_layout_prepare(); -void compute_vertex_areas(const Vertices vertices, int section); -void compute_edge_lengths(const Vertices vertices, int section); +double compute_vertex_areas(const Vertices vertices, int section); +double compute_edge_lengths(const Vertices vertices, int section); + /* these don't actually return anything interesting - they're just + * like this so they fit into the parallel/sequential scheme */ extern double vertex_areas[N], vertex_mean_edge_lengths[N], edge_lengths[N][V6]; diff --git a/parallel.h b/parallel.h index 3d50822..19616e4 100644 --- a/parallel.h +++ b/parallel.h @@ -21,6 +21,18 @@ (v) < OUTER_PERSECTION_BASE((zero),(n), section + 1) && (v) < (n); \ (v)++) +/* + * OUTER is a loop constructor like INNER (see mgraph.h). + * + * Constraints on its use: + * - must be in exactly one loop of particular function + * - function must not modify anything other than + * its return value (for cost computation functions, COST()) or + * its designated output (for precomputation functions, PRECOMP()) + * (which latter it may not read) + * - function must of course be reentrant + */ + #define nsections NSECTIONS typedef void Computation(const struct Vertices *vertices, @@ -30,5 +42,13 @@ void inparallel(const struct Vertices *vertices, Computation *separately, Computation *combine, size_t secdatasz, void *gendata); + /* nsections copies of the computation `separately' are run in parallel + * with different values of `section' from 0 to nsections-1. + * Each copy is passed the same gendata as passed to inparallel. + * Each copy gets its own data block (struct aligned) of size + * secdatasz, passed as secdata, uninitialised on entry. + * After all the copies have finished, `combine' is invoked + * nsections times sequentially, with the same sets of arguments. + */ #endif /*PARALLEL_H*/