Browse Source

Time the problems and launch a fixed number before exiting

Ian Goldberg 14 years ago
parent
commit
87ea78a8c2
1 changed files with 65 additions and 8 deletions
  1. 65 8
      controller.cc

+ 65 - 8
controller.cc

@@ -12,6 +12,8 @@ extern "C" {
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#include <sys/time.h>
+
 #include <fstream>
 #include <vector>
 #include <set>
@@ -42,6 +44,17 @@ void besetdump(const BESet &bes, ostream &os)
     os << dec << "\n";
 }
 
+void besetfree(BESet &bes)
+{
+    BESet::iterator besit;
+
+    for (besit = bes.begin(); besit != bes.end(); ++besit) {
+	bufferevent_free(*besit);
+    }
+
+    bes.clear();
+}
+
 void bemapdump(const BEMap &bem, ostream &os)
 {
     BEMap::const_iterator bemit;
@@ -53,6 +66,17 @@ void bemapdump(const BEMap &bem, ostream &os)
     os << dec << "\n";
 }
 
+void bemapfree(BEMap &bem)
+{
+    BEMap::iterator bemit;
+
+    for (bemit = bem.begin(); bemit != bem.end(); ++bemit) {
+	bufferevent_free(bemit->first);
+    }
+
+    bem.clear();
+}
+
 struct Statuses {
     BESet idle;
     BEMap working;
@@ -64,6 +88,11 @@ struct Statuses {
 	os << "  working (" << working.size() << "):\n";
 	bemapdump(working, os);
     }
+
+    void free(void) {
+	besetfree(idle);
+	bemapfree(working);
+    }
 };
 
 struct FactorDecomp {
@@ -78,11 +107,15 @@ static struct ControllerState {
     FactorDecomp p, q;
     ZZ base, target;
     bool working;
+    struct timeval started_working;
     vector<SubproblemProgress> subproblems_p, subproblems_q;
     Statuses dpnodes, workers;
     unsigned int num_unsolved_subproblems;
+    unsigned int problems_remaining;
+    struct evconnlistener *listener;
 
-    ControllerState() : working(false), num_unsolved_subproblems(0) {}
+    ControllerState() : working(false), num_unsolved_subproblems(0),
+	problems_remaining(0), listener(NULL) {}
 
     // Reset the state for a new problem with the same modulus
     void reset(void) {
@@ -92,6 +125,8 @@ static struct ControllerState {
 	subproblems_p.clear();
 	subproblems_q.clear();
 	num_unsolved_subproblems = 0;
+	started_working.tv_sec = 0;
+	started_working.tv_usec = 0;
     }
 
     // Dump the state for debug purposes
@@ -214,7 +249,7 @@ struct SubproblemProgress : Subproblem {
 	    bufferevent_write(bev, ipports[i].ipport, 6);
 	}
 #ifdef DEBUG
-	cerr << "Added worker " << bev << "to subproblem "
+	cerr << "Added worker " << bev << " to subproblem "
 		<< problemid << "\n";
 #endif
     }
@@ -358,12 +393,22 @@ static void computation_complete(void)
     }
     ZZ& expon = exp_p;
 
+    struct timeval ended_working;
+    gettimeofday(&ended_working, NULL);
+    unsigned long long computation_length_ms =
+	(ended_working.tv_sec - ctrlstate.started_working.tv_sec) * 1000 +
+	(ended_working.tv_usec - ctrlstate.started_working.tv_usec) / 1000;
+    char length_buf[50];
+    sprintf(length_buf, "%lld.%03lld s", computation_length_ms / 1000,
+					    computation_length_ms % 1000);
+
     cout << "expon = " << expon << "\n";
     ZZ base_exp = PowerMod(ctrlstate.base, expon, ctrlstate.rho);
     if (base_exp == ctrlstate.target) {
-	cout << "CORRECT!\n";
+	cout << "CORRECT in " << length_buf << "\n";
     } else {
-	cout << "INCORRECT:\nbase^exp = " << base_exp << "\n";
+	cout << "INCORRECT in " << length_buf << ":\n";
+	cout << "base^exp = " << base_exp << "\n";
 	cout << "target   = " << ctrlstate.target << "\n";
     }
 
@@ -429,6 +474,14 @@ static vector<SubproblemProgress> decomp(const ZZ_p &base, const ZZ_p &target,
 
 static int generate_problem(struct event_base *evbase)
 {
+    // If there are no more problems to generate, close the listener
+    if (ctrlstate.problems_remaining == 0) {
+	evconnlistener_free(ctrlstate.listener);
+	ctrlstate.dpnodes.free();
+	ctrlstate.workers.free();
+	return -1;
+    }
+
     // If there's already a problem on the go, don't generate another one
     if (ctrlstate.working == true) {
 	return -1;
@@ -443,6 +496,7 @@ static int generate_problem(struct event_base *evbase)
     do {
 	ZZ_p base = power(random_ZZ_p(), 2);
 	ZZ_p target = power(random_ZZ_p(), 2);
+	gettimeofday(&ctrlstate.started_working, NULL);
 	ctrlstate.base = rep(base);
 	ctrlstate.target = rep(target);
 
@@ -458,6 +512,8 @@ static int generate_problem(struct event_base *evbase)
 
     schedule();
 
+    --ctrlstate.problems_remaining;
+
     return 0;
 }
 
@@ -552,7 +608,6 @@ static void controller_dpnode_reader(struct bufferevent *bev, void *ctx)
 			if (ctrlstate.num_unsolved_subproblems == 0) {
 			    computation_complete();
 			    generate_problem(bufferevent_get_base(bev));
-			    ctrlstate.dump(cerr);
 			}
 			schedule();
 		    }
@@ -683,8 +738,8 @@ static void controller_accept_cb(struct evconnlistener *listener,
 // Create a new controller socket.  bindport is the port to bind to (in
 // host byte order), or 0 if any port will do.  ip and boundport are set
 // to the IP and port of the socket, in network byte order.
-void *controller_create(struct event_base *evbase, unsigned short bindport,
-    unsigned int *ip, unsigned short *boundport)
+struct evconnlistener *controller_create(struct event_base *evbase,
+    unsigned short bindport, unsigned int *ip, unsigned short *boundport)
 {
     return listener_create(evbase, bindport, controller_accept_cb, NULL,
 	ip, boundport, false);
@@ -715,10 +770,12 @@ int main(int argc, char **argv)
     unsigned int myip;
     unsigned short myport;
 
-    controller_create(evbase, bindport, &myip, &myport);
+    ctrlstate.listener = controller_create(evbase, bindport, &myip, &myport);
     struct in_addr myaddr = { myip };
     printf("Bound to %s:%d\n", inet_ntoa(myaddr), ntohs(myport));
 
+    ctrlstate.problems_remaining = 2;
+
     // Kick off the first problem to solve
     generate_problem(evbase);