-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathPartitionParmetis.h
145 lines (126 loc) · 4.49 KB
/
PartitionParmetis.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// SPDX-FileCopyrightText: 2017-2023 Technical University of Munich
//
// SPDX-License-Identifier: BSD-3-Clause
/**
* @file
* This file is part of PUML
*
* For conditions of distribution and use, please see the copyright
* notice in the file 'COPYING' at the root directory of this package
* and the copyright notice at https://github.com/TUM-I5/PUMGen
*
* @author Sebastian Rettenberger <[email protected]>
* @author David Schneller <[email protected]>
*/
#ifndef PUML_PARTITIONPARMETIS_H
#define PUML_PARTITIONPARMETIS_H
#include "PartitionTarget.h"
#include <vector>
#include "utils/logger.h"
#ifdef USE_MPI
#endif // USE_MPI
#ifndef USE_PARMETIS
#warning ParMETIS is not enabled.
#endif
#include <metis.h>
#include <parmetis.h>
#include <cassert>
#include "PartitionBase.h"
#include "PartitionGraph.h"
#include "Topology.h"
namespace PUML {
enum class ParmetisPartitionMode { Default, Geometric };
template <TopoType Topo>
class PartitionParmetis : public PartitionBase<Topo> {
public:
PartitionParmetis(ParmetisPartitionMode mode) : mode(mode) {}
#ifdef USE_MPI
virtual auto partition(int* partition,
const PartitionGraph<Topo>& graph,
const PartitionTarget& target,
int seed = 1) -> PartitioningResult {
auto comm = graph.comm();
std::vector<idx_t> vtxdist(graph.vertexDistribution().begin(),
graph.vertexDistribution().end());
std::vector<idx_t> xadj(graph.adjDisp().begin(), graph.adjDisp().end());
std::vector<idx_t> adjncy(graph.adj().begin(), graph.adj().end());
std::vector<idx_t> vwgt(graph.vertexWeights().begin(), graph.vertexWeights().end());
std::vector<idx_t> adjwgt(graph.edgeWeights().begin(), graph.edgeWeights().end());
auto cellCount = graph.localVertexCount();
idx_t ncon = graph.vertexWeightCount();
if (ncon == 0) {
ncon = 1;
}
idx_t nparts = target.vertexCount();
std::vector<real_t> tpwgts(nparts * ncon, static_cast<real_t>(1.) / nparts);
if (!target.vertexWeightsUniform()) {
for (idx_t i = 0; i < target.vertexCount(); i++) {
for (idx_t j = 0; j < ncon; ++j) {
tpwgts[(i * ncon) + j] = target.vertexWeights()[i];
}
}
}
idx_t options[3] = {1, 0, seed};
idx_t numflag = 0;
idx_t wgtflag = 0;
if (!vwgt.empty()) {
wgtflag |= 2;
}
if (!adjwgt.empty()) {
wgtflag |= 1;
}
std::vector<real_t> ubvec(ncon, target.imbalance() + 1.0);
idx_t edgecut = 0;
std::vector<idx_t> part(cellCount);
if (mode == ParmetisPartitionMode::Default) {
ParMETIS_V3_PartKway(vtxdist.data(),
xadj.data(),
adjncy.data(),
vwgt.empty() ? nullptr : vwgt.data(),
adjwgt.empty() ? nullptr : adjwgt.data(),
&wgtflag,
&numflag,
&ncon,
&nparts,
tpwgts.data(),
ubvec.data(),
options,
&edgecut,
part.data(),
&comm);
} else if (mode == ParmetisPartitionMode::Geometric) {
idx_t ndims = 3;
std::vector<real_t> xyz;
graph.geometricCoordinates(xyz);
ParMETIS_V3_PartGeomKway(vtxdist.data(),
xadj.data(),
adjncy.data(),
vwgt.empty() ? nullptr : vwgt.data(),
adjwgt.empty() ? nullptr : adjwgt.data(),
&wgtflag,
&numflag,
&ndims,
xyz.data(),
&ncon,
&nparts,
tpwgts.data(),
ubvec.data(),
options,
&edgecut,
part.data(),
&comm);
} else {
logError() << "Unknown partitioning mode for ParMETIS";
return PartitioningResult::ERROR;
}
for (int i = 0; i < cellCount; i++) {
partition[i] = part[i];
}
return PartitioningResult::SUCCESS;
}
#endif // USE_MPI
private:
ParmetisPartitionMode mode;
};
} // namespace PUML
#endif // PUML_PARTITIONPARMETIS_H