Peano
Loading...
Searching...
No Matches
SplitOversizedTree.cpp
Go to the documentation of this file.
2
3#include "tarch/Assertions.h"
4#include "tarch/tarch.h"
10
11
13 "toolbox::loadbalancing::strategies::SplitOversizedTree"
14);
15
16
18 Configuration* configuration, CostMetrics* costMetrics
19):
20 AbstractLoadBalancing(configuration, costMetrics),
21 _roundRobinToken(0) {
22 assertion(configuration != nullptr);
23 assertion(costMetrics != nullptr);
26}
27
28
30
31
33 std::ostringstream msg;
34
35 msg
36 << "(type=split-oversized-tree"
37 << ",state=" << ::toString(_state) << ",statistics=" << _statistics.toString() << ",cost-metrics="
38 << _costMetrics->toString() << ",round-robin-token=" << _roundRobinToken << ",blacklist=" << _blacklist.toString()
39 << ",heaviest-local-tree=" << getIdOfHeaviestLocalSpacetree() << " (analysed)"
40 << ",heaviest-local-weight=" << getWeightOfHeaviestLocalSpacetree() << " (analysed)"
42 << ",is-inter-rank-balancing-bad=" << isInterRankBalancingBad()
43 << ",is-intra-rank-balancing-bad=" << isIntraRankBalancingBad() << ",target-tree-cost=" << getTargetTreeCost()
44 << ",min-tree-size=" << _configuration->getMinTreeSize(_state) << ")";
45
46 return msg.str();
47}
48
49
52 logDebug("updateState()", "don't update as we have switched off");
53 } else if (areRanksUnemployed()) {
55 logDebug("updateState()", "switch to state " << ::toString(_state));
56 } else if (isInterRankBalancingBad() and _roundRobinToken == tarch::mpi::Rank::getInstance().getRank() and doesLocalTreeViolateThreshold()) {
58 logDebug("updateState()", "switch to state " << ::toString(_state));
59 } else if (isIntraRankBalancingBad() and doesLocalTreeViolateThreshold()) {
61 logDebug("updateState()", "switch to state " << ::toString(_state));
62 } else {
64
65 _roundRobinToken++;
66 _roundRobinToken = _roundRobinToken % tarch::mpi::Rank::getInstance().getNumberOfRanks();
67 }
68}
69
70
72 if (not _statistics.hasConsistentViewOfWorld()) { //
73 return false;
74 } else if (peano4::parallel::SpacetreeSet::getInstance().getLocalSpacetrees().size() == 0) {
75 return false;
76 } else if (peano4::parallel::SpacetreeSet::getInstance().getLocalSpacetrees().size() == 1) {
77 return true;
78 }
79 else if ( static_cast<int>(peano4::parallel::SpacetreeSet::getInstance().getLocalSpacetrees().size()) >= _configuration->getMaxLocalTreesPerRank(_state) ) {
80 return false;
81 } else {
82 bool result = false;
83
85 result |= _costMetrics->getCostOfLocalTree(p) > getTargetTreeCost();
86 }
87
88 return result;
89 }
90}
91
92
94#if PeanoDebug > 0
95 logInfo("updateLoadBalancing()", "load balancing's state=" << toString());
96#endif
97
98 switch (_state) {
100 int heaviestSpacetree = getIdOfHeaviestLocalSpacetree(_configuration->getWorstCaseBalancingRatio(_state));
101 double weightOfHeaviestSpacetree = getWeightOfHeaviestLocalSpacetree();
102 if (
103 fitsIntoMemory(_state)
104 and
105 heaviestSpacetree!=NoHeaviestTreeAvailable
106 and
107 not _blacklist.isBlacklisted(heaviestSpacetree)
108 and
109 weightOfHeaviestSpacetree > getTargetTreeCost()
110 and
111 _costMetrics->getLightestRank()!=tarch::mpi::Rank::getInstance().getRank()
112 and
113 computeNumberOfSplits(heaviestSpacetree)>0
114 ) {
115 logInfo(
116 "updateLoadBalancing()",
117 "Not all ranks are used. Split once and deploy to lightest global rank " << _costMetrics->getLightestRank()
118 );
119 triggerSplit(heaviestSpacetree, _costMetrics->getLightestRank(), 1);
120 } else if (heaviestSpacetree != NoHeaviestTreeAvailable) {
121 logInfo(
122 "updateLoadBalancing()",
123 "can't split heaviest tree " << heaviestSpacetree << " even though this tree is too heavy " << toString()
124 );
125 }
126 } break;
128 int heaviestSpacetree = getIdOfHeaviestLocalSpacetree();
129 int weightOfHeaviestSpacetree = getWeightOfHeaviestLocalSpacetree();
130 if (
131 fitsIntoMemory(_state)
132 and
133 heaviestSpacetree != NoHeaviestTreeAvailable
134 and
135 not _blacklist.isBlacklisted(heaviestSpacetree)
136 and
137 weightOfHeaviestSpacetree > getTargetTreeCost()
138 and
139 computeNumberOfSplits(heaviestSpacetree) > 0
140 ) {
141 logInfo(
142 "updateLoadBalancing()",
143 "biggest local tree "
144 << heaviestSpacetree << " is too heavy as it hosts " << weightOfHeaviestSpacetree
145 << " cells. Try to split tree " << computeNumberOfSplits(heaviestSpacetree)
146 << " times and to offload subsection(s) of tree to " << _costMetrics->getLightestRank() << " " << toString()
147 );
148 triggerSplit(heaviestSpacetree, _costMetrics->getLightestRank(), computeNumberOfSplits(heaviestSpacetree));
149 } else if (heaviestSpacetree != NoHeaviestTreeAvailable) {
150 logInfo(
151 "updateLoadBalancing()",
152 "can't split heaviest tree "
153 << heaviestSpacetree << " and fork off to remote rank,as "
154 << "heaviest tree is on blacklist " << toString()
155 );
156 }
157 } break;
160 if (
161 fitsIntoMemory(_state)
162 and
163 not _blacklist.isBlacklisted(p)
164 and
165 _costMetrics->getCostOfLocalTree(p) > getTargetTreeCost()
166 and
167 computeNumberOfSplits(p) > 0
168 ) {
169 logInfo(
170 "updateLoadBalancing()",
171 "local tree "
172 << p << " is too heavy as it has a weight of " << _costMetrics->getCostOfLocalTree(p)
173 << ". Try to split tree " << computeNumberOfSplits(p) << " times on local rank " << toString()
174 << " (max local trees=" << _configuration->getMaxLocalTreesPerRank(_state)
175 << ", min-tree-size=" << _configuration->getMinTreeSize(_state) << ")"
176 );
177 triggerSplit(p, tarch::mpi::Rank::getInstance().getRank(), computeNumberOfSplits(p));
178 }
179 }
180 } break;
181 default:
182 break;
183 }
184}
185
186
188 _statistics.updateGlobalView();
189 _costMetrics->updateGlobalView();
190 _blacklist.update();
191
192 updateLoadBalancing();
193 updateState();
194
195 _statistics.notifyOfStateChange(_state);
196
198}
199
200
202 int numberOfSplits = static_cast<int>(_costMetrics->getCostOfLocalTree(sourceTree) / getTargetTreeCost()) - 1;
203
204 numberOfSplits = std::max(1, numberOfSplits);
205 numberOfSplits = std::min(
206 numberOfSplits,
207 _configuration->getMaxLocalTreesPerRank(_state)
208 -
210 );
211
212 int currentSourceTreeCells = peano4::parallel::SpacetreeSet::getInstance()
213 .getGridStatistics(sourceTree)
215
216 while (
217 currentSourceTreeCells / (numberOfSplits + 1) < _configuration->getMinTreeSize(_state)
218 and
219 numberOfSplits > 0
220 ) {
221 numberOfSplits--;
222 }
223
224 return numberOfSplits;
225}
226
227
229 int sourceTree, int targetRank, int numberOfSplits
230) {
231 const int numberOfSplitCells = std::max(
232 1,
233 peano4::parallel::SpacetreeSet::getInstance().getGridStatistics(sourceTree).getNumberOfLocalUnrefinedCells()
234 / (1 + numberOfSplits)
235 );
236 for (int i = 0; i < numberOfSplits; i++) {
238 sourceTree,
239 peano4::SplitInstruction{numberOfSplitCells, _configuration->getMode(_state)},
240 targetRank
241 );
242 if (not success) {
243 logInfo("triggerSplit()", "wanted to split local rank " << sourceTree << " but failed");
244 }
245
246 _blacklist.triggeredSplit(sourceTree);
247 _statistics.incLocalNumberOfSplits();
248 }
249}
250
251
253 const int TargetNumberOfThreads = std::min(
255 _configuration->getMaxLocalTreesPerRank(_state),
257 );
258
259 return _costMetrics->getGlobalCost() / tarch::mpi::Rank::getInstance().getNumberOfRanks() / TargetNumberOfThreads;
260}
#define assertion(expr)
#define logDebug(methodName, logMacroMessageStream)
Definition Log.h:50
#define logInfo(methodName, logMacroMessageStream)
Wrapper macro around tarch::tarch::logging::Log to improve logging.
Definition Log.h:411
bool split(int treeId, const peano4::SplitInstruction &instruction, int targetRank)
Split a local tree.
peano4::grid::GridStatistics getGridStatistics() const
Return statistics object for primary spacetree.
static SpacetreeSet & getInstance()
std::set< int > getLocalSpacetrees() const
Log Device.
Definition Log.h:516
int getNumberOfRanks() const
Definition Rank.cpp:552
static Rank & getInstance()
This operation returns the singleton instance.
Definition Rank.cpp:539
int getRank() const
Return rank of this node.
Definition Rank.cpp:529
static Core & getInstance()
Definition Core.cpp:56
int getNumberOfThreads() const
Returns the number of threads that is used.
Definition Core.cpp:67
Abstract interface to tweak the behaviour of the recursive subdivision.
void notifyOfStateChange(State state)
virtual void finishStep() override
Triggers actual load balancing data exchange, triggers rebalancing, and dumps statistics.
void updateLoadBalancing()
Core actions where we take the action and translate it into action - what a pun.
SplitOversizedTree(Configuration *configuration=new DefaultConfiguration(), CostMetrics *costMetrics=new toolbox::loadbalancing::metrics::CellCount())
Set up recursive subdivision.
virtual std::string toString() const override
I need the stats here mainly for debugging purposes.
void triggerSplit(int sourceTree, int targetRank, int numberOfSplits)
Wrapper around the spacetree set which also updates the blacklist.
bool doesLocalTreeViolateThreshold() const
Is the balancing on the rank ok.
std::string toString(Filter filter)
Definition convert.cpp:170
int getWeightOfHeaviestLocalSpacetree()
This is a helper routine which is used by ExaHyPE's default main for for example.
void dumpStatistics()
Dump the stats of the lb to the terminal (info device).
@ InterRankBalancing
We have completed the first two phases and try to balance between the ranks now to meet the load bala...
@ WaitForRoundRobinToken
You usually don't get this state when we query the configuration, i.e.
@ SwitchedOff
You usually don't get this state when we query the configuration, i.e.
@ InterRankDistribution
Code has not yet spread out over all ranks but would like to do so now.
@ IntraRankBalancing
The code is satisfied with the load balancing quality between the ranks and now spawns more partition...
Instruction to split.
Definition grid.h:34