-/* Filling the state table is a set of nested for loops NumDimensions deep.
- * We split this into two procedures: 1 and 2. #1 is the outer, slowest-
- * changing indexes. #1 fires off many calls to #2 that run in parallel.
- * The order of the nesting of the dimensions, the order of iteration within
- * each dimension, and where the 1 / 2 split is placed are carefully chosen
- * to make this arrangement safe.
- *
- * Outermost two layers: Go from high-energy states (lots of fuel, edens) to
- * low-energy state. These must be processed sequentially and in this order
- * because you travel through high-energy states to get to the low-energy
- * states.
- *
- * Third layer: Planet. This is a good layer to parallelize on. There's
- * high enough cardinality that we don't have to mess with parallelizing
- * multiple layers for good utilization (on 2011 machines). Each thread
- * works on one planet's states and need not synchronize with peer threads.
- */
-func FillStateTable1(data planet_data, dims []int, table []State) {
- barrier := make(chan bool, len(data.Planets))
- eden_capacity := data.Commodities["Eden Warp Units"].Limit
- work_units := (float64(*fuel) + 1) * (float64(eden_capacity) + 1)
- work_done := 0.0
- for fuel_remaining := *fuel; fuel_remaining >= 0; fuel_remaining-- {
- for edens_remaining := eden_capacity; edens_remaining >= 0; edens_remaining-- {
- for planet := range data.Planets {
- go FillStateTable2(data, dims, table, fuel_remaining,
- edens_remaining, planet, barrier)
- }
- for _ = range data.Planets {
- <-barrier
- }
- work_done++
- print(fmt.Sprintf("\r%3.0f%%", 100*work_done/work_units))