chiark / gitweb /
fix threading bugs and arrangements
authorIan Jackson <ian@davenant.relativity.greenend.org.uk>
Sat, 27 Sep 2008 23:43:00 +0000 (00:43 +0100)
committerIan Jackson <ian@davenant.relativity.greenend.org.uk>
Sat, 27 Sep 2008 23:43:00 +0000 (00:43 +0100)
energy.c
mgraph.h
minimise.h
parallel.h

index e43ecede21c987bdc638805ccc069d2ab10eff6a..ae592cf4817fb6895f40cf2454cda90b190153bd 100644 (file)
--- 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; ci<NCOSTS; ci++)
-    energies[ci]= costs[ci].fn(vs->a, 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; ci<NCOSTS; ci++)
-    totals[ci] += energies[ci];
+                        int section, void *energy_v, void *ccd_v) {
+  CostComputationData *ccd= ccd_v;
+  double *energy= energy_v;
+  ccd->total += *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; ci<NCOSTS; ci++)
-    addcost(&energy, costs[ci].weight, totals[ci], printing);
+  for (ci=0; ci<NCOSTS; ci++) {
+    ccd.total= 0;
+    ccd.cc= &costs[ci];
+    
+    inparallel(vs,
+              compute_energy_separately,
+              compute_energy_combine,
+              sizeof(energy),
+              &ccd);
+
+    if (ccd.cc->weight != 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 ----------*/
index 7f2ab4397ad747ea54e95901d0f093eb71f42d1a..2ac57c7f6e7b71e333a9190c4653481a81a4c838 100644 (file)
--- a/mgraph.h
+++ b/mgraph.h
 #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)++)
 
index c2e13e7b40fef83169495c5b2754fc91333c90d1..29e320795dc587e7fcebecf7b9690f7ff1f3a194 100644 (file)
@@ -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];
 
index 3d5082285824cf07bd0ab560fe032d0d0567b616..19616e43f64b9aeba95b4dc21e973ec571eab7a9 100644 (file)
        (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*/