/*************************************************************************/ /* */ /* Copyright (c) 1994 Stanford University */ /* */ /* All rights reserved. */ /* */ /* Permission is given to use, copy, and modify this software for any */ /* non-commercial purpose as long as this copyright notice is not */ /* removed. All other uses, including redistribution in whole or in */ /* part, are forbidden without prior written permission. */ /* */ /* This software is provided with absolutely no warranty and no */ /* support. */ /* */ /*************************************************************************/ EXTERN_ENV #include "matrix.h" #include #include struct Chunk { long first, last, assign; struct Chunk *next; } *chunks_head = NULL, *chunks_tail = NULL; long tolerance = 20; double domain_ops; double *divide_lo=NULL, *divide_hi; extern double *work_tree; extern long *firstchild, *child; long Divide(struct Chunk *root); void AddInOrder(struct Chunk *t); void Partition(SMatrix M, long parts, long *T, long *assigned_ops, long *domain, long *domains, long *proc_domains) { long i, p, start, minm, maxm, ops, change; long which=0; long *depth; double ave, maxo=0.0, maxd; struct Chunk *t; start = 0; for (i=0; ifirst = start; t->last = i+1; AddInOrder(t); start = i+1; } NumberPartition(parts, assigned_ops, 0); for (;;) { minm = assigned_ops[MinBucket(assigned_ops, parts)]; maxm = assigned_ops[MaxBucket(assigned_ops, parts)]; if (maxm == 0 || (100.0*(maxm - minm)/(double) maxm < tolerance) || (1.0*parts*maxm/work_tree[M.n] < 0.05)) break; t = GetChunk(); change = Divide(t); if (!change) break; NumberPartition(parts, assigned_ops, 0); } NumberPartition(parts, assigned_ops, 1); which = 0; for (i=0; iassign == i) { domains[which++] = t->last-1; } t = t->next; } } proc_domains[parts] = which; /* free chunk list */ while (chunks_head) { t = chunks_head; chunks_head = chunks_head->next; free(t); } depth = (long *) malloc(proc_domains[parts]*sizeof(long)); for (p=0; p maxd) maxd = ops; } ave = domain_ops/(double) parts; printf("Divide for %ld P, %ld domains, ", parts, proc_domains[parts]); printf("%.2f of work static, ", domain_ops/work_tree[M.n]); printf("%.2f eff, (%.2f overall)\n", ave/maxd, work_tree[M.n]/maxo/parts); } void MarkSubtreeAsDomain(long *domain, long root) { long i, first, root_super; extern long *node; first = root; while (firstchild[first] != firstchild[first+1]) first = child[firstchild[first]]; /* all nodes not at root have domain[i] = 1 */ for (i=first; i<=root; i++) domain[i] = 1; /* root super has domain[i] = 2 */ root_super = root; if (node[root_super] < 0) root_super += node[root_super]; for (i=root_super; ilast-1]; old_t = t; t = t->next; if (distribute) { old_t->assign = minm; } } } long Divide(struct Chunk *root) { long i, first, first_in_super; long change = 1; struct Chunk *t2; first_in_super = root->last-1; while (firstchild[first_in_super]+1 == firstchild[first_in_super+1]) { first_in_super--; } first = root->first; for (i=firstchild[first_in_super];ilast = child[i]+1; t2->first = first; AddInOrder(t2); first = t2->last; } free(root); return(change); } long MaxBucket(long *assigned_ops, long parts) { long i, maxm, ind; maxm = assigned_ops[0]; ind = 0; for (i=1; i maxm) { ind = i; maxm = assigned_ops[i]; } return(ind); } long MinBucket(long *assigned_ops, long parts) { long i, minm, ind; minm = assigned_ops[0]; ind = 0; for (i=1; ilast-1]; current = chunks_head; if (!current) { t->next = NULL; chunks_head = t; } else if (work >= work_tree[current->last-1]) { t->next = chunks_head; chunks_head = t; } else { while (current->next && worknext->last-1]) current = current->next; t->next = current->next; current->next = t; } if (t->next == NULL) chunks_tail = t; } struct Chunk *GetChunk() { struct Chunk *t; t = chunks_head; if (t) { chunks_head = t->next; if (t == chunks_tail) chunks_tail = NULL; } return(t); }