From 6ade4ef8100c03df1479666a52182c3efbdb9884 Mon Sep 17 00:00:00 2001
From: Stefan Brass <stefan.brass@informatik.uni-halle.de>
Date: Tue, 25 Sep 2018 11:08:48 +0200
Subject: [PATCH] Neue Job-Klasse fuer parallele Ausfuehrung

---
 opt/opt.cpp | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 192 insertions(+), 3 deletions(-)

diff --git a/opt/opt.cpp b/opt/opt.cpp
index c0a0351..c8ebab3 100755
--- a/opt/opt.cpp
+++ b/opt/opt.cpp
@@ -26,6 +26,13 @@
 // #define DO_CHECKS 0
 #define DO_CHECKS 1
 
+//=============================================================================
+// How many parallel jobs?
+//=============================================================================
+
+#define NUM_JOBS 2
+
+
 //=============================================================================
 // Type for Large Integers (64 Bit):
 //=============================================================================
@@ -1162,6 +1169,165 @@ int optimize_simple(par_t best_par, sys_t sys,
 	return best_hits;
 }
 
+//=============================================================================
+// Class for Optimization Job (Can be executed in a thread):
+//=============================================================================
+
+class job_c {
+
+	public:
+
+	//---------------------------------------------------------------------
+	// Default Constructor (needed to declare array of jobs):
+	//---------------------------------------------------------------------
+
+	job_c() :
+		MinPar(), MaxPar(), IncPar(), BestPar()
+	{
+		Sys   = nullptr;
+		JobNo = 0;
+		BestHits = -1;
+	}
+
+	//---------------------------------------------------------------------
+	// This does the real initialization:
+	//---------------------------------------------------------------------
+
+	void init(sys_t job_sys, const par_c& job_min_par,
+			const par_c& job_max_par, const par_c& job_inc_par,
+			int split_dimen, int split_jobs, int job_no)
+	{
+		// Store given data:
+		Sys      = job_sys;
+		MinPar   = job_min_par;
+		MaxPar   = job_max_par;
+		IncPar   = job_inc_par;
+		JobNo    = job_no;
+		BestHits = -1;
+
+		// Check splitting parameters:
+#if DO_CHECK
+		if(split_jobs < 1) {
+			std::cerr << "Invalid number of jobs: " <<
+					split_jobs << "\n";
+			exit(6);
+		}
+		if(job_no < 0 || job_no >= split_jobs) {
+			std::cerr << "Invalid job no: " << job_no << "\n";
+			exit(6);
+		}
+#endif
+
+		// Split parameter range in given dimension (for parallel exec):
+		if(split_dimen == par_c::DIMEN_NULL || split_jobs <= 1)
+			return;
+		long min = MinPar.get(split_dimen);
+		long max = MaxPar.get(split_dimen);
+		long inc = IncPar.get(split_dimen);
+		long diff = max - min;
+		long steps = IDIV_CEILING((diff+1), inc);
+		if(steps < split_jobs) {
+			std::cerr << split_jobs << " jobs requested, " <<
+				"but only " << steps << " steps " <<
+				"in dimension " << split_dimen << ".\n";
+				exit(7);
+		}
+		long steps_per_job = steps / split_jobs;
+		MinPar.set(split_dimen, min + job_no * steps_per_job * inc);
+		MaxPar.set(split_dimen,
+			min + (job_no+1) * steps_per_job * inc - 1);
+		if(job_no == split_jobs - 1)
+			MaxPar.set(split_dimen, max);
+std::cout << "Job " << JobNo << ": Min= " << MinPar.get(split_dimen) <<
+		", Max = " << MaxPar.get(split_dimen) << "\n";
+	}
+
+	//---------------------------------------------------------------------
+	// Do Optimization (without relative optimization):
+	//---------------------------------------------------------------------
+
+	int optimize_simple()
+	{
+		int max_hits = 0;
+
+		// Compute total number of steps:
+		bigint_t total_steps = 1;
+		for(int d = par_c::DIMEN_FIRST; d <= par_c::DIMEN_LAST; d++) {
+			long diff = MaxPar.get(d) - MinPar.get(d);
+			total_steps *= IDIV_CEILING((diff+1), IncPar.get(d));
+		}
+
+std::cout << "Job: " << JobNo << "\n";
+std::cout << "Min: "; MinPar.print_short();
+std::cout << "Max: "; MaxPar.print_short();
+std::cout << "Inc: "; IncPar.print_short();
+std::cout << "Steps: " << total_steps << std::endl;
+
+		// For output of progress:
+		bigint_t one_percent = IDIV_CEILING(total_steps, 100);
+		bigint_t countdown = 1;
+		int pct = 0;
+
+		// Optimization:
+		par_c par = MinPar;
+		while(1) {
+			// Print control output:
+			if(--countdown <= 0) {
+				std::cout << "[Job: " << JobNo << ", done: " <<
+					pct << "%]" << std::endl;
+				countdown = one_percent;
+				pct++;
+			}
+
+			//par.print_short();
+
+			int hits = check_formula(&par, Sys);
+			if(hits > max_hits) {
+				BestPar = par;
+				max_hits = hits;
+			}
+
+			// Determine next parameter value:
+			int dimen = par_c::DIMEN_LAST;
+			while(dimen >= par_c::DIMEN_FIRST) {
+				par.add(dimen, IncPar.get(dimen));
+				if(par.get(dimen) <= MaxPar.get(dimen))
+					break;
+				par.set(dimen, MinPar.get(dimen));
+				dimen--;
+				
+			}
+			if(dimen < par_c::DIMEN_FIRST)
+				break;
+		}
+
+		BestHits = max_hits;
+		return max_hits;
+	}
+
+	//---------------------------------------------------------------------
+	// Attribute Accessor Functions:
+	//---------------------------------------------------------------------
+
+	inline const par_c *best_par() const { return &BestPar; }
+
+	inline int best_hits() const { return BestHits; }
+
+	//---------------------------------------------------------------------
+	// Attributes:
+	//---------------------------------------------------------------------
+
+	private:
+
+	sys_t Sys;
+	par_c MinPar;
+	par_c MaxPar;
+	par_c IncPar;
+	par_c BestPar;
+	int   BestHits;
+	int   JobNo;
+};
+
 //=============================================================================
 // The main Function (Does the Optimization):
 //=============================================================================
@@ -1218,7 +1384,14 @@ int main(int argc, str_t argv[])
 
 	// Small test search:
 	//         |Startup|   Load|   Rule| Result|DataVal|
-	par_c steps(    500,    500,   1000,   1000,    500);
+	par_c steps(    10,    50,   100,    50,    50);
+
+	// Very Large Search:
+	//         |Startup|   Load|   Rule| Result|DataVal|
+	//par_c steps(    100,    500,   1000,    500,    500);
+	// 12.500.000.000.000 So 11 Stunden CPU-Zeit (40.000s) fuer 1-2%.
+
+	// How many parameter tuples will be considered in total?
 	std::cout << "Number of parameter tuples:     " << steps.prod() << "\n";
 	std::cout << "\n";
 
@@ -1254,10 +1427,26 @@ int main(int argc, str_t argv[])
 	std::cout << "---------\n";
 	inc_par.print("\t");
 
+	// Optimization Jobs:
+	job_c jobs[NUM_JOBS];
+	for(int i = 0; i < NUM_JOBS; i++) {
+		jobs[i].init(sys, min_par, max_par, inc_par,
+				par_c::DIMEN_STARTUP, NUM_JOBS, i);
+	}
 
 	// Do optimization:
-	best_hits = optimize_simple(&best_par, sys,
-			&min_par, &max_par, &inc_par);
+	//best_hits = optimize_simple(&best_par, sys,
+	//		&min_par, &max_par, &inc_par);
+	for(int i = 0; i < NUM_JOBS; i++)
+		jobs[i].optimize_simple();
+
+	// Find the best solution among the job results:
+	best_par = *(jobs[0].best_par());
+	best_hits = jobs[0].best_hits();
+	for(int i = 1; i < NUM_JOBS; i++) {
+		if(jobs[i].best_hits() > best_hits)
+			best_par = *(jobs[i].best_par());
+	}
 
 	// Local Optimization form good starting points:
 	//          Start   Load  RuleApp Result
-- 
GitLab