fpmas 1.5
ghost_mode.h
Go to the documentation of this file.
1#ifndef FPMAS_GHOST_MODE_H
2#define FPMAS_GHOST_MODE_H
3
10#include "fpmas/utils/macros.h"
11#include "../data_update_pack.h"
12#include "../synchro.h"
13#include "single_thread_mutex.h"
14
15namespace fpmas { namespace synchro {
16 namespace ghost {
17
26 template<typename T>
27 class GhostMutex : public SingleThreadMutex<T> {
28 public:
30
31 const T& read() override {return this->data();};
32 void releaseRead() override {};
33 T& acquire() override {return this->data();};
34 void releaseAcquire() override {};
35 void synchronize() override {};
36 };
37
44 template<typename T>
46 public:
55
56 private:
57 DataMpi& data_mpi;
58 IdMpi& id_mpi;
59
61 std::unordered_map<int, std::vector<DistributedId>> buildRequests();
62 std::unordered_map<int, std::vector<DistributedId>> buildRequests(
63 std::unordered_set<api::graph::DistributedNode<T>*> nodes
64 );
65 void _synchronize(
66 std::unordered_map<int, std::vector<DistributedId>> requests
67 );
68
69 public:
79 DataMpi& data_mpi, IdMpi& id_mpi,
81 )
82 : data_mpi(data_mpi), id_mpi(id_mpi), graph(graph) {}
83
88 void synchronize() override;
89
90 void synchronize(
91 std::unordered_set<api::graph::DistributedNode<T>*> nodes
92 ) override;
93 };
94
95 template<typename T>
96 void GhostDataSync<T>::_synchronize(
97 std::unordered_map<int, std::vector<DistributedId>> requests) {
98 FPMAS_LOGI(
99 graph.getMpiCommunicator().getRank(), "GHOST_MODE",
100 "Synchronizing graph data...", ""
101 );
102 requests = id_mpi.migrate(requests);
103
104 std::unordered_map<int, std::vector<NodeUpdatePack<T>>> updated_data;
105 for(auto list : requests) {
106 for(auto id : list.second) {
107 FPMAS_LOGV(
108 graph.getMpiCommunicator().getRank(), "GHOST_MODE",
109 "Export %s to %i", FPMAS_C_STR(id), list.first
110 );
111 auto node = graph.getNode(id);
112 updated_data[list.first].push_back({
113 id, node->data(), node->getWeight()
114 });
115 }
116 }
117 // TODO : Should use data update packs.
118 updated_data = data_mpi.migrate(updated_data);
119 for(auto list : updated_data) {
120 for(auto& data : list.second) {
121 auto local_node = graph.getNode(data.id);
123 local_node->data(),
124 std::move(data.updated_data)
125 );
126 local_node->setWeight(data.updated_weight);
127 }
128 }
129
130 FPMAS_LOGI(
131 graph.getMpiCommunicator().getRank(), "GHOST_MODE",
132 "Graph data synchronized.", ""
133 );
134 }
135
136 template<typename T>
137 std::unordered_map<int, std::vector<DistributedId>> GhostDataSync<T>
138 ::buildRequests(std::unordered_set<api::graph::DistributedNode<T>*> nodes) {
139 std::unordered_map<int, std::vector<DistributedId>> requests;
140 for(auto node : nodes) {
141 if(node->state() == fpmas::api::graph::DISTANT) {
142 FPMAS_LOGV(
143 graph.getMpiCommunicator().getRank(), "GHOST_MODE",
144 "Request %s from %i",
145 FPMAS_C_STR(node->getId()), node->location());
146
147 requests[node->location()].push_back(node->getId());
148 }
149 }
150 return requests;
151 }
152
153 template<typename T>
155 std::unordered_set<api::graph::DistributedNode<T>*> nodes) {
156 FPMAS_LOGI(
157 graph.getMpiCommunicator().getRank(), "GHOST_MODE",
158 "Synchronizing graph data...", ""
159 );
160
161 std::unordered_map<int, std::vector<DistributedId>> requests
162 = buildRequests(nodes);
163 _synchronize(requests);
164 for(auto node : nodes)
165 node->mutex()->synchronize();
166 }
167
168 template<typename T>
169 std::unordered_map<int, std::vector<DistributedId>> GhostDataSync<T>
171 std::unordered_map<int, std::vector<DistributedId>> requests;
172 for(auto node : graph.getLocationManager().getDistantNodes()) {
173 FPMAS_LOGV(
174 graph.getMpiCommunicator().getRank(), "GHOST_MODE",
175 "Request %s from %i",
176 FPMAS_C_STR(node.first), node.second->location()
177 );
178 requests[node.second->location()].push_back(node.first);
179 }
180 return requests;
181 }
182
183 template<typename T>
185 FPMAS_LOGI(
186 graph.getMpiCommunicator().getRank(), "GHOST_MODE",
187 "Synchronizing graph data...", "");
188
189 std::unordered_map<int, std::vector<DistributedId>> requests
190 = buildRequests();
191 _synchronize(requests);
192 for(auto node : graph.getNodes())
193 node.second->mutex()->synchronize();
194 }
195
196
213 template<typename T>
215 public:
236 private:
237 std::vector<EdgePtr> link_buffer;
238 std::unordered_map<int, std::vector<DistributedId>> unlink_migration;
239 std::unordered_map<int, std::vector<DistributedId>> remove_node_buffer;
240 std::vector<NodeApi*> local_nodes_to_remove;
241
242 EdgeMpi& edge_mpi;
243 IdMpi& id_mpi;
245
246 protected:
251 void synchronize_links();
252
253 public:
263 EdgeMpi& edge_mpi, IdMpi& id_mpi,
265 : edge_mpi(edge_mpi), id_mpi(id_mpi), graph(graph) {}
266
273 void link(EdgeApi* edge) override;
274
284 void unlink(EdgeApi* edge) override;
285
286 void removeNode(NodeApi* node) override;
287 };
288
289 template<typename T>
291 FPMAS_LOGI(graph.getMpiCommunicator().getRank(),
292 "GHOST_MODE", "Synchronizing graph links...", "");
293 /*
294 * Migrate links
295 */
296 std::vector<EdgePtr> edges_to_clear;
297 std::unordered_map<int, std::vector<EdgePtr>> link_migration;
298 for(auto edge : link_buffer) {
299 auto src = edge->getSourceNode();
300 if(src->state() == LocationState::DISTANT) {
301 link_migration[src->location()].push_back(edge);
302 }
303 auto tgt = edge->getTargetNode();
304 if(tgt->state() == LocationState::DISTANT) {
305 link_migration[tgt->location()].push_back(edge);
306 }
307 if(src->state() == LocationState::DISTANT
308 && tgt->state() == LocationState::DISTANT) {
309 edges_to_clear.push_back(edge);
310 }
311 }
312 link_migration = edge_mpi.migrate(link_migration);
313
314 for(auto import_list : link_migration) {
315 for (auto edge : import_list.second) {
316 graph.importEdge(edge);
317 }
318 }
319 link_buffer.clear();
320
321 /*
322 * Migrate node removal
323 */
324 remove_node_buffer = id_mpi.migrate(remove_node_buffer);
325 for(auto import_list : remove_node_buffer) {
326 for(DistributedId node_id : import_list.second) {
327 auto* node = graph.getNode(node_id);
328 for(auto edge : node->getOutgoingEdges())
329 graph.unlink(edge);
330 for(auto edge : node->getIncomingEdges())
331 graph.unlink(edge);
332 }
333 }
334
335 /*
336 * Migrate unlinks
337 */
338 unlink_migration = id_mpi.migrate(unlink_migration);
339 for(auto import_list : unlink_migration) {
340 for(DistributedId id : import_list.second) {
341 if(graph.getEdges().count(id) > 0) {
342 auto edge = graph.getEdge(id);
343 graph.erase(edge);
344 }
345 }
346 }
347 unlink_migration.clear();
348
349 for(auto edge : edges_to_clear)
350 graph.erase(edge);
351
352 for(auto import_list : remove_node_buffer)
353 for(auto node_id : import_list.second)
354 local_nodes_to_remove.push_back(graph.getNode(node_id));
355 remove_node_buffer.clear();
356
357 for(auto node : local_nodes_to_remove) {
358 graph.erase(node);
359 }
360 local_nodes_to_remove.clear();
361
362 FPMAS_LOGI(graph.getMpiCommunicator().getRank(),
363 "GHOST_MODE", "Graph links synchronized.", "");
364 }
365
366 template<typename T>
368 if(edge->state() == LocationState::DISTANT) {
369 link_buffer.push_back(const_cast<EdgeApi*>(edge));
370 }
371 }
372
373 template<typename T>
375 if(edge->state() == LocationState::DISTANT) {
376 link_buffer.erase(
377 std::remove(link_buffer.begin(), link_buffer.end(), edge),
378 link_buffer.end()
379 );
380 auto src = edge->getSourceNode();
381 if(src->state() == LocationState::DISTANT) {
382 unlink_migration[src->location()].push_back(edge->getId());
383 }
384 auto tgt = edge->getTargetNode();
385 if(tgt->state() == LocationState::DISTANT) {
386 unlink_migration[tgt->location()].push_back(edge->getId());
387 }
388 }
389 }
390
391 template<typename T>
393 if(node->state() == LocationState::DISTANT) {
394 remove_node_buffer[node->location()].push_back(node->getId());
395 } else {
396 for(auto edge : node->getOutgoingEdges())
397 graph.unlink(edge);
398 for(auto edge : node->getIncomingEdges())
399 graph.unlink(edge);
400 }
401 local_nodes_to_remove.push_back(node);
402 }
403
413 template<typename T>
415 public:
417
418 void synchronize() override;
419 };
420
421 template<typename T>
423 this->synchronize_links();
424 }
425
448 template<typename T, template<typename> class Mutex>
453
454 GhostDataSync<T> data_sync;
455 GhostSyncLinker<T> sync_linker;
456
457 public:
467 : id_mpi(comm), data_mpi(comm), edge_mpi(comm),
468 data_sync(data_mpi, id_mpi, graph), sync_linker(edge_mpi, id_mpi, graph) {}
469
475 Mutex<T>* buildMutex(api::graph::DistributedNode<T>* node) override {
476 return new Mutex<T>(node->data());
477 };
478
484 GhostDataSync<T>& getDataSync() override {return data_sync;}
485
491 GhostSyncLinker<T>& getSyncLinker() override {return sync_linker;}
492 };
493 }
494
540 template<typename T>
542}}
543#endif
Definition: communication.h:251
Definition: communication.h:637
Definition: distributed_edge.h:91
virtual LocationState state() const =0
Definition: distributed_graph.h:169
Definition: distributed_id.h:89
Definition: distributed_node.h:28
virtual LocationState state() const =0
virtual int location() const =0
virtual IdType getId() const =0
virtual NodeType * getSourceNode() const =0
virtual NodeType * getTargetNode() const =0
virtual const std::vector< EdgeType * > getIncomingEdges() const =0
virtual IdType getId() const =0
virtual const std::vector< EdgeType * > getOutgoingEdges() const =0
Definition: sync_mode.h:26
Definition: sync_mode.h:79
Definition: sync_mode.h:120
Definition: ptr_wrapper.h:21
Definition: ghost_mode.h:45
void synchronize() override
Definition: ghost_mode.h:184
api::communication::TypedMpi< DistributedId > IdMpi
Definition: ghost_mode.h:54
GhostDataSync(DataMpi &data_mpi, IdMpi &id_mpi, api::graph::DistributedGraph< T > &graph)
Definition: ghost_mode.h:78
api::communication::TypedMpi< NodeUpdatePack< T > > DataMpi
Definition: ghost_mode.h:50
Definition: ghost_mode.h:449
GhostDataSync< T > & getDataSync() override
Definition: ghost_mode.h:484
Mutex< T > * buildMutex(api::graph::DistributedNode< T > *node) override
Definition: ghost_mode.h:475
GhostSyncLinker< T > & getSyncLinker() override
Definition: ghost_mode.h:491
GhostMode(api::graph::DistributedGraph< T > &graph, api::communication::MpiCommunicator &comm)
Definition: ghost_mode.h:464
Definition: ghost_mode.h:27
const T & read() override
Definition: ghost_mode.h:31
void synchronize() override
Definition: ghost_mode.h:35
void releaseAcquire() override
Definition: ghost_mode.h:34
void releaseRead() override
Definition: ghost_mode.h:32
T & acquire() override
Definition: ghost_mode.h:33
Definition: ghost_mode.h:214
void unlink(EdgeApi *edge) override
Definition: ghost_mode.h:374
api::communication::TypedMpi< DistributedId > IdMpi
Definition: ghost_mode.h:235
void removeNode(NodeApi *node) override
Definition: ghost_mode.h:392
api::graph::DistributedNode< T > NodeApi
Definition: ghost_mode.h:223
void link(EdgeApi *edge) override
Definition: ghost_mode.h:367
api::utils::PtrWrapper< EdgeApi > EdgePtr
Definition: ghost_mode.h:227
api::graph::DistributedEdge< T > EdgeApi
Definition: ghost_mode.h:219
void synchronize_links()
Definition: ghost_mode.h:290
api::communication::TypedMpi< EdgePtr > EdgeMpi
Definition: ghost_mode.h:231
GhostSyncLinkerBase(EdgeMpi &edge_mpi, IdMpi &id_mpi, api::graph::DistributedGraph< T > &graph)
Definition: ghost_mode.h:262
Definition: ghost_mode.h:414
void synchronize() override
Definition: ghost_mode.h:422
Definition: single_thread_mutex.h:13
T & data() override
Definition: single_thread_mutex.h:29
#define FPMAS_C_STR(arg)
Definition: macros.h:24
LocationState
Definition: location_state.h:15
@ DISTANT
Definition: location_state.h:28
Definition: fpmas.cpp:3
static void update(T &local_data, T &&updated_data)
Definition: synchro.h:31