|
@@ -106,6 +106,8 @@ struct FactorDecomp {
|
|
|
|
|
|
|
|
static void vsppdump(const vector<SubproblemProgress> &spv, ostream &os);
|
|
static void vsppdump(const vector<SubproblemProgress> &spv, ostream &os);
|
|
|
|
|
|
|
|
|
|
+static unsigned short curproblemid = 0;
|
|
|
|
|
+
|
|
|
static struct ControllerState {
|
|
static struct ControllerState {
|
|
|
ZZ rho;
|
|
ZZ rho;
|
|
|
FactorDecomp p, q;
|
|
FactorDecomp p, q;
|
|
@@ -117,9 +119,10 @@ static struct ControllerState {
|
|
|
unsigned int num_unsolved_subproblems;
|
|
unsigned int num_unsolved_subproblems;
|
|
|
Worklist worklist;
|
|
Worklist worklist;
|
|
|
struct evconnlistener *listener;
|
|
struct evconnlistener *listener;
|
|
|
|
|
+ unsigned int problemid;
|
|
|
|
|
|
|
|
ControllerState() : working(false), num_unsolved_subproblems(0),
|
|
ControllerState() : working(false), num_unsolved_subproblems(0),
|
|
|
- listener(NULL) {}
|
|
|
|
|
|
|
+ listener(NULL), problemid(0) {}
|
|
|
|
|
|
|
|
// Reset the state for a new problem with the same modulus
|
|
// Reset the state for a new problem with the same modulus
|
|
|
void reset(void) {
|
|
void reset(void) {
|
|
@@ -131,6 +134,7 @@ static struct ControllerState {
|
|
|
num_unsolved_subproblems = 0;
|
|
num_unsolved_subproblems = 0;
|
|
|
started_working.tv_sec = 0;
|
|
started_working.tv_sec = 0;
|
|
|
started_working.tv_usec = 0;
|
|
started_working.tv_usec = 0;
|
|
|
|
|
+ problemid = curproblemid++;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Dump the state for debug purposes
|
|
// Dump the state for debug purposes
|
|
@@ -197,11 +201,14 @@ struct SubproblemProgress : Subproblem {
|
|
|
// The solution, if found.
|
|
// The solution, if found.
|
|
|
ZZ solution;
|
|
ZZ solution;
|
|
|
|
|
|
|
|
|
|
+ unsigned int kernel_launch_count;
|
|
|
|
|
+ unsigned int num_workers_replied;
|
|
|
|
|
+
|
|
|
SubproblemProgress(unsigned short id, const ZZ &b, const ZZ &t,
|
|
SubproblemProgress(unsigned short id, const ZZ &b, const ZZ &t,
|
|
|
const ZZ &m, const ZZ &o) :
|
|
const ZZ &m, const ZZ &o) :
|
|
|
// By default, 1 in 1000 points are distinguihed points. The
|
|
// By default, 1 in 1000 points are distinguihed points. The
|
|
|
// number in the next line is 2^32/1000
|
|
// number in the next line is 2^32/1000
|
|
|
- Subproblem(id, b, t, m, o, 4294967), solved(false) {
|
|
|
|
|
|
|
+ Subproblem(id, b, t, m, o, 4294967), solved(false), kernel_launch_count(0), num_workers_replied(0) {
|
|
|
|
|
|
|
|
desired_resources(order, desired_dpnodes, max_workers, dpfreq);
|
|
desired_resources(order, desired_dpnodes, max_workers, dpfreq);
|
|
|
|
|
|
|
@@ -218,12 +225,23 @@ struct SubproblemProgress : Subproblem {
|
|
|
for (BESet::iterator iter = dpnodes.begin(); iter != dpnodes.end();
|
|
for (BESet::iterator iter = dpnodes.begin(); iter != dpnodes.end();
|
|
|
++iter) {
|
|
++iter) {
|
|
|
bufferevent_write(*iter, stopcmd, 1);
|
|
bufferevent_write(*iter, stopcmd, 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ for (BESet::iterator iter = workers.begin(); iter != workers.end();
|
|
|
|
|
+ ++iter) {
|
|
|
|
|
+ bufferevent_write(*iter, stopcmd, 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void reset(void) {
|
|
|
|
|
+ BESet::iterator iter;
|
|
|
|
|
+
|
|
|
|
|
+ for (BESet::iterator iter = dpnodes.begin(); iter != dpnodes.end();
|
|
|
|
|
+ ++iter) {
|
|
|
ctrlstate.dpnodes.working.erase(*iter);
|
|
ctrlstate.dpnodes.working.erase(*iter);
|
|
|
ctrlstate.dpnodes.idle.insert(*iter);
|
|
ctrlstate.dpnodes.idle.insert(*iter);
|
|
|
}
|
|
}
|
|
|
for (BESet::iterator iter = workers.begin(); iter != workers.end();
|
|
for (BESet::iterator iter = workers.begin(); iter != workers.end();
|
|
|
++iter) {
|
|
++iter) {
|
|
|
- bufferevent_write(*iter, stopcmd, 1);
|
|
|
|
|
ctrlstate.workers.working.erase(*iter);
|
|
ctrlstate.workers.working.erase(*iter);
|
|
|
ctrlstate.workers.idle.insert(*iter);
|
|
ctrlstate.workers.idle.insert(*iter);
|
|
|
}
|
|
}
|
|
@@ -428,7 +446,7 @@ static void computation_complete(void)
|
|
|
ctrlstate.reset();
|
|
ctrlstate.reset();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static unsigned short curproblemid = 0;
|
|
|
|
|
|
|
+static unsigned short cursubproblemid = 0;
|
|
|
|
|
|
|
|
// Take base and target mod f.factor, then decompose that into small
|
|
// Take base and target mod f.factor, then decompose that into small
|
|
|
// subproblems given our knowledge of the factors of phi(f.factor)
|
|
// subproblems given our knowledge of the factors of phi(f.factor)
|
|
@@ -464,8 +482,8 @@ static vector<SubproblemProgress> decomp(const ZZ_p &base, const ZZ_p &target,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- ++curproblemid;
|
|
|
|
|
- ret.push_back(SubproblemProgress(curproblemid, rep(subgroup_base),
|
|
|
|
|
|
|
+ ++cursubproblemid;
|
|
|
|
|
+ ret.push_back(SubproblemProgress(cursubproblemid, rep(subgroup_base),
|
|
|
rep(subgroup_target), f.factor, order));
|
|
rep(subgroup_target), f.factor, order));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -490,8 +508,13 @@ static bool read_modulus(const char *filename)
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static int generate_problem(struct event_base *evbase)
|
|
|
|
|
|
|
+static int generate_problem()
|
|
|
{
|
|
{
|
|
|
|
|
+ // If there's already a problem on the go, don't generate another one
|
|
|
|
|
+ if (ctrlstate.working == true) {
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
while (ctrlstate.worklist[0].second == 0) {
|
|
while (ctrlstate.worklist[0].second == 0) {
|
|
|
ctrlstate.worklist.erase(ctrlstate.worklist.begin());
|
|
ctrlstate.worklist.erase(ctrlstate.worklist.begin());
|
|
|
if (ctrlstate.worklist.size() > 0) {
|
|
if (ctrlstate.worklist.size() > 0) {
|
|
@@ -509,10 +532,6 @@ static int generate_problem(struct event_base *evbase)
|
|
|
return -1;
|
|
return -1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // If there's already a problem on the go, don't generate another one
|
|
|
|
|
- if (ctrlstate.working == true) {
|
|
|
|
|
- return -1;
|
|
|
|
|
- }
|
|
|
|
|
ctrlstate.working = true;
|
|
ctrlstate.working = true;
|
|
|
|
|
|
|
|
int num_subproblems_p = 0;
|
|
int num_subproblems_p = 0;
|
|
@@ -628,14 +647,10 @@ static void controller_dpnode_reader(struct bufferevent *bev, void *ctx)
|
|
|
spp->target ==
|
|
spp->target ==
|
|
|
PowerMod(spp->base, expon, spp->modulus)) {
|
|
PowerMod(spp->base, expon, spp->modulus)) {
|
|
|
// Subproblem solved!
|
|
// Subproblem solved!
|
|
|
|
|
+ ctrlstate.num_unsolved_subproblems--;
|
|
|
spp->solution = expon;
|
|
spp->solution = expon;
|
|
|
spp->solved = true;
|
|
spp->solved = true;
|
|
|
spp->stop();
|
|
spp->stop();
|
|
|
- ctrlstate.num_unsolved_subproblems--;
|
|
|
|
|
- if (ctrlstate.num_unsolved_subproblems == 0) {
|
|
|
|
|
- computation_complete();
|
|
|
|
|
- generate_problem(bufferevent_get_base(bev));
|
|
|
|
|
- }
|
|
|
|
|
schedule();
|
|
schedule();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -652,6 +667,47 @@ static void controller_dpnode_reader(struct bufferevent *bev, void *ctx)
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+static void controller_worker_reader(struct bufferevent *bev, void *ctx)
|
|
|
|
|
+{
|
|
|
|
|
+ struct evbuffer *input = bufferevent_get_input(bev);
|
|
|
|
|
+ ControllerConnInfo *info = (ControllerConnInfo *)ctx;
|
|
|
|
|
+
|
|
|
|
|
+ while(1) {
|
|
|
|
|
+ unsigned int kernel_launch_count = 0;
|
|
|
|
|
+
|
|
|
|
|
+ size_t len = evbuffer_get_length(input);
|
|
|
|
|
+ if (len < sizeof(kernel_launch_count)) return;
|
|
|
|
|
+
|
|
|
|
|
+ bufferevent_read(bev, &kernel_launch_count, sizeof(kernel_launch_count));
|
|
|
|
|
+
|
|
|
|
|
+ // this assumes that workers never leave a subproblem (never crash or get re-assigned)
|
|
|
|
|
+ // otherwise we'll miss out on the kernel_launch_count for some workers
|
|
|
|
|
+
|
|
|
|
|
+ SubproblemProgress *spp = ctrlstate.workers.working[bev];
|
|
|
|
|
+
|
|
|
|
|
+ spp->kernel_launch_count += kernel_launch_count;
|
|
|
|
|
+ spp->num_workers_replied += 1;
|
|
|
|
|
+
|
|
|
|
|
+ if (spp->num_workers_replied == spp->workers.size()) {
|
|
|
|
|
+ cout << "Timing (name, problemid, subproblemid, launches): "
|
|
|
|
|
+ << ctrlstate.worklist[0].first << ", "
|
|
|
|
|
+ << ctrlstate.problemid << ", "
|
|
|
|
|
+ << spp->problemid << ", "
|
|
|
|
|
+ << spp->kernel_launch_count << "\n";
|
|
|
|
|
+ cout.flush();
|
|
|
|
|
+
|
|
|
|
|
+ spp->reset();
|
|
|
|
|
+ schedule();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (ctrlstate.num_unsolved_subproblems == 0 && ctrlstate.workers.working.size() == 0) {
|
|
|
|
|
+ computation_complete();
|
|
|
|
|
+ generate_problem();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static void controller_dpnode_event_cb(struct bufferevent *bev, short events,
|
|
static void controller_dpnode_event_cb(struct bufferevent *bev, short events,
|
|
|
void *ctx)
|
|
void *ctx)
|
|
|
{
|
|
{
|
|
@@ -665,6 +721,7 @@ static void controller_dpnode_event_cb(struct bufferevent *bev, short events,
|
|
|
ctrlstate.dpnodes.working.erase(bev);
|
|
ctrlstate.dpnodes.working.erase(bev);
|
|
|
spp->dpnodes.erase(bev);
|
|
spp->dpnodes.erase(bev);
|
|
|
spp->stop();
|
|
spp->stop();
|
|
|
|
|
+ spp->reset();
|
|
|
} else {
|
|
} else {
|
|
|
ctrlstate.dpnodes.idle.erase(bev);
|
|
ctrlstate.dpnodes.idle.erase(bev);
|
|
|
}
|
|
}
|
|
@@ -727,10 +784,10 @@ static void controller_master_reader(struct bufferevent *bev, void *ctx)
|
|
|
return;
|
|
return;
|
|
|
case 'W':
|
|
case 'W':
|
|
|
ctrlstate.workers.idle.insert(bev);
|
|
ctrlstate.workers.idle.insert(bev);
|
|
|
- // We don't actually read anything from workers
|
|
|
|
|
bufferevent_enable(bev, EV_WRITE);
|
|
bufferevent_enable(bev, EV_WRITE);
|
|
|
- bufferevent_setcb(bev, NULL, NULL,
|
|
|
|
|
|
|
+ bufferevent_setcb(bev, controller_worker_reader, NULL,
|
|
|
controller_worker_event_cb, ctx);
|
|
controller_worker_event_cb, ctx);
|
|
|
|
|
+ controller_worker_reader(bev, ctx);
|
|
|
schedule();
|
|
schedule();
|
|
|
return;
|
|
return;
|
|
|
default:
|
|
default:
|
|
@@ -858,7 +915,7 @@ int controller_main(const Worklist &worklist, unsigned short bindport,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Kick off the first problem to solve
|
|
// Kick off the first problem to solve
|
|
|
- generate_problem(evbase);
|
|
|
|
|
|
|
+ generate_problem();
|
|
|
|
|
|
|
|
event_base_dispatch(evbase);
|
|
event_base_dispatch(evbase);
|
|
|
|
|
|