Selaa lähdekoodia

Have the ability to do partial workloads.

(Read: Split searches among multiple machines.)
Sacha Ligthert 1 vuosi sitten
vanhempi
sitoutus
74f1fb63e1
4 muutettua tiedostoa jossa 93 lisäystä ja 0 poistoa
  1. 24 0
      solver/flags.go
  2. 6 0
      solver/solver.go
  3. 61 0
      solver/split.go
  4. 2 0
      solver/types.go

+ 24 - 0
solver/flags.go

@@ -20,6 +20,8 @@ func (solver *Solver) parse_flags() {
 	var row7 string
 	var row8 string
 	var row9 string
+	var split int
+	var part int
 
 	// Define parameters
 	flag.StringVar(&row1, "row1", "000000000", "1st row of the sudoku puzzle.")
@@ -32,10 +34,13 @@ func (solver *Solver) parse_flags() {
 	flag.StringVar(&row8, "row8", "000000000", "8th row of the sudoku puzzle.")
 	flag.StringVar(&row9, "row9", "000000000", "9th row of the sudoku puzzle.")
 	flag.IntVar(&solver.numcpus, "numcpu", runtime.NumCPU(), "Number of CPU cores to assign to this task.")
+	flag.IntVar(&split, "split", 1, "Split the tasks in n parts. This depends on the availability of the first row.")
+	flag.IntVar(&part, "part", 1, "Process part x in n parts. Cannot be lower than 1, or higher than specified in split.")
 
 	// Parse the flags
 	flag.Parse()
 
+	// Process any changes to the CPU usage.
 	if solver.numcpus <= 0 {
 		log.Printf("ERROR: Number of CPU cores must be 1 or higher.\n\n")
 		solver.print_Usage()
@@ -46,6 +51,7 @@ func (solver *Solver) parse_flags() {
 		runtime.GOMAXPROCS(solver.numcpus)
 	}
 
+	// Process rows
 	if row1 == "000000000" || row2 == "000000000" || row3 == "000000000" || row4 == "000000000" || row5 == "000000000" || row6 == "000000000" || row7 == "000000000" || row8 == "000000000" || row9 == "000000000" {
 		log.Printf("ERROR: All parameters must be entered.\n\n")
 		solver.print_Usage()
@@ -74,6 +80,24 @@ func (solver *Solver) parse_flags() {
 	solver.row8 = row8
 	solver.row9 = row9
 
+	// Process workload splitting
+	// Ensure split and part are 1 or higher
+	if split <= 0 || part <= 0 {
+		log.Printf("ERROR: '-split' and '-part' need to be 1 or higher.\n")
+		solver.print_Usage()
+		os.Exit(1)
+	}
+
+	// Ensure part is between 1 and split
+	if part > split {
+		log.Printf("ERROR: '-part' cannot be bigger than `-split`.\n")
+		solver.print_Usage()
+		os.Exit(1)
+	}
+
+	solver.split = split
+	solver.part = part
+
 }
 
 func (solver *Solver) validate_row(name string, row string) {

+ 6 - 0
solver/solver.go

@@ -24,6 +24,12 @@ func Run() {
 	// Find rows that fit with the entered rows
 	solver.populate_blocks()
 
+	// If needed, split the workload
+	// May exit and throw an error if the work load isn't viable
+	if solver.split != 1 {
+		solver.select_workload()
+	}
+
 	// Print the total number of solutions to validate
 	log.Println("Number of (potential) solutions:", solver.iter)
 

+ 61 - 0
solver/split.go

@@ -0,0 +1,61 @@
+package solver
+
+import (
+	"log"
+	"os"
+	"strconv"
+	"time"
+)
+
+// Perform some checks
+// and
+// Modify solver.row1s so it limits the workload to what is only desired.
+func (solver *Solver) select_workload() {
+	if solver.split > len(solver.row1s) {
+		log.Println("ERROR: Unable to divide the workload in " + strconv.Itoa(solver.split) + " parts, when only " + strconv.Itoa(len(solver.row1s)) + " are available.\n\n")
+		os.Exit(1)
+	}
+	defer solver.timeTrack(time.Now(), "Workload set")
+	log.Println("Setting workload")
+	log.Println("We are agent " + strconv.Itoa(solver.part) + " of " + strconv.Itoa(solver.split))
+	workloads := solver.split_workload()
+	solver.set_workload(workloads)
+}
+
+// Determine how workload should be split among the agents
+func (solver *Solver) split_workload() []int {
+	agents := make([]int, solver.split)
+	var tracker int
+	var tasks int = len(solver.row1s)
+
+	for tasks != 0 {
+		agents[tracker] += 1
+		tasks -= 1
+		tracker += 1
+		if tracker == solver.split {
+			tracker = 0
+		}
+	}
+
+	return agents
+}
+
+// Set the workload by setting solver.row1s
+func (solver *Solver) set_workload(agents []int) {
+	var start int = 0
+	var finish int = 0
+	for key, value := range agents {
+		if key == solver.part-1 {
+			finish = start + value
+			break
+		} else {
+			start += value
+		}
+	}
+
+	// Set the shortened set of instructions
+	solver.row1s = solver.row1s[start:finish]
+
+	// Recalculate how much we need to grind through
+	solver.iter = int64(len(solver.row1s)) * int64(len(solver.row2s)) * int64(len(solver.row3s)) * int64(len(solver.row4s)) * int64(len(solver.row5s)) * int64(len(solver.row6s)) * int64(len(solver.row7s)) * int64(len(solver.row8s)) * int64(len(solver.row9s))
+}

+ 2 - 0
solver/types.go

@@ -29,4 +29,6 @@ type Solver struct {
 	solutions []string
 	rates     []int64
 	numcpus   int
+	split     int
+	part      int
 }