Commit f24b982f authored by Christopher Alfeld's avatar Christopher Alfeld

Performance mods. Specifically adjusted to scale well with number of

pclasses.  This involved removing the heuristics, which, for the most
part, were not worth the cycles they consumed, and scaled badly.
parent 735cfd70
......@@ -49,7 +49,7 @@ tb_vgraph G;
dictionary<tb_pnode*,node> pnode2node;
dictionary<tb_pnode*,int> pnode2posistion;
pclass_list pclasses;
dictionary<string,pclass_list*> type_table;
pclass_types type_table;
dictionary<string,node> pname2node;
dictionary<string,node> vname2node;
......@@ -272,7 +272,7 @@ int assign()
" violated:" << violated << " trans:" << trans <<
" accepts:" << accepts << endl;
#endif STATS
int newpos;
int newpos=0;
trans++;
iters++;
......@@ -291,93 +291,10 @@ int assign()
unassigned_nodes.insert(n,random());
}
//////////////////////////////////////////////////////////////////////
// Lots of code to calculate the relative weights of the pclasses.
// The weights are stored in the weights dictionary which is indexed
// by pclass* and contains the weight.
//////////////////////////////////////////////////////////////////////
dictionary<tb_pclass*,double> weights;
list_item lit;
dic_item dit;
// find acceptable pclasses
tb_vnode &vn=G[n];
pclass_list *L = type_table.access(vn.type);
forall_items(lit,*L) {
tb_pclass *c = L->inf(lit);
if (c->used != c->size) {
if (c->members.access(vn.type)->front() != NULL) {
weights.insert(c,PCLASS_BASE_WEIGHT);
}
}
}
// adjust weight by neighbors
edge e;
forall_inout_edges(e,n) {
node dst = G.target(e);
if (dst == n) dst = G.source(e);
tb_vnode &vdst = G[dst];
if (vdst.posistion != 0) {
tb_pnode &pdst = PG[pnodes[vdst.posistion]];
tb_pclass *c = pdst.my_class;
dit = weights.lookup(c);
if (dit != nil) {
weights.change_inf(dit,weights.inf(dit)+PCLASS_NEIGHBOR_WEIGHT);
}
}
}
// Adjust classes by utilizaiton
forall_items(lit,pclasses) {
tb_pclass *c = pclasses.inf(lit);
dit = weights.lookup(c);
if (dit != nil) {
if (c->used > 0) {
weights.change_inf(dit,weights.inf(dit)+
PCLASS_UTIL_WEIGHT);
}
}
}
// Adjust classes by features/desires
// We calculate the fd score for all possible classes and normalize
// to 1 and then multiply by PCLASS_FD_WEIGHT
dictionary<tb_pclass*,double> fdscores;
double max_afds=0;
forall_items(dit,weights) {
tb_pclass *c = weights.key(dit);
tb_pnode *p = c->members.access(vn.type)->front();
int v;
double score = fd_score(vn,*p,&v);
fdscores.insert(c,score);
if (fabs(score) > max_afds) max_afds=fabs(score);
}
if (max_afds == 0) max_afds=1;
forall_items(dit,weights) {
tb_pclass *c = weights.key(dit);
double fds = fdscores.access(c);
weights.change_inf(dit,
weights.inf(dit)+PCLASS_FDS_WEIGHT*fds/max_afds);
}
// Calculate total weight.
double total=0;
forall_items(dit,weights) {
total += weights.inf(dit);
}
#ifdef PCLASS_DEBUG_MORE
cerr << "Finding pclass for " << vn.name << endl;
{
dic_item pit;
forall_items(pit,weights) {
tb_pclass *p = weights.key(pit);
cout << " " << p->name << " " << weights.inf(pit) << endl;
}
}
#endif
tt_entry tt = type_table.access(vn.type);
int num_types = tt.first();
pclass_array &acceptable_types = *(tt.second());
////
// We've now calculated the weights and the total weight. We
......@@ -386,9 +303,23 @@ int assign()
////
// Loop will break eventually.
tb_pnode *newpnode;
do {
newpnode = choose_pnode(weights,total,vn.type);
if (newpnode == NULL) {
int i = random()%num_types;
int first = i;
bool found_pclass = true;
for (;;) { // breaks loop in a number of places
i = (i+1)%num_types;
newpnode = acceptable_types[i]->members.access(vn.type)->front();
#ifdef PCLASS_DEBUG
cerr << "Found pclass: " <<
acceptable_types[i]->name << " and node " <<
(newpnode == NULL ? string("NULL") : newpnode->name) << "\n";
#endif
if (newpnode != NULL) {
newpos = pnode2posistion.access(newpnode);
if (add_node(n,newpos) == 0) break; // main exit condition
}
if (i == first) {
// no available nodes
// need to free up a node and recalculate weights.
int pos = 0;
......@@ -403,13 +334,13 @@ int assign()
}
remove_node(ntor);
unassigned_nodes.insert(ntor,random());
found_pclass = false;
break;
}
newpos = pnode2posistion.access(newpnode);
} while (add_node(n,newpos) == 1);
}
// This occurs when no pclass could be found.
if (newpnode == NULL) continue;
if (found_pclass == false) continue;
unassigned_nodes.del(n);
......
......@@ -24,7 +24,7 @@
extern node pnodes[MAX_PNODES];
extern dictionary<tb_pnode*,node> pnode2node;
extern pclass_list pclasses;
extern dictionary<string,pclass_list*> type_table;
extern pclass_types type_table;
typedef two_tuple<node,int> link_info; // dst, bw
......@@ -125,16 +125,34 @@ int generate_pclasses(tb_pgraph &PG) {
}
}
dictionary<string,pclass_list*> pre_type_table;
list_item it;
forall_items(it,pclasses) {
tb_pclass *cur = pclasses[it];
dic_item dit;
forall_items(dit,cur->members) {
if (type_table.lookup(cur->members.key(dit)) == nil) {
type_table.insert(cur->members.key(dit),new pclass_list);
if (pre_type_table.lookup(cur->members.key(dit)) == nil) {
pre_type_table.insert(cur->members.key(dit),new pclass_list);
}
type_table.access(cur->members.key(dit))->push_back(cur);
pre_type_table.access(cur->members.key(dit))->push_back(cur);
}
}
// now we convert the lists in pre_type_table into arrays for
// faster access.
dic_item dit;
forall_items(dit,pre_type_table) {
pclass_list *L = pre_type_table.inf(dit);
pclass_array *A = new pclass_array(L->length());
int i=0;
type_table.insert(pre_type_table.key(dit),tt_entry(L->length(),A));
forall_items(it,*L) {
(*A)[i++] = L->inf(it);
}
delete L;
}
return 0;
}
......@@ -231,10 +249,10 @@ void pclass_debug()
dic_item dit;
forall_items(dit,type_table) {
cout << type_table.key(dit) << ":";
list_item lit;
pclass_list *L = type_table.inf(dit);
forall_items(lit,*L) {
cout << " " << (L->inf(lit))->name;
int n = type_table.inf(dit).first();
pclass_array &A = *(type_table.inf(dit).second());
for (int i = 0; i < n ; ++i) {
cout << " " << A[i];
}
cout << "\n";
}
......
......@@ -53,6 +53,9 @@ public:
};
typedef list<tb_pclass*> pclass_list;
typedef array<tb_pclass*> pclass_array;
typedef two_tuple<int,pclass_array*> tt_entry;
typedef dictionary<string,tt_entry> pclass_types;
/* Constants */
#define PCLASS_BASE_WEIGHT 1
......
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