Commit c7e2d29e authored by Robert Ricci's avatar Robert Ricci

Fix dynamic pclasses, and make them the default for virtual nodes

again.

One of the fixes changes the way in which we iterate through pclasses
in find_pnode(). We used to treat the vector like a ring buffer, and
start (randomly) someplace in the middle. This turns out to give some
bad statistical properties when doing dynamic pclasses, since long
chains of disabled pclasses will cause some pclasses to be selected
more often. My old hack of just hopping around randomly in the
disabled-pclass case was bad, because it's hard to tell when you've
actually tried all the pclasses - so, we were getting false negatives
where it was looking like there was no place available where we could
map a vnode, which turned out to have worse effects than I had
thought.

So, now, we make a list of all the indices and randomize the order,
then just iterate through that list.

We also now count the number of pclasses that are enabled at every
temperature step, and adjust the neighborhood size to remove them.
This makes dynamic pclasses quite a bit faster - it cuts the time
by 30% - 50% for my test case.

Cleaned up find_pnode() by removing some #ifdef's that we don't use,
and probably will never want to again - this makes the function almost
readable!
parent d1a24c04
...@@ -122,127 +122,65 @@ tb_pnode *find_pnode(tb_vnode *vn) ...@@ -122,127 +122,65 @@ tb_pnode *find_pnode(tb_vnode *vn)
pclass_vector *acceptable_types = tt.second; pclass_vector *acceptable_types = tt.second;
tb_pnode *newpnode = NULL; tb_pnode *newpnode = NULL;
//cerr << "Node is " << vn->name << " First = " << first << endl;
/* // Randomize the order in which we go through the list of acceptable pclasses
int enabled_pclasses = 0; // We do this by making a randomly-ordered list of indicies into the
// acceptable_types vector
vector<int> traversal_order(num_types);
for (int i = 0; i < num_types; i++) { for (int i = 0; i < num_types; i++) {
if ((*acceptable_types)[i]->disabled) { traversal_order[i] = i;
continue; }
} for (int i = 0; i < num_types; i++) {
enabled_pclasses++; int i1 = std::rand() % num_types;
int i2 = std::rand() % num_types;
int tmp = traversal_order[i1];
traversal_order[i1] = traversal_order[i2];
traversal_order[i2] = tmp;
} }
cout << "Looking for a pnode for " << vn->name << " - there are " <<
enabled_pclasses << " to choose from (" << num_types << " total)" << endl;
assert(num_types == enabled_pclasses);
*/
int i = std::random()%num_types;
int first = i;
bool first_time_through = true;
for (;;) {
// Stopping condition - stop if we're back to the first one, and this isn't
// our first time through the loop
if (i == first) {
if (first_time_through) {
first_time_through = false;
} else {
// Couldn't find a sutable node
return NULL;
}
}
i = (i+1)%num_types; for (int i = 0; i < num_types; i++) {
// Skip pclasses that have been disabled int index = traversal_order[i];
if ((*acceptable_types)[i]->disabled) { tb_pclass *pclass = (*acceptable_types)[index];
i = std::rand()%num_types;
continue;
}
#ifdef PCLASS_SIZE_BALANCE // Skip pclasses that have been disabled
int acceptchance = 1000 * (*acceptable_types)[i]->size * 1.0 / if (pclass->disabled) {
npnodes; continue;
if ((std::rand() % 1000) < acceptchance) {
continue;
} }
#endif
// For load balancing only
REDO_SEARCH:
tb_pnode* firstmatch = NULL;
#ifndef FIND_PNODE_SEARCH #ifndef FIND_PNODE_SEARCH
// If not searching for the pnode, just grab the front one // If not searching for the pnode, just grab the front one
newpnode = (*acceptable_types)[i]->members[vn->type]->front(); newpnode = pclass->members[vn->type]->front();
#else #else
#ifdef PER_VNODE_TT #ifdef PER_VNODE_TT
// If using PER_VNODE_TT and vclasses, it's possible that there are // If using PER_VNODE_TT and vclasses, it's possible that there are
// some pclasses in this node's type table that can't be used right now, // some pclasses in this node's type table that can't be used right now,
// becuase they contain entires that don't contain the vnodes _current_ // becuase they contain entires that don't contain the vnodes _current_
// type // type
if ((*acceptable_types)[i]->members.find(vn->type) == if (pclass->members.find(vn->type) == pclass->members.end()) {
(*acceptable_types)[i]->members.end()) {
continue; continue;
} }
#endif #endif
list<tb_pnode*>::iterator it = (*acceptable_types)[i]->members[vn->type]->L.begin(); list<tb_pnode*>::iterator it = pclass->members[vn->type]->L.begin();
#ifdef LOAD_BALANCE while (it != pclass->members[vn->type]->L.end()) {
int skip = std::rand() % (*acceptable_types)[i]->members[vn->type]->L.size();
// Skip the begging of the list
for (int j = 0; j < skip; j++) {
it++;
}
#endif // LOAD_BALANCE
while (it != (*acceptable_types)[i]->members[vn->type]->L.end()) {
#ifdef LOAD_BALANCE
if ((*it)->typed) {
if ((*it)->current_type.compare(vn->type)) {
it++;
} else {
if (firstmatch == NULL) {
firstmatch = *it;
}
double acceptchance = 1 - (*it)->current_load * 1.0
/ (*it)->max_load;
int p = 1000 * acceptchance;
if ((std::random() % 1000) < (1000 * acceptchance)) {
break;
} else {
it++;
}
}
} else {
break;
}
#else // LOAD_BALANCE
if (pnode_is_match(vn,*it)) { if (pnode_is_match(vn,*it)) {
break; break;
} else { } else {
it++; it++;
} }
#endif // LOAD_BALANCE
} }
if (it == (*acceptable_types)[i]->members[vn->type]->L.end()) { if (it == pclass->members[vn->type]->L.end()) {
#ifdef LOAD_BALANCE
if (firstmatch) {
//newpnode = firstmatch;
goto REDO_SEARCH;
} else {
newpnode = NULL;
}
#else // LOAD_BALANCE
newpnode = NULL; newpnode = NULL;
#endif // LOAD_BALANCE
} else { } else {
newpnode = *it; newpnode = *it;
} }
#endif // FIND_PNODE_SEARCH #endif // FIND_PNODE_SEARCH
#ifdef PCLASS_DEBUG #ifdef PCLASS_DEBUG
cerr << "Found pclass: " << cerr << "Found pclass: " <<
(*acceptable_types)[i]->name << " and node " << pclass->name << " and node " <<
(newpnode == NULL ? "NULL" : newpnode->name) << "\n"; (newpnode == NULL ? "NULL" : newpnode->name) << "\n";
#endif #endif
if (newpnode != NULL) { if (newpnode != NULL) {
...@@ -250,6 +188,9 @@ REDO_SEARCH: ...@@ -250,6 +188,9 @@ REDO_SEARCH:
return newpnode; return newpnode;
} }
} }
// Nope, didn't find one
return NULL;
} }
...@@ -500,13 +441,19 @@ void anneal(bool scoring_selftest, double scale_neighborhood, ...@@ -500,13 +441,19 @@ void anneal(bool scoring_selftest, double scale_neighborhood,
scores[0] = bestscore; scores[0] = bestscore;
#endif #endif
// Adjust the number of transitions we're going to do based on the number
// of pclasses that are actually 'in play'
int transitions = neighborsize *
(count_enabled_pclasses() *1.0 / pclasses.size());
assert(transitions <= neighborsize);
if (melting) { if (melting) {
cout << "Doing melting run" << endl; cout << "Doing melting run" << endl;
} }
while ((melting && (trans < melt_trans)) while ((melting && (trans < melt_trans))
#ifdef NEIGHBOR_LENGTH #ifdef NEIGHBOR_LENGTH
|| (trans < neighborsize)) { || (trans < transitions)) {
#else #else
|| (!melting && (trans < mintrans && accepts < naccepts))) { || (!melting && (trans < mintrans && accepts < naccepts))) {
#endif #endif
......
...@@ -440,3 +440,16 @@ void pclass_debug() ...@@ -440,3 +440,16 @@ void pclass_debug()
} }
} }
/* Count how many enabled, non-empty, pclasses there currently are. */
int count_enabled_pclasses()
{
pclass_list::iterator it;
int count = 0;
for (it=pclasses.begin();it != pclasses.end();++it) {
if ((*it)->disabled) { continue; }
// XXX - skip empty pclasses
count++;
}
return count;
}
...@@ -134,4 +134,6 @@ int pclass_unset(tb_pnode *p); ...@@ -134,4 +134,6 @@ int pclass_unset(tb_pnode *p);
void pclass_debug(); void pclass_debug();
int count_enabled_pclasses();
#endif #endif
...@@ -847,7 +847,7 @@ int add_node(vvertex vv,pvertex pv, bool deterministic, bool is_fixed) ...@@ -847,7 +847,7 @@ int add_node(vvertex vv,pvertex pv, bool deterministic, bool is_fixed)
typedef vector<tb_link_info> resolution_vector; typedef vector<tb_link_info> resolution_vector;
typedef vector<pvertex_list> switchlist_vector; typedef vector<pvertex_list> switchlist_vector;
resolution_vector resolutions(10); resolution_vector resolutions(3);
int resolution_index = 0; int resolution_index = 0;
float total_weight = 0; float total_weight = 0;
......
...@@ -529,7 +529,7 @@ sub RunAssign ($) ...@@ -529,7 +529,7 @@ sub RunAssign ($)
TBDebugTimeStamp("assign started"); TBDebugTimeStamp("assign started");
# Run assign # Run assign
my $cmdargs = "$ptopfile $topfile"; my $cmdargs = "$ptopfile $topfile";
$cmdargs = "-Pop $cmdargs" $cmdargs = "-Pod $cmdargs"
if ($virtcount); if ($virtcount);
print "assign $cmdargs\n"; print "assign $cmdargs\n";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment