Example #1
0
        /* Combine goals of collections of processors for next division. */
        public static void merge_goals(double[] goal,           /* desired set sizes */
                                       double[] merged_goal,    /* sizes of sets at this partition level */
                                       set_info *set_info,      /* information about all sets */
                                       int[] subsets,           /* set numbers of processors to merge */
                                       int nsets,               /* number of sets created by this division */
                                       int ndims_tot,           /* total number of dimensions in the hypercube */
                                       bool cube_or_mesh,       /* 0=> hypercube, d=> d-dimensional mesh */
                                       int[] mesh_dims /*[3]*/, /* shape of mesh */
                                       double vwgt_sum          /* actual sum of vertex weights */
                                       )
        {
            set_info *set;        /* set of processors still clumped together */
            double    total_goal; /* total of desired goals */
            int       index;      /* x, y or z location of a processor */
            int       i, x, y, z; /* loop counters */

            total_goal = 0;
            for (i = 0; i < nsets; i++)
            {
                set            = &(set_info[subsets[i]]);
                merged_goal[i] = 0;

                if (cube_or_mesh)
                {
                    /* Mesh architecture. */
                    for (x = set->low[0]; x < set->low[0] + set->span[0]; x++)
                    {
                        for (y = set->low[1]; y < set->low[1] + set->span[1]; y++)
                        {
                            for (z = set->low[2]; z < set->low[2] + set->span[2]; z++)
                            {
                                index           = z * mesh_dims[0] * mesh_dims[1] + y * mesh_dims[0] + x;
                                merged_goal[i] += goal[index];
                            }
                        }
                    }
                }

                else if (!cube_or_mesh)
                {
                    /* Hypercube architecture. */
                    x = 1 << (ndims_tot - set->ndims);
                    y = 1 << ndims_tot;
                    for (z = set->setnum; z < y; z += x)
                    {
                        merged_goal[i] += goal[z];
                    }
                }

                total_goal += merged_goal[i];
            }

            /* Now scale goals to reflect actual weight of vertices available. */
            for (i = 0; i < nsets; i++)
            {
                merged_goal[i] = (merged_goal[i] / total_goal) * vwgt_sum;
            }
        }
Example #2
0
/* Compute the average distance between two subsets of mesh processors. */
        private static double avg_dist_mesh(set_info *set1,  /* data about all first set */
                                            set_info *set2,  /* data about all second set */
                                            int architecture /* dimension of mesh */
                                            )
        {
            double val; /* distance returned */
            int    i;   /* loop counter */

            val = 0;

            for (i = 0; i < architecture; i++)
            {
                val += avg_dist_interval(set1->low[i], set1->span[i], set2->low[i], set2->span[i]);
            }

            return(val);
        }
Example #3
0
        static void avg_dists_mesh(int architecture,          /* dimensions of mesh */
                                   set_info *set_info,        /* data about all the sets */
                                   int nsets,                 /* number of subsets being created */
                                   int set_max,               /* largest set created so far */
                                   int []            subsets, /* subsets being created */
                                   float *[] dists            /*[MAXSETS]*/ /* distances from my subsets to other sets */
                                   )
        {
            float *dist0; /* first of dists vectors */
            float *dist;  /* one of dists vectors */
            double val;   /* distance from subset to set */
            double sep;   /* distance between two subsets */
            int    set;   /* loops through all other sets */
            int    i;     /* loop counter */

            /* First compute distances for subset 0. */
            dist0 = dists[0];

            for (set = 0; set < set_max; set++)
            {
                if (set_info[set].span[0] >= 0)
                {
                    val        = avg_dist_mesh(&set_info[subsets[0]], &set_info[set], architecture);
                    dist0[set] = (float)val;
                }
            }

            /* Now compute all distances relative to subset 0. */
            for (i = 1; i < nsets; i++)
            {
                dist = dists[i];
                sep  = avg_dist_mesh(&set_info[subsets[i]], &set_info[subsets[0]], architecture);

                for (set = 0; set < set_max; set++)
                {
                    if (set_info[set].span[0] >= 0)
                    {
                        val = avg_dist_mesh(&set_info[subsets[i]], &set_info[set], architecture);
                        /* Note: this is net preference for set over 0. */
                        dist[set] = (float)((dist0[set] - val) / sep);
                    }
                }
            }
        }
Example #4
0
        private static bool define_subcubes(int nsets_real,                      /* actual number of sets being created */
                                            int ndims_tot,                       /* total hypercube dimensions */
                                            int ndims,                           /* # dimension in this cut */
                                            set_info *set,                       /* data for set being divided */
                                            set_info *set_info,                  /* data for all sets */
                                            int []            subsets,           /* subsets to be created */
                                            bool inert,                          /* using inertial method? */
                                            int *pstriping,                      /* cut in single direction? */
                                            int[][]              hop_mtx_special /*[MAXSETS][MAXSETS]*/ /* nonstandard hop values */
                                            )
        {
            bool hop_flag; /* use special hop matrix? */
            int  nsets;    /* number of sets being created */
            int  setnum;   /* global number of subset */
            int  bits;     /* number of bits in which two sets differ */
            int  i, j, k;  /* loop counters */

            nsets    = 1 << ndims;
            hop_flag = false;

            for (k = nsets - 1; k >= 0; k--) /* Backwards to not overwrite current set. */

            {
                setnum = set->setnum | (k << (ndims_tot - set->ndims));
                set_info[setnum].ndims = set->ndims - ndims;
                subsets[k]             = setnum;
            }

            *pstriping = (inert && nsets_real > 2) ? 1 : 0;

            if (*pstriping != 0) /* Gray code for better mapping. */
            {
                for (k = 0; k < nsets; k++)
                {
                    subsets[k] = gray(subsets[k]);
                }

                if (KL_METRIC == KernighanLinMetric.Hops)
                {
                    hop_flag = true;
                    for (i = 0; i < nsets; i++)
                    {
                        hop_mtx_special[i][i] = 0;
                        for (j = 0; j < i; j++)
                        {
                            hop_mtx_special[i][j] = 0;
                            bits = (subsets[i]) ^ (subsets[j]);
                            while (bits != 0)
                            {
                                if ((bits & 1) != 0)
                                {
                                    ++hop_mtx_special[i][j];
                                }
                                bits >>= 1;
                            }
                            hop_mtx_special[j][i] = hop_mtx_special[i][j];
                        }
                    }
                }
            }

            return(hop_flag);
        }
Example #5
0
        public static bool divide_procs(int architecture,                 /* 0 => hypercube, d => d-dimensional mesh */
                                        int ndims,                        /* normal dimension of each cut */
                                        int ndims_tot,                    /* total number of hypercube dimensions */
                                        set_info *info_set,               /* data for all sets */
                                        set_info *divide_set,             /* data for set being divided */
                                        int[]             subsets,        /* subsets to be created */
                                        bool inert,                       /* using inertial method? */
                                        int *pndims_real,                 /* actual ndims for this cut */
                                        int *pnsets_real,                 /* # sets created by this cut */
                                        int *pstriping,                   /* cut in single direction? */
                                        int []            cut_dirs,       /* direction of each cut if mesh */
                                        int []            mesh_dims,      /* size of full mesh */
                                        int[][]              hops_special /*[][MAXSETS]*/ /* hop matrix for nonstandard cases */
                                        )
        {
            int  nsets_real = -1;   /* number of sets to divide into */
            int  ndims_real = -1;   /* number of eigenvectors to use */
            int  striping   = -1;   /* cut in single direction? */
            bool flag       = true; /* unusual partition => use special hops */
            int  ndim_poss;         /* largest dimensionality possible */
            int  idims;             /* true dimensionality of subgrid */
            int  i;                 /* loop counter */

            if (architecture > 0)   /* Mesh, complicated case. */
            {
                nsets_real = divide_set->span[0] * divide_set->span[1] * divide_set->span[2];
                nsets_real = Math.Min(1 << ndims, nsets_real);
                ndims_real = ndims;
                while (1 << ndims_real > nsets_real)
                {
                    --ndims_real;
                }

                ndim_poss = 0;
                idims     = 0;
                for (i = 0; i < 3; i++)
                {
                    if (divide_set->span[i] >= 2)
                    {
                        ndim_poss++;
                        idims++;
                    }
                    if (divide_set->span[i] >= 4)
                    {
                        ndim_poss++;
                    }
                    if (divide_set->span[i] >= 8)
                    {
                        ndim_poss++;
                    }
                }
                ndims_real = Math.Min(ndim_poss, ndims_real);

                if (idims > 1)
                {
                    nsets_real = 1 << ndims_real;
                }

                flag = define_submeshes(nsets_real, architecture, mesh_dims, divide_set, info_set, subsets,
                                        inert, &striping, cut_dirs, hops_special);
                if (striping != 0)
                {
                    ndims_real = 1;
                }
            }

            else if (architecture == 0) /* Hypercube, easy case. */
            {
                ndims_real = Math.Min(ndims, divide_set->ndims);
                nsets_real = 1 << ndims_real;

                flag = define_subcubes(nsets_real, ndims_tot, ndims_real, divide_set, info_set, subsets, inert,
                                       &striping, hops_special);

                if (striping != 0)
                {
                    ndims_real = 1;
                }
            }

            *pndims_real = ndims_real;
            *pnsets_real = nsets_real;
            *pstriping   = striping;

            return(flag);
        }
Example #6
0
        /* Figure out how to divide mesh into pieces.  Return true if nonstandard. */
        private static bool define_submeshes(int nsets,                           /* number of subsets in this partition */
                                             int cube_or_mesh,                    /* 0=> hypercube, d=> d-dimensional mesh */
                                             int []            mesh_dims,         /* shape of mesh */
                                             set_info *set,                       /* set data for set I'm partitioning */
                                             set_info *set_info,                  /* set data for all sets */
                                             int []            subsets,           /* subsets being created by partition */
                                             bool inert,                          /* using inertial method? */
                                             int *striping,                       /* should I partition with parallel cuts? */
                                             int []            dir,               /* directions of each cut */
                                             int[][]              hop_mtx_special /*[MAXSETS][MAXSETS]*/ /* hops values if unusual */
                                             )
        {
            int ndims;                 /* dimension of cut */

            int[] dims = new int[3];   /* local copy of mesh_dims to modify */
            int   maxdim;              /* longest dimension of the mesh */
            int   mindim;              /* intest dimension of mesh */

            int[] start  = new int[3]; /* start in each index of submesh */
            int[] width  = new int[3]; /* length in each index of submesh */
            int[] nbits  = new int[3]; /* values for computing hops */
            int[] coords = new int[3]; /* location of set in logical grid */
            int[] mask   = new int[3]; /* values for computing hops */
            int   setnum;              /* number of created set */
            bool  flag;                /* return condition */
            bool  snaking;             /* is single stripe snaking through grid? */
            bool  reverse;             /* should I reverse direction for embedding? */
            int   i, j, k;             /* loop counters */

            dims[0] = set->span[0];
            dims[1] = set->span[1];
            dims[2] = set->span[2];

            ndims = 1;
            while ((2 << ndims) <= nsets)
            {
                ndims++;
            }

            /* Find the intest and longest directions in mesh. */
            maxdim = -1;
            mindim = dims[0];
            dir[1] = dir[2] = 0;
            for (i = 0; i < cube_or_mesh; i++)
            {
                if (dims[i] > maxdim)
                {
                    maxdim = dims[i];
                    dir[0] = i;
                }
                if (dims[i] < mindim)
                {
                    mindim = dims[i];
                }
            }

            /* Decide whether or not to force striping. */
            i = 0;
            for (j = 0; j < cube_or_mesh; j++)
            {
                if (set->span[j] > 1)
                {
                    i++;
                }
            }

            *striping = (i <= 1 || nsets == 3 ||
                         (maxdim > nsets && (maxdim > .6 * nsets * mindim || (inert && nsets > 2)))) ? 1 : 0;

            snaking = !(*striping != 0) && inert && nsets > 2;

            if (!(*striping != 0))
            {
                if (nsets >= 4) /* Find direction of second & third cuts. */
                {
                    dims[dir[0]] /= 2;
                    maxdim        = -1;
                    for (i = 0; i < cube_or_mesh; i++)
                    {
                        if (dims[i] > maxdim)
                        {
                            maxdim = dims[i];
                            dir[1] = i;
                        }
                    }
                }

                if (nsets == 8) /* Find a third direction. */
                {
                    dims[dir[1]] /= 2;
                    maxdim        = -1;
                    for (i = 0; i < cube_or_mesh; i++)
                    {
                        if (dims[i] > maxdim)
                        {
                            maxdim = dims[i];
                            dir[2] = i;
                        }
                    }
                }
                nbits[0] = nbits[1] = nbits[2] = 0;
                for (i = 0; i < ndims; i++)
                {
                    ++nbits[dir[i]];
                }
                for (i = 0; i < 3; i++)
                {
                    mask[i] = (1 << nbits[i]) - 1;
                }
                mask[1] <<= nbits[0];
                mask[2] <<= nbits[0] + nbits[1];
            }

            for (k = nsets - 1; k >= 0; k--) /* Backwards to not overwrite current set. */

            {
                for (i = 0; i < 3; i++)
                {
                    start[i] = 0;
                    width[i] = dims[i] = set->span[i];
                }

                if ((*striping) != 0) /* Use longest direction for all cuts. */
                {
                    start[dir[0]] = (k * dims[dir[0]] + nsets - 1) / nsets;
                    width[dir[0]] = ((k + 1) * dims[dir[0]] + nsets - 1) / nsets - start[dir[0]];
                }

                else /* Figure out partition based on cut directions. */
                {
                    coords[0] = k & mask[0];
                    coords[1] = (k & mask[1]) >> nbits[0];
                    coords[2] = (k & mask[2]) >> (nbits[0] + nbits[1]);
                    if (snaking)
                    {
                        reverse = (coords[1] & 1) != 0;
                        if (reverse)
                        {
                            coords[0] = mask[0] - coords[0];
                        }
                        reverse = (coords[2] & 1) != 0;
                        if (reverse)
                        {
                            coords[1] = (mask[1] >> nbits[0]) - coords[1];
                        }
                    }

                    for (j = 0; j < ndims; j++)
                    {
                        --nbits[dir[j]];
                        if ((coords[dir[j]] & (1 << nbits[dir[j]])) != 0)
                        {
                            /* Right side of partition. */
                            start[dir[j]] += (width[dir[j]] + 1) / 2;
                            width[dir[j]] /= 2;
                        }
                        else /* Left side of partition */
                        {
                            width[dir[j]] = (width[dir[j]] + 1) / 2;
                        }
                    }

                    /* Now restore nbits values. */
                    nbits[0] = nbits[1] = nbits[2] = 0;
                    for (i = 0; i < ndims; i++)
                    {
                        ++nbits[dir[i]];
                    }
                }

                for (i = 0; i < 3; i++)
                {
                    start[i] += set->low[i];
                }

                setnum = (start[2] * mesh_dims[1] + start[1]) * mesh_dims[0] + start[0];

                for (i = 0; i < 3; i++)
                {
                    set_info[setnum].low[i]  = start[i];
                    set_info[setnum].span[i] = width[i];
                }
                subsets[k] = setnum;
            }

            /* Check to see if hop_mtx is nonstandard. */
            flag = false;
            if (KL_METRIC == KernighanLinMetric.Hops)
            {
                if ((*striping) != 0)
                {
                    flag = true;
                    for (i = 0; i < nsets; i++)
                    {
                        for (j = 0; j < nsets; j++)
                        {
                            hop_mtx_special[i][j] = Math.Abs(i - j);
                        }
                    }
                }

                else if (nsets == 4)
                {
                    if (dir[0] == dir[1] || snaking)
                    {
                        flag = true;
                        for (i = 0; i < nsets; i++)
                        {
                            start[0] = i & mask[0];
                            start[1] = (i & mask[1]) >> nbits[0];
                            if (snaking)
                            {
                                reverse = (start[1] & 1) != 0;
                                if (reverse)
                                {
                                    start[0] = mask[0] - start[0];
                                }
                            }
                            for (j = i; j < nsets; j++)
                            {
                                coords[0] = j & mask[0];
                                coords[1] = (j & mask[1]) >> nbits[0];
                                if (snaking)
                                {
                                    reverse = (coords[1] & 1) != 0;
                                    if (reverse)
                                    {
                                        coords[0] = mask[0] - coords[0];
                                    }
                                }

                                hop_mtx_special[i][j] = hop_mtx_special[j][i] =
                                    Math.Abs(start[0] - coords[0]) + Math.Abs(start[1] - coords[1]);
                            }
                        }
                    }
                }
                else if (nsets == 8)
                {
                    if (dir[0] == dir[1] || dir[0] == dir[2] || dir[1] == dir[2] || snaking)
                    {
                        flag = true;
                        for (i = 0; i < nsets; i++)
                        {
                            start[0] = i & mask[0];
                            start[1] = (i & mask[1]) >> nbits[0];
                            start[2] = (i & mask[2]) >> (nbits[0] + nbits[1]);
                            if (snaking)
                            {
                                reverse = (start[1] & 1) != 0;
                                if (reverse)
                                {
                                    start[0] = mask[0] - start[0];
                                }
                                reverse = (start[2] & 1) != 0;
                                if (reverse)
                                {
                                    start[1] = (mask[1] >> nbits[0]) - start[1];
                                }
                            }
                            for (j = i; j < nsets; j++)
                            {
                                coords[0] = j & mask[0];
                                coords[1] = (j & mask[1]) >> nbits[0];
                                coords[2] = (j & mask[2]) >> (nbits[0] + nbits[1]);
                                if (snaking)
                                {
                                    reverse = (coords[1] & 1) != 0;
                                    if (reverse)
                                    {
                                        coords[0] = mask[0] - coords[0];
                                    }
                                    reverse = (coords[2] & 1) != 0;
                                    if (reverse)
                                    {
                                        coords[1] = (mask[1] >> nbits[0]) - coords[1];
                                    }
                                }

                                hop_mtx_special[i][j] = hop_mtx_special[j][i] =
                                    Math.Abs(start[0] - coords[0]) + Math.Abs(start[1] - coords[1]) + Math.Abs(start[2] - coords[2]);
                            }
                        }
                    }
                }
            }

            *striping = ((*striping != 0) && snaking) ? 1 : 0;

            return(flag);
        }
Example #7
0
        static void avg_dists_cube(int ndims_tot,             /* total number of hypercube dimensions */
                                   int ndims,                 /* number of dimensions created this step */
                                   set_info *set_info,        /* data about all the sets */
                                   int nsets,                 /* number of subsets being created */
                                   int set_max,               /* largest set created so far */
                                   int []            subsets, /* subsets being created */
                                   float *[] dists            /*[MAXSETS]*/       /* distances from my subsets to other sets */
                                   )
        {
            float *dist0;      /* first of dists vectors */
            float *dist;       /* one of dists vectors */
            int    ndims_old;  /* hypercube dimensions not relevant */
            int    ndims_left; /* hypercube dimensions left to do */
            int    myset;      /* subset being analyzed */
            int    start;      /* bit difference between two sets */
            int    val;        /* number of differing bits */
            int    set;        /* loops through all other sets */
            int    i;          /* loop counter */

            /* First compute distances for subset 0. */
            myset      = subsets[0];
            dist0      = dists[0];
            ndims_left = set_info[myset].ndims;
            ndims_old  = ndims_tot - ndims_left - ndims;
            for (set = 0; set < set_max; set++)
            {
                if (set_info[set].ndims >= 0)
                {
                    val = 0;
                    if (ndims_left == set_info[set].ndims)
                    {
                        start = (myset ^ set) >> ndims_old;
                        while (start != 0)
                        {
                            if ((start & 1) != 0)
                            {
                                val++;
                            }
                            start >>= 1;
                        }
                    }
                    dist0[set] = val;
                }
            }

            /* Now compute all distances relative to subset 0. */
            for (i = 1; i < nsets; i++)
            {
                myset = subsets[i];
                dist  = dists[i];

                for (set = 0; set < set_max; set++)
                {
                    if (set_info[set].ndims >= 0)
                    {
                        val = 0;
                        if (ndims_left == set_info[set].ndims)
                        {
                            start = (myset ^ set) >> ndims_old;
                            while (start != 0)
                            {
                                if ((start & 1) != 0)
                                {
                                    val++;
                                }
                                start >>= 1;
                            }
                        }
                        /* Note: this is net preference for set over set 0. */
                        dist[set] = dist0[set] - val;
                    }
                }
            }
        }
Example #8
0
        /* Compute the terminal constraints for next partition. */
        public static void make_term_props(vtx_data **graph,              /* data structure for graph */
                                           int sub_nvtxs,                 /* number of vtxs in subgraph */
                                           int *loc2glob,                 /* mapping from subgraph to graph */
                                           int *assignment,               /* set for each vertex */
                                           int architecture,              /* 0 => hypercube, 1 => mesh */
                                           int ndims_tot,                 /* total hypercube dimensions */
                                           int ndims,                     /* number of dimensions at this step */
                                           set_info *set_info,            /* data about all the sets */
                                           int setnum,                    /* number of set being divided */
                                           int nsets,                     /* number of subsets being created */
                                           int set_max,                   /* largest set created so far */
                                           int []             subsets,    /* subsets being created */
                                           float *[]           term_wgts, /* set of terminal weights for each vertex */
                                           bool useEdgeWeights            /* are edge weights being used? */
                                           )
        {
            double[] term_wgt = new double[MAXSETS]; /* terminal weights */
            float *  twptr;                          /* one of the term_wgts vectors */

            float *[] dists = new float *[MAXSETS];  /* distances from my subsets to other sets */
            float *   dist;                          /* one of the dists arrays */
            float     edge_wgt;                      /* weight of an edge */
            int       vtx;                           /* vertex number */
            int       neighbor;                      /* neighboring vertex number */
            int       neighbor_setnum;               /* set neighboring vertex is in */
            int       i, j, k;                       /* loop counters */

            /* First compute average distance between my subsets and all other sets. */
            dist = (float *)Marshal.AllocHGlobal(nsets * (set_max + 1) * sizeof(float));
            for (i = 0; i < nsets; i++)
            {
                dists[i] = dist;
                dist    += set_max + 1;
            }

            for (k = 0; k < MAXSETS; k++)
            {
                term_wgt[k] = 0;
            }

            if (architecture == 0)
            {
                avg_dists_cube(ndims_tot, ndims, set_info, nsets, set_max, subsets, dists);
            }
            else if (architecture > 0)
            {
                avg_dists_mesh(architecture, set_info, nsets, set_max, subsets, dists);
            }

            edge_wgt = 1;
            for (i = 1; i <= sub_nvtxs; i++)
            {
                for (k = 1; k < nsets; k++)
                {
                    term_wgt[k] = 0;
                }

                vtx = loc2glob[i];

                for (j = 1; j < graph[vtx]->nedges; j++)
                {
                    neighbor        = graph[vtx]->edges[j];
                    neighbor_setnum = assignment[neighbor];
                    if (neighbor_setnum != setnum)
                    {
                        if (useEdgeWeights)
                        {
                            edge_wgt = graph[vtx]->ewgts[j];
                        }
                        for (k = 1; k < nsets; k++)
                        {
                            dist         = dists[k];
                            term_wgt[k] += edge_wgt * dist[neighbor_setnum];
                        }
                    }
                }

                for (k = 1; k < nsets; k++)
                {
                    twptr    = term_wgts[k];
                    twptr[i] = (float)term_wgt[k];
                }
            }

            Marshal.FreeHGlobal((IntPtr)dists[0]);
        }