Ejemplo n.º 1
0
    std::tuple<ptrdiff_t, ptrdiff_t>
    partition(const distributed_matrix<B> &A, idx_t npart, std::vector<ptrdiff_t> &perm) const {
        communicator comm = A.comm();
        idx_t n = A.loc_rows();
        int active = (n > 0);

        std::vector<idx_t> ptr;
        std::vector<idx_t> col;

        symm_graph(A, ptr, col);

        idx_t wgtflag = 0;
        idx_t numflag = 0;
        idx_t options = 0;
        idx_t edgecut = 0;
        idx_t ncon    = 1;

        std::vector<real_t> tpwgts(npart, 1.0 / npart);
        std::vector<real_t> ubvec(ncon, 1.05);
        std::vector<idx_t>  part(n);
        if (!n) part.reserve(1); // So that part.data() is not NULL

        MPI_Comm scomm;
        MPI_Comm_split(comm, active ? 0 : MPI_UNDEFINED, comm.rank, &scomm);

        if (active) {
            communicator sc(scomm);
            std::vector<idx_t> vtxdist = sc.exclusive_sum(n);

            sc.check(
                    METIS_OK == ParMETIS_V3_PartKway( &vtxdist[0], &ptr[0],
                        &col[0], NULL, NULL, &wgtflag, &numflag, &ncon,
                        &npart, &tpwgts[0], &ubvec[0], &options, &edgecut,
                        &part[0], &scomm),
                    "Error in ParMETIS"
                    );

            MPI_Comm_free(&scomm);
        }

        return graph_perm_index(comm, npart, part, perm);
    }
void 
ParMETISGraphPartitionerImpl::p_partition(void)
{
  int me(this->processor_rank());
  std::vector<idx_t> vtxdist;
  std::vector<idx_t> xadj;
  std::vector<idx_t> adjncy;

  ParMETISGraphWrapper wrap(p_adjacency_list);

  wrap.get_csr_local(vtxdist, xadj, adjncy);

  int nnodes(vtxdist[me+1] - vtxdist[me]);

#if 0
  for (int p = 0; p < this->processor_size(); ++p) {
    if (this->processor_rank() == p) {
      std::cout << "Processor " << p << ":     nodes: ";
      for (Index n = 0; n < nnodes; ++n) {
        std::cout << p_adjacency_list.node_index(n) << ",";
      }
      std::cout << std::endl;
      std::cout << "Processor " << p << ":   vtxdist: ";
      std::copy(vtxdist.begin(), vtxdist.end(),
                std::ostream_iterator<idx_t>(std::cout, ","));
      std::cout << std::endl;
      std::cout << "Processor " << p << ":      xadj: ";
      std::copy(xadj.begin(), xadj.end(),
                std::ostream_iterator<idx_t>(std::cout, ","));
      std::cout << std::endl;
      std::cout << "Processor " << p << ":    adjncy: ";
      std::copy(adjncy.begin(), adjncy.end(),
                std::ostream_iterator<idx_t>(std::cout, ","));
      std::cout << std::endl;
    }
    this->communicator().barrier();
  }
#endif

  // Call the partitioner (try to use variable names that match the documentation)

  int status;

  idx_t ncon(1);
  idx_t wgtflag(3), numflag(0);
  idx_t nparts(this->processor_size());
  std::vector<idx_t> vwgt(nnodes, 1);
  std::vector<idx_t> adjwgt(adjncy.size(), 2);
  std::vector<real_t> tpwgts(nparts*ncon, 1.0/static_cast<real_t>(nparts));
  real_t ubvec(1.05);
  std::vector<idx_t> options(3);
  options[0] = 1;
  options[1] = 127;
  options[2] = 14;
  MPI_Comm comm(this->communicator());

  idx_t edgecut;
  std::vector<idx_t> part(nnodes);
  status = ParMETIS_V3_PartKway(&vtxdist[0], 
                                &xadj[0], 
                                &adjncy[0],
                                &vwgt[0],
                                &adjwgt[0],
                                &wgtflag,
                                &numflag,
                                &ncon,
                                &nparts,
                                &tpwgts[0],
                                &ubvec,
                                &options[0],
                                &edgecut, &part[0],
                                &comm);
  if (status != 0) {
    // FIXME: throw an exception
  }

  // "part" contains the destination processors; transfer this to the
  // local array

  wrap.set_partition(vtxdist, part);
  wrap.get_partition(p_node_destinations);

}