Sanchayan Maity
0f4b39775c
During the last commit of splash2 benchmark it seems before committing when we ran "make clean", it effectively undid what the patch at below link did http://www.capsl.udel.edu/splash/Download.html Fix this since without this it is not possible to build the arcane splash2 benchmark.
332 lines
9.2 KiB
C
332 lines
9.2 KiB
C
/*************************************************************************/
|
|
/* */
|
|
/* 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 <stdio.h>
|
|
#include "matrix.h"
|
|
|
|
long *next_in_super, *member_of, *super_parent;
|
|
long *tree_firstchild, *tree_sibling;
|
|
long *tree_original_firstchild, *tree_original_sibling;
|
|
long ops_added;
|
|
double *crit;
|
|
extern long *INVP;
|
|
|
|
long OpsFromSuper(long size, long nz)
|
|
{
|
|
long ops = 0;
|
|
|
|
ops += size*(size+1)*(2*size+1)/6;
|
|
ops += size*size*(nz-size);
|
|
ops += 2*size*(nz-size)*(nz-size+1)/2;
|
|
|
|
return(ops);
|
|
}
|
|
|
|
long CountSupers(long cols, long *node)
|
|
{
|
|
long i, supers;
|
|
|
|
supers = 0;
|
|
for (i=0; i<cols; i+=node[i])
|
|
supers++;
|
|
|
|
return(supers);
|
|
}
|
|
|
|
void Amalgamate2(long join, SMatrix M, long *T, long *nz, long *node, long *domain, long target_size)
|
|
{
|
|
long i, j;
|
|
long counter, supers_before, supers_after;
|
|
double g_ops_before;
|
|
extern double *work_tree;
|
|
extern long *PERM, *firstchild, *child;
|
|
|
|
tree_firstchild = (long *) malloc((M.n+1)*sizeof(long));
|
|
tree_sibling = (long *) malloc((M.n+1)*sizeof(long));
|
|
tree_original_firstchild = (long *) malloc((M.n+1)*sizeof(long));
|
|
tree_original_sibling = (long *) malloc((M.n+1)*sizeof(long));
|
|
next_in_super = (long *) malloc((M.n+1)*sizeof(long));
|
|
member_of = (long *) malloc((M.n+1)*sizeof(long));
|
|
super_parent = (long *) malloc((M.n+1)*sizeof(long));
|
|
|
|
for (i=0; i<=M.n; i++)
|
|
tree_firstchild[i] = -1;
|
|
|
|
/* link supernodes in child, sibling tree */
|
|
for (i=0; i<M.n; i+=node[i]) {
|
|
super_parent[i] = T[i+node[i]-1];
|
|
tree_sibling[i] = tree_firstchild[super_parent[i]];
|
|
tree_firstchild[super_parent[i]] = i;
|
|
}
|
|
super_parent[M.n] = M.n;
|
|
for (i=0; i<=M.n; i++) {
|
|
tree_original_firstchild[i] = tree_firstchild[i];
|
|
tree_original_sibling[i] = tree_sibling[i];
|
|
}
|
|
|
|
/* link nodes within supernodes */
|
|
for (i=0; i<M.n; i+=node[i]) {
|
|
for (j=i; j<i+node[i]; j++) {
|
|
next_in_super[j] = j+1;
|
|
member_of[j] = i;
|
|
}
|
|
next_in_super[i+node[i]-1] = -1;
|
|
}
|
|
member_of[M.n] = M.n;
|
|
|
|
supers_before = CountSupers(M.n, node);
|
|
|
|
ops_added = 0;
|
|
g_ops_before = work_tree[M.n];
|
|
|
|
i = tree_original_firstchild[M.n];
|
|
while (i != -1) {
|
|
ConsiderMerge(join, i, M, nz, node, domain, target_size, 1);
|
|
i = tree_original_sibling[i];
|
|
}
|
|
|
|
counter = M.n;
|
|
ReorderMatrix(M, M.n, node, &counter, PERM);
|
|
InvertPerm(M.n, PERM, INVP);
|
|
|
|
FixNodeNZAndT(M, PERM, node, nz, T);
|
|
|
|
free(tree_firstchild); free(tree_sibling);
|
|
free(tree_original_firstchild); free(tree_original_sibling);
|
|
free(next_in_super); free(member_of); free(super_parent);
|
|
|
|
ParentToChild(T, M.n, firstchild, child);
|
|
ComputeWorkTree(M, nz, work_tree);
|
|
|
|
supers_after = CountSupers(M.n, node);
|
|
|
|
printf("%ld/%ld supers before/after\n", supers_before, supers_after);
|
|
printf("%.0f/%.0f (%.2f) ops before/after amalgamation\n",
|
|
g_ops_before, work_tree[M.n], work_tree[M.n]/(double) g_ops_before);
|
|
if (ops_added != work_tree[M.n]-g_ops_before)
|
|
printf("Model says %ld ops added, really %.0f\n", ops_added,
|
|
work_tree[M.n]-g_ops_before);
|
|
}
|
|
|
|
|
|
void ConsiderMerge(long join, long super, SMatrix M, long *nz, long *node, long *domain, long target_size, long traversal_order)
|
|
{
|
|
long i, parent;
|
|
long ops_before, ops_after, do_merge, do_merge_simple, possible;
|
|
long allow_critical_to_grow;
|
|
double time_before, time_after, dummy, simple_diff;
|
|
double path_grows;
|
|
|
|
super = member_of[super];
|
|
|
|
/* merge until no longer profitable */
|
|
for (;;) {
|
|
|
|
if (super_parent[super] == M.n)
|
|
break;
|
|
|
|
parent = super_parent[super];
|
|
|
|
ops_before = OpsFromSuper(node[super], nz[super]);
|
|
ops_after = OpsFromSuper(node[super], nz[parent]+node[super]);
|
|
|
|
time_before = 0;
|
|
PDIV(node[super], nz[super], &dummy, &dummy, &time_before);
|
|
PMOD(node[super], nz[super]-node[super], nz[super]-node[super],
|
|
&dummy, &dummy, &time_before);
|
|
PADD(nz[super]-node[super], nz[super]-node[super], &dummy, &time_before);
|
|
PDIV(node[parent], nz[parent], &dummy, &dummy, &time_before);
|
|
PMOD(node[parent], nz[parent]-node[parent], nz[parent]-node[parent],
|
|
&dummy, &dummy, &time_before);
|
|
PADD(nz[parent]-node[parent], nz[parent]-node[parent], &dummy,
|
|
&time_before);
|
|
|
|
time_after = 0;
|
|
PDIV(node[super]+node[parent], node[super]+nz[parent],
|
|
&dummy, &dummy, &time_after);
|
|
PMOD(node[super]+node[parent], nz[parent]-node[parent],
|
|
nz[parent]-node[parent], &dummy, &dummy, &time_after);
|
|
PADD(nz[parent]-node[parent], nz[parent]-node[parent], &dummy, &time_after);
|
|
|
|
simple_diff = (ops_after-ops_before) -
|
|
5.0*3*(nz[super]-node[super])*(nz[super]-node[super]+1)/2;
|
|
|
|
possible = (!domain || domain[super] == 0 || domain[parent] != 0);
|
|
|
|
allow_critical_to_grow = 1;
|
|
if ((!domain || domain[super] == 0) && time_before > time_after) {
|
|
if (allow_critical_to_grow)
|
|
path_grows = 0;
|
|
}
|
|
else
|
|
path_grows = 0.0;
|
|
|
|
do_merge = (possible && time_before > time_after && path_grows == 0.0);
|
|
do_merge_simple = (possible && simple_diff < 0);
|
|
|
|
if (do_merge) {
|
|
|
|
JoinTwoSupers2(nz, node, super, parent);
|
|
ops_added += (ops_after-ops_before);
|
|
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
i = tree_original_firstchild[super];
|
|
while (i != -1) {
|
|
ConsiderMerge(join, i, M, nz, node, domain, target_size, traversal_order);
|
|
i = tree_original_sibling[i];
|
|
}
|
|
}
|
|
|
|
void JoinTwoSupers2(long *nz, long *node, long child, long parent)
|
|
{
|
|
long i, child_last, member, grandparent;
|
|
|
|
/* record new memberships */
|
|
member = parent;
|
|
while (member != -1) {
|
|
member_of[member] = child;
|
|
member = next_in_super[member];
|
|
}
|
|
|
|
/* find last member of child */
|
|
child_last = child;
|
|
while (next_in_super[child_last] != -1)
|
|
child_last = next_in_super[child_last];
|
|
|
|
/* link in nodes in parent */
|
|
next_in_super[child_last] = parent;
|
|
|
|
/* adjust sizes */
|
|
nz[child] = nz[parent]+node[child];
|
|
node[child] += node[parent];
|
|
|
|
/* adjust child parent */
|
|
super_parent[child] = super_parent[parent];
|
|
|
|
/* children of 'parent' become children of 'child' */
|
|
while (tree_firstchild[parent] != -1) {
|
|
i = tree_firstchild[parent];
|
|
tree_firstchild[parent] = tree_sibling[i];
|
|
if (member_of[i] != child) {
|
|
super_parent[member_of[i]] = child;
|
|
tree_sibling[i] = tree_firstchild[child];
|
|
tree_firstchild[child] = i;
|
|
}
|
|
}
|
|
|
|
/* siblings of 'parent' become siblings of 'child' */
|
|
grandparent = super_parent[parent];
|
|
tree_sibling[child] = tree_sibling[parent];
|
|
i = tree_firstchild[grandparent];
|
|
if (i == parent)
|
|
tree_firstchild[grandparent] = child;
|
|
else {
|
|
while (tree_sibling[i] != parent)
|
|
i = tree_sibling[i];
|
|
tree_sibling[i] = child;
|
|
}
|
|
}
|
|
|
|
|
|
void ReorderMatrix(SMatrix M, long super, long *node, long *counter, long *PERM)
|
|
{
|
|
long child, member, which_member;
|
|
|
|
if (super != M.n) {
|
|
super = member_of[super];
|
|
|
|
member = super; which_member = 0;
|
|
while (member != -1) {
|
|
PERM[*counter-node[super]+which_member] = member;
|
|
member = next_in_super[member];
|
|
which_member++;
|
|
}
|
|
|
|
*counter -= node[super];
|
|
}
|
|
|
|
child = tree_firstchild[super];
|
|
while (child != -1) {
|
|
ReorderMatrix(M, child, node, counter, PERM);
|
|
child = tree_sibling[child];
|
|
}
|
|
}
|
|
|
|
|
|
void FixNodeNZAndT(SMatrix M, long *PERM, long *node, long *nz, long *T)
|
|
{
|
|
long super, j;
|
|
long *tmp;
|
|
|
|
tmp = (long *) malloc(M.n*sizeof(long));
|
|
|
|
for (j=0; j<M.n; j++)
|
|
tmp[j] = node[j];
|
|
for (j=0; j<M.n; j++)
|
|
node[j] = tmp[PERM[j]];
|
|
for (super=0; super<M.n; super+=node[super])
|
|
for (j=super+1; j<super+node[super]; j++)
|
|
node[j] = super-j;
|
|
|
|
for (j=0; j<M.n; j++)
|
|
tmp[j] = nz[j];
|
|
for (super=0; super<M.n; super+=node[super]) {
|
|
nz[super] = tmp[PERM[super]];
|
|
for (j=super+1; j<super+node[super]; j++)
|
|
nz[j] = nz[super]+super-j;
|
|
}
|
|
|
|
for (super=0; super<M.n; super+=node[super]) {
|
|
for (j=super; j<super+node[super]; j++)
|
|
T[j] = j+1;
|
|
T[super+node[super]-1] = INVP[super_parent[PERM[super]]];
|
|
}
|
|
|
|
free(tmp);
|
|
}
|
|
|
|
void InvertPerm(long n, long *PERM, long *INVP)
|
|
{
|
|
long i;
|
|
|
|
for (i=0; i<=n; i++)
|
|
INVP[i] = -1;
|
|
|
|
for (i=0; i<=n; i++)
|
|
INVP[PERM[i]] = i;
|
|
|
|
for (i=0; i<=n; i++)
|
|
if (INVP[i] == -1)
|
|
printf("Not a valid permutation\n");
|
|
}
|
|
|
|
|
|
double PathLength(long cols, long rows, long target_panel_size)
|
|
{
|
|
double path_length;
|
|
|
|
path_length = 3*(cols*rows-cols*(cols-1)/2);
|
|
path_length *= target_panel_size;
|
|
|
|
return(path_length);
|
|
}
|
|
|