root/src/parallelization/hiparsimulator.h @ 108:605da18c9c0a

Revision 108:605da18c9c0a, 8.9 KB (checked in by Andreas Schaefer <gentryx@…>, 16 months ago)
Line 
1#include <libgeodecomp/config.h>
2#ifdef LIBGEODECOMP_FEATURE_MPI
3#ifndef _libgeodecomp_parallelization_hiparsimulator_h_
4#define _libgeodecomp_parallelization_hiparsimulator_h_
5
6#include <cmath>
7#include <libgeodecomp/loadbalancer/loadbalancer.h>
8#include <libgeodecomp/misc/supermap.h>
9#include <libgeodecomp/mpilayer/mpilayer.h>
10#include <libgeodecomp/parallelization/distributedsimulator.h>
11#include <libgeodecomp/parallelization/hiparsimulator/partitions/stripingpartition.h>
12#include <libgeodecomp/parallelization/hiparsimulator/partitionmanager.h>
13#include <libgeodecomp/parallelization/hiparsimulator/intersectingregionaccumulator.h>
14#include <libgeodecomp/parallelization/hiparsimulator/vanillaregionaccumulator.h>
15#include <libgeodecomp/parallelization/hiparsimulator/innersetmarker.h>
16#include <libgeodecomp/parallelization/hiparsimulator/rimmarker.h>
17#include <libgeodecomp/parallelization/hiparsimulator/updategroup.h>
18       
19// fixme: move implementation to hiparsimulator/implementation?
20
21namespace LibGeoDecomp {
22namespace HiParSimulator {
23
24enum EventPoint {LOAD_BALANCING=0, OUTPUT=1, SIMULATION_END=2, PAUSE=3};
25typedef SuperSet<EventPoint> EventSet;
26typedef SuperMap<unsigned, EventSet> EventMap;
27
28inline std::string eventToStr(const EventPoint& event) 
29{
30    switch(event) {
31    case LOAD_BALANCING:
32        return "LOAD_BALANCING";
33    case OUTPUT:
34        return "OUTPUT";
35    case SIMULATION_END:
36        return "SIMULATION_END";
37    default:
38        return "invalid";
39    }
40}
41
42template<class CELL_TYPE, class PARTITION>
43class HiParSimulator : public DistributedSimulator<CELL_TYPE>
44{
45    friend class HiParSimulatorTest;
46public:
47    typedef typename CELL_TYPE::Topology Topology;
48    typedef DisplacedGrid<CELL_TYPE, Topology> GridType;
49    static const int DIMENSIONS = Topology::DIMENSIONS;
50
51    inline HiParSimulator(
52        Initializer<CELL_TYPE> *_initializer,
53        LoadBalancer *_balancer = 0,
54        const unsigned& _outputPeriod = 1, 
55        const unsigned& _loadBalancingPeriod = 1,
56        // fixme: move ghostZoneWidth to partition manager
57        const unsigned &ghostZoneWidth = 1,
58        const unsigned& _root = 0,
59        // fixme: forward this to regionStepper
60        MPI::Comm *communicator = &MPI::COMM_WORLD) : 
61        DistributedSimulator<CELL_TYPE>(_initializer),
62        balancer(_balancer),
63        outputPeriod(_outputPeriod * CELL_TYPE::nanoSteps()),
64        loadBalancingPeriod(_loadBalancingPeriod * CELL_TYPE::nanoSteps()),
65        root(_root),
66        mpiLayer(communicator),
67        eventRepetitionHorizon(4)
68    {
69        resetSimulation(ghostZoneWidth);
70    }   
71
72    // fixme: need test
73    inline void run()
74    {
75        unsigned remainingNanoSteps = this->initializer->maxSteps() * 
76            CELL_TYPE::nanoSteps() - nanoStepCounter;
77        nanoStep(remainingNanoSteps);
78    }
79
80    // fixme: need test
81    inline void step()
82    {
83        nanoStep(CELL_TYPE::nanoSteps());
84    }
85
86    // fixme: need test
87    virtual void getGridFragment(
88        const GridType **grid, 
89        const Region<2> **validRegion) 
90    {
91        *validRegion = &partitionManager.ownRegion();
92    }
93
94    inline const DisplacedGrid<CELL_TYPE> *getDisplacedGrid()
95    {       
96        return 0;
97        // return regionStepper.getGrid();
98    }
99
100private:
101//     SuperMap<unsigned, Outgroup<PARTITION> > outgroups;
102    // fixme: who deletes the balancer?
103    LoadBalancer *balancer;
104    unsigned outputPeriod;
105    unsigned loadBalancingPeriod;
106    unsigned nanoStepCounter;
107    EventMap events;
108    PartitionManager<2> partitionManager;
109    unsigned root;   
110    // fixme: can we get rid of this?
111    MPILayer mpiLayer;
112    unsigned eventRepetitionHorizon;
113
114    inline void nanoStep(const unsigned& s)
115    {
116        unsigned endNanoStep = nanoStepCounter + s;
117        events[endNanoStep].insert(PAUSE);
118       
119        while (nanoStepCounter < endNanoStep) {
120            std::pair<unsigned, EventSet> currentEvents = extractCurrentEvents();
121            nanoStepCounter = currentEvents.first;
122            handleEvents(currentEvents.second);
123        }
124    }
125
126    inline std::pair<unsigned, EventSet> extractCurrentEvents()
127    {
128        EventMap::iterator curEventsPair = events.begin();
129        unsigned curStop  = curEventsPair->first;
130        EventSet curEvents = curEventsPair->second;
131        if (curStop < nanoStepCounter)
132            throw std::logic_error("Stale events found in event point queue");
133        events.erase(curEventsPair);
134        return std::make_pair(curStop, curEvents);
135    }
136
137
138    inline void handleEvents(const EventSet& curEvents)
139    {
140        //fixme: handle events
141        //             for (EventSet::iterator event = curEvents.begin(); event != curEvents.end(); ++event)
142        //                 std::cout << "  nanoStep: " << nanoStepCounter << " got event: " << eventToStr(*event) << "\n";
143        //             if (curEvents.size() > 1)
144        //                 std::cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n";
145        //             std::cout << "\n";
146           
147        if (curEvents.count(OUTPUT)) 
148            events[this->nextOutput(eventRepetitionHorizon)].insert(OUTPUT);
149        if (curEvents.count(LOAD_BALANCING))
150            events[this->nextLoadBalancing(eventRepetitionHorizon)].insert(LOAD_BALANCING);
151    }
152
153
154    inline void resetSimulation(const unsigned &ghostZoneWidth)
155    {
156        // this->resetEvents();
157        // this->resetRegions(ghostZoneWidth);
158    }
159
160    inline void resetRegions(const unsigned &ghostZoneWidth)
161    {
162        partitionManager.resetRegions(
163            CoordBox<2>(Coord<2>(), 
164                        this->initializer->gridDimensions()),
165            new VanillaRegionAccumulator<PARTITION>(
166            myPartition(),
167            myOffset(),
168            initialWeights()),
169            mpiLayer.rank(),
170            ghostZoneWidth);
171
172        SuperVector<CoordBox<2> > boundingBoxes(mpiLayer.size());
173        CoordBox<2> ownBoundingBox(partitionManager.ownRegion().boundingBox());
174        mpiLayer.allGather(ownBoundingBox, &boundingBoxes);
175        partitionManager.resetGhostZones(boundingBoxes);
176        // fixme: care for validGhostZoneWidth
177    }
178
179    inline SuperVector<unsigned> initialWeights() const
180    {
181        SuperVector<unsigned> weights(mpiLayer.size());
182        if (mpiLayer.rank() == root) {
183            unsigned remainingCells = this->initializer->gridBox().size();
184            for (unsigned i = mpiLayer.size(); i > 0; --i) {
185                unsigned curWeight = (unsigned)round((double)remainingCells / i);
186                weights[i - 1] = curWeight;
187                remainingCells -= curWeight;
188            }
189        }
190        mpiLayer.broadcastVector(&weights, root);
191        return weights;
192    }
193   
194    inline void resetEvents()
195    {
196        nanoStepCounter = this->initializer->startStep() * CELL_TYPE::nanoSteps();
197        events.clear();
198        unsigned firstOutput        = ((int)ceil(nanoStepCounter / (double)outputPeriod))        * outputPeriod;
199        unsigned firstLoadBalancing = ((int)ceil(nanoStepCounter / (double)loadBalancingPeriod)) * loadBalancingPeriod;
200        for (int i = 0; i < eventRepetitionHorizon; ++i) {
201            events[firstOutput        + i * outputPeriod       ].insert(OUTPUT);
202            events[firstLoadBalancing + i * loadBalancingPeriod].insert(LOAD_BALANCING);
203        }
204        events[this->initializer->maxSteps() * CELL_TYPE::nanoSteps()].insert(SIMULATION_END);
205    }
206
207    inline unsigned nextOutput(const unsigned& horizon=1) const
208    {
209        return (nanoStepCounter / outputPeriod + horizon) * outputPeriod;
210    }   
211
212    inline unsigned nextLoadBalancing(const unsigned horizon=1) const
213    {
214        return (nanoStepCounter / loadBalancingPeriod + horizon) * loadBalancingPeriod;
215    }   
216
217    inline Region<2> allGatherGroupRegion() 
218    {
219        return allGatherGroupRegion(partitionManager.ownRegion());
220    }
221
222    inline Region<2> allGatherGroupRegion(const Region<2>& region) 
223    {
224        int streakNum = region.numStreaks();
225        SuperVector<int> streakNums(mpiLayer.allGather(streakNum));
226        SuperVector<Streak<2> > ownStreaks(region.toVector());
227        SuperVector<Streak<2> > allStreaks(mpiLayer.allGatherV(&ownStreaks[0], streakNums));
228        Region<2> ret;
229        for (SuperVector<Streak<2> >::iterator i = allStreaks.begin(); 
230             i != allStreaks.end(); ++i)
231            ret << *i;
232        return ret;
233    }
234
235    inline void registerOutgroupRegion(const unsigned& relativeLevel, const Region<2>& region)
236    {
237//         outgroupSteppers[relativeLevel].resetRegions(
238
239// IntersectingRegionAccumulator<PARTITION>(region, myPartition(), myOffset(), initialWeights());
240    }
241
242    inline void updateOutgroupRegion(const unsigned& relativeLevel, const unsigned& steps)
243    {
244       
245    }
246
247    inline PARTITION myPartition() const
248    {
249        return PARTITION(Coord<2>(0, 0), 
250                         this->initializer->gridDimensions());
251    }
252
253    inline unsigned myOffset() const
254    {
255        return 0;
256    }
257
258};
259
260};
261};
262
263#endif
264#endif
Note: See TracBrowser for help on using the browser.