Zoltan2
Loading...
Searching...
No Matches
Zoltan2_AlgBlock.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Zoltan2: A package of combinatorial algorithms for scientific computing
4//
5// Copyright 2012 NTESS and the Zoltan2 contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef _ZOLTAN2_ALGBLOCK_HPP_
11#define _ZOLTAN2_ALGBLOCK_HPP_
12
13#include <Zoltan2_Algorithm.hpp>
16
17#include <bitset>
18#include <sstream>
19#include <string>
20
25namespace Zoltan2{
26
37
55template <typename Adapter>
56class AlgBlock : public Algorithm<Adapter>
57{
58
59private:
60 const RCP<const Environment> env;
61 const RCP<const Comm<int> > problemComm;
62 const RCP<const typename Adapter::base_adapter_t > adapter;
63
64public:
65 typedef typename Adapter::lno_t lno_t; // local ids
66 typedef typename Adapter::gno_t gno_t; // global ids
67 typedef typename Adapter::scalar_t scalar_t; // scalars
68 typedef typename Adapter::part_t part_t; // part numbers
69
70 // Constructor
72 const RCP<const Environment> &env_,
73 const RCP<const Comm<int> > &problemComm_,
74 const RCP<const typename Adapter::base_adapter_t > &adapter_
75 ) :
76 env(env_), problemComm(problemComm_), adapter(adapter_)
77 {}
78
79 // Partitioning method
80 void partition(const RCP<PartitioningSolution<Adapter> > &solution)
81 {
82 env->debug(DETAILED_STATUS, std::string("Entering AlgBlock"));
83
84 int rank = env->myRank_;
85 int nprocs = env->numProcs_;
86
88 // From the IdentifierModel we need:
89 // the number of gnos
90 // number of weights per gno
91 // the weights
92
93 modelFlag_t modelFlag;
94 IdentifierModel<typename Adapter::base_adapter_t> ids(adapter, env, problemComm, modelFlag);
95 size_t numGnos = ids.getLocalNumIdentifiers();
96
97 ArrayView<const gno_t> idList;
98 typedef StridedData<lno_t, scalar_t> input_t;
99 ArrayView<input_t> wgtList;
100
101 ids.getIdentifierList(idList, wgtList);
102
103 // If user supplied no weights, we use uniform weights.
104 bool uniformWeights = (wgtList.size() == 0);
105
107 // Partitioning problem parameters of interest:
108 // objective
109 // imbalance_tolerance
110
111 const Teuchos::ParameterList &pl = env->getParameters();
112 const Teuchos::ParameterEntry *pe;
113
114 pe = pl.getEntryPtr("partitioning_objective");
115 if (pe) {
116 std::string po = pe->getValue<std::string>(&po);
117 if (po == std::string("balance_object_count"))
118 uniformWeights = true; // User requests that we ignore weights
119 }
120
121 double imbalanceTolerance=1.1;
122 pe = pl.getEntryPtr("imbalance_tolerance");
123 if (pe) imbalanceTolerance = pe->getValue<double>(&imbalanceTolerance);
124
126 // From the Solution we get part information:
127 // number of parts and part sizes
128
129 size_t numGlobalParts = solution->getTargetGlobalNumberOfParts();
130
131 Array<scalar_t> part_sizes(numGlobalParts);
132
133 if (solution->criteriaHasUniformPartSizes(0))
134 for (unsigned int i=0; i<numGlobalParts; i++)
135 part_sizes[i] = 1.0 / numGlobalParts;
136 else
137 for (unsigned int i=0; i<numGlobalParts; i++)
138 part_sizes[i] = solution->getCriteriaPartSize(0, i);
139
140 for (unsigned int i=1; i<numGlobalParts; i++)
141 part_sizes[i] += part_sizes[i-1];
142
143 // TODO assertion that last part sizes is about equal to 1.0
144
145
147 // The algorithm
148 //
149 // Block partitioning algorithm lifted from zoltan/src/simple/block.c
150 // The solution is:
151 // a list of part numbers in gno order
152 // an imbalance for each weight
153
154 scalar_t wtsum(0);
155
156 if (!uniformWeights) {
157 for (size_t i=0; i<numGnos; i++)
158 wtsum += wgtList[0][i]; // [] operator knows stride
159 }
160 else
161 wtsum = static_cast<scalar_t>(numGnos);
162
163 Array<scalar_t> scansum(nprocs+1, 0);
164
165 Teuchos::gatherAll<int, scalar_t>(*problemComm, 1, &wtsum, nprocs,
166 scansum.getRawPtr()+1);
167
168 /* scansum = sum of weights on lower processors, excluding self. */
169
170 for (int i=2; i<=nprocs; i++)
171 scansum[i] += scansum[i-1];
172
173 scalar_t globalTotalWeight = scansum[nprocs];
174
175 if (env->getDebugLevel() >= VERBOSE_DETAILED_STATUS) {
176 std::ostringstream oss("Part sizes: ");
177 for (unsigned int i=0; i < numGlobalParts; i++)
178 oss << part_sizes[i] << " ";
179 oss << std::endl << std::endl << "Weights : ";
180 for (int i=0; i <= nprocs; i++)
181 oss << scansum[i] << " ";
182 oss << std::endl;
183 env->debug(VERBOSE_DETAILED_STATUS, oss.str());
184 }
185
186 /* Loop over objects and assign part. */
187 part_t part = 0;
188 wtsum = scansum[rank];
189 Array<scalar_t> partTotal(numGlobalParts, 0);
190 ArrayRCP<part_t> gnoPart= arcp(new part_t[numGnos], 0, numGnos);
191
192 env->memory("Block algorithm memory");
193
194 for (size_t i=0; i<numGnos; i++){
195 scalar_t gnoWeight = (uniformWeights ? 1.0 : wgtList[0][i]);
196 /* wtsum is now sum of all lower-ordered object */
197 /* determine new part number for this object,
198 using the "center of gravity" */
199 while (unsigned(part)<numGlobalParts-1 &&
200 (wtsum+0.5*gnoWeight) > part_sizes[part]*globalTotalWeight)
201 part++;
202 gnoPart[i] = part;
203 partTotal[part] += gnoWeight;
204 wtsum += gnoWeight;
205 }
206
208 // Done
209
210 solution->setParts(gnoPart);
211
212 env->debug(DETAILED_STATUS, std::string("Exiting AlgBlock"));
213 }
214};
215
216} // namespace Zoltan2
217
218#endif
Defines the IdentifierModel interface.
Defines the PartitioningSolution class.
Adapter::part_t part_t
AlgBlock(const RCP< const Environment > &env_, const RCP< const Comm< int > > &problemComm_, const RCP< const typename Adapter::base_adapter_t > &adapter_)
Adapter::scalar_t scalar_t
void partition(const RCP< PartitioningSolution< Adapter > > &solution)
Partitioning method.
Algorithm defines the base class for all algorithms.
IdentifierModel defines the interface for all identifier models.
size_t getIdentifierList(ArrayView< const gno_t > &Ids, ArrayView< input_t > &wgts) const
A PartitioningSolution is a solution to a partitioning problem.
The StridedData class manages lists of weights or coordinates.
Created by mbenlioglu on Aug 31, 2020.
std::bitset< NUM_MODEL_FLAGS > modelFlag_t
@ DETAILED_STATUS
sub-steps, each method's entry and exit
@ VERBOSE_DETAILED_STATUS
include more detail about sub-steps
blockParams
The boolean parameters of interest to the Block algorithm.
@ block_balanceTotalMaximum