HavoqGT
visitor_queue.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013, Lawrence Livermore National Security, LLC.
3  * Produced at the Lawrence Livermore National Laboratory.
4  * Written by Roger Pearce <rpearce@llnl.gov>.
5  * LLNL-CODE-644630.
6  * All rights reserved.
7  *
8  * This file is part of HavoqGT, Version 0.1.
9  * For details, see https://computation.llnl.gov/casc/dcca-pub/dcca/Downloads.html
10  *
11  * Please also read this link – Our Notice and GNU Lesser General Public License.
12  * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
13  *
14  * This program is free software; you can redistribute it and/or modify it under
15  * the terms of the GNU Lesser General Public License (as published by the Free
16  * Software Foundation) version 2.1 dated February 1999.
17  *
18  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
19  * WARRANTY; without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A
20  * PARTICULAR PURPOSE. See the terms and conditions of the GNU General Public
21  * License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public License along
24  * with this program; if not, write to the Free Software Foundation, Inc.,
25  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26  *
27  * OUR NOTICE AND TERMS AND CONDITIONS OF THE GNU GENERAL PUBLIC LICENSE
28  *
29  * Our Preamble Notice
30  *
31  * A. This notice is required to be provided under our contract with the
32  * U.S. Department of Energy (DOE). This work was produced at the Lawrence
33  * Livermore National Laboratory under Contract No. DE-AC52-07NA27344 with the DOE.
34  *
35  * B. Neither the United States Government nor Lawrence Livermore National
36  * Security, LLC nor any of their employees, makes any warranty, express or
37  * implied, or assumes any liability or responsibility for the accuracy,
38  * completeness, or usefulness of any information, apparatus, product, or process
39  * disclosed, or represents that its use would not infringe privately-owned rights.
40  *
41  * C. Also, reference herein to any specific commercial products, process, or
42  * services by trade name, trademark, manufacturer or otherwise does not
43  * necessarily constitute or imply its endorsement, recommendation, or favoring by
44  * the United States Government or Lawrence Livermore National Security, LLC. The
45  * views and opinions of authors expressed herein do not necessarily state or
46  * reflect those of the United States Government or Lawrence Livermore National
47  * Security, LLC, and shall not be used for advertising or product endorsement
48  * purposes.
49  *
50  */
51 
52 #ifndef HAVOQGT_MPI_VISITOR_QUEUE_HPP_INCLUDED
53 #define HAVOQGT_MPI_VISITOR_QUEUE_HPP_INCLUDED
54 
55 #include <havoqgt/mailbox.hpp>
58 #include <vector>
59 #include <iterator>
60 #include <sched.h>
61 
62 namespace havoqgt { namespace mpi {
63 
65 class el_partitioned_t { };
66 
67 template <typename TVisitor, template<typename T> class Queue, typename TGraph>
69  typedef TVisitor visitor_type;
70 
72  typedef TGraph graph_type;
73  typedef typename TGraph::vertex_locator vertex_locator;
74  //typedef typename havoqgt::detail::reservable_priority_queue<visitor_type,
75  // std::vector<visitor_type>, std::greater<visitor_type> > local_queue_type;
76  typedef Queue<visitor_type> local_queue_type;
77 
78  struct visitor_wrapper {
79  uint32_t dest() const { return m_visitor.vertex.owner(); }
80  uint32_t get_bcast() const { return m_visitor.vertex.get_bcast(); }
81  void set_bcast(uint32_t bcast) {m_visitor.vertex.set_bcast(bcast); }
82  void set_dest(uint32_t dest) {m_visitor.vertex.set_dest(dest); }
83  bool is_intercept() const { return m_visitor.vertex.is_intercept(); }
84  void set_intercept(bool intercept) {m_visitor.vertex.set_intercept(intercept); }
85  TVisitor m_visitor;
86  };
87 
88 #ifdef __bgp__
89  typedef mailbox_bgp_torus<visitor_wrapper> mailbox_type;
90 #else
92 #endif
93 
94 
95 public:
96  visitor_queue(TGraph* _graph)
97  : m_mailbox(MPI_COMM_WORLD, 0)
98  , m_termination_detection(MPI_COMM_WORLD, 2, 2, 3, 4)
99  , m_ptr_graph(_graph) {
100  //m_localqueue_owned.reserve(_graph->num_local_vertices());
101  //m_localqueue_delegates.reserve(_graph->num_delegates() * 4);
102  }
103 
105  // if(m_mailbox.comm_rank() == 0) {
106  // std::cout << "*************** Visitor Queue Statistics *****************" << std::endl;
107  // std::cout << "m_localqueue_owned.reserve = " << m_ptr_graph->num_local_vertices() << std::endl;
108  // std::cout << "m_localqueue_owned.capacity = " << m_localqueue_owned.capacity() << std::endl;
109  // std::cout << "m_localqueue_delegates.reserve = " << 0/*m_ptr_graph->num_delegates()*/ << std::endl;
110  // std::cout << "m_localqueue_delegates.capacity = " << m_localqueue_delegates.capacity() << std::endl;
111  // std::cout << "***********************************************************" << std::endl;
112  // }
113  }
114 
116  : public std::iterator<std::output_iterator_tag, void, void, void, void> {
117  public:
120  m_vq->handle_mailbox_receive(__value);
121  return *this;
122  }
123 
124  bool intercept(const visitor_wrapper& __value) {
125  assert(m_vq->m_ptr_graph->master(__value.m_visitor.vertex) != uint32_t(m_vq->m_mailbox.comm_rank()));
126  bool ret = __value.m_visitor.pre_visit();
127  if(!ret) {
129  }
130  return ret;
131  }
132 
136  { return *this; }
137 
141  { return *this; }
142 
146  { return *this; }
147 
148  private:
150  };
151 
152  void init_visitor_traversal(vertex_locator _source_v) {
153  if(0 /*_source_v.owner()*/ == m_mailbox.comm_rank()) {
154  queue_visitor(visitor_type(_source_v));
155  }
156  do {
157  do {
159  while(!empty()) {
161  visitor_type this_visitor = pop_top();
162  vertex_locator v = this_visitor.vertex;
163  bool ret = this_visitor.visit(*m_ptr_graph, this);
164  if(ret && v.is_delegate() && m_ptr_graph->master(v) == m_mailbox.comm_rank()) {
165  visitor_wrapper vw;
166  vw.m_visitor = this_visitor;
167  vw.set_bcast(true);
170  }
172  }
174  } while(!m_local_controller_queue.empty() || !m_mailbox.is_idle() );
175  sched_yield();
177  }
178 
179 
180  void do_visit(visitor_type& this_visitor) {
181  vertex_locator v = this_visitor.vertex;
182  bool ret = this_visitor.visit(*m_ptr_graph, this);
183  if(ret && v.is_delegate() && m_ptr_graph->master(v) == m_mailbox.comm_rank()) {
184  visitor_wrapper vw;
185  vw.m_visitor = this_visitor;
186  vw.set_bcast(true);
189  }
190  }
191 
193  typename TGraph::controller_iterator citr = m_ptr_graph->controller_begin();
194  for(; citr != m_ptr_graph->controller_end(); ++citr) {
195  visitor_type v(*citr);
196  if(v.pre_visit()) { //RECENTLY ADDED 2013.10.10
197  do_visit( v );
198  check_mailbox();
199  }
200  }
201  typename TGraph::vertex_iterator vitr = m_ptr_graph->vertices_begin();
202  for(; vitr != m_ptr_graph->vertices_end(); ++vitr) {
203  visitor_type v(*vitr);
204  if(v.pre_visit()) { //RECENTLY ADDED 2013.10.10
205  do_visit( v );
206  check_mailbox();
207  }
208  }
209  do {
210  do {
212  while(!empty()) {
214  visitor_type this_visitor = pop_top();
215  do_visit(this_visitor);
217  }
219  } while(!m_local_controller_queue.empty() || !m_mailbox.is_idle() );
221  }
222 
223  void queue_visitor(const visitor_type& v) {
224  if(v.vertex.is_delegate()) {
226  } else {
227  if(v.vertex.owner() == uint32_t(m_mailbox.comm_rank())) {
228  if(v.pre_visit()) {
229  push(v);
231  }
232  } else {
233  visitor_wrapper vw;
234  //vw.m_dest = v.vertex.owner();
235  vw.m_visitor = v;
236  m_mailbox.send(v.vertex.owner(), vw, visitor_queue_inserter(this));
238  }
239  }
240  }
241 
242 private:
243  // This occurs when the local process first encounters a delegate
244  void local_delegate_visit(const visitor_type& v) {
245  if(v.pre_visit()) {
246  if(m_ptr_graph->master(v.vertex) == uint32_t(m_mailbox.comm_rank())) {
247  //delegate_bcast(v);
248  push(v);
250  /* THIS was working, but trying to change how delegates are bcast from the master
251  visitor_wrapper vw;
252  vw.m_visitor = v;
253  vw.set_bcast(true);
254  m_mailbox.bcast(vw, visitor_queue_inserter(this));
255  m_termination_detection.inc_queued(m_mailbox.comm_size());*/
256  } else { //send interceptable to parent
257  visitor_wrapper vw;
258  vw.m_visitor = v;
259  vw.set_intercept(true);
260  uint32_t master_rank = m_ptr_graph->master(v.vertex);
261  vw.set_dest(master_rank);
262  m_mailbox.send(master_rank, vw, visitor_queue_inserter(this));
263  //delegate_parent(v);
265  }
266  }
267  }
268 
269  /*oid delegate_parent(const visitor_type& v) {
270  uint64_t parent = offset_tree_parent(m_mailbox.comm_size(), 2, m_ptr_graph->master(v.vertex),
271  m_mailbox.comm_rank());
272  visitor_wrapper vw;
273  vw.m_visitor = v;
274  vw.m_visitor.vertex.set_dest(parent);
275  m_mailbox.send(parent, vw, visitor_queue_inserter(this));
276  }*/
277 
278 
279  /*void delegate_bcast(const visitor_type& v) {
280  uint32_t root = m_ptr_graph->master(v.vertex);
281  uint32_t num_bcast_children = offset_tree_num_children(m_mailbox.comm_size(),
282  2, root,
283  m_mailbox.comm_rank());
284  if(num_bcast_children > 0) {
285  uint32_t first_bcast_child = offset_tree_first_child(m_mailbox.comm_size(),
286  2, root,
287  m_mailbox.comm_rank());
288  for(uint32_t i=0; i<num_bcast_children; ++i) {
289  uint32_t child = (first_bcast_child + i)%m_mailbox.comm_size();
290  visitor_wrapper vw;
291  vw.m_visitor = v;
292  vw.m_visitor.vertex.set_dest(child);
293  vw.m_visitor.vertex.set_bcast(true);
294  m_mailbox.send(child, vw, visitor_queue_inserter(this));
295  }
296  }
297  }*/
298 
300  {
301  while(!m_local_controller_queue.empty()) {
302  TVisitor v = m_local_controller_queue.front();
304  v.visit(*m_ptr_graph, this);
306  }
307  }
308 
310  if(vw.m_visitor.vertex.is_delegate()) {
311  if(vw.m_visitor.vertex.get_bcast()) {
312  //delegate_bcast(vw.m_visitor);
313  if(m_ptr_graph->master(vw.m_visitor.vertex) == uint32_t(m_mailbox.comm_rank())) {
314  //This is because the mailbox bcast returns to self -- this should be fixed!
316  } else {
317  //vw.m_visitor.pre_visit();
318  //push(vw.m_visitor);
319  /* 2013.10.11 -- this causes too much recursion in mailbox, trying something new....
320  vw.m_visitor.visit(*m_ptr_graph, this);
321  m_termination_detection.inc_completed();
322  */
324  }
325  } else {
326  assert(m_ptr_graph->master(vw.m_visitor.vertex) == uint32_t(m_mailbox.comm_rank()));
327  if(vw.m_visitor.pre_visit()) {
328  //if(m_ptr_graph->master(vw.m_visitor.vertex) == m_mailbox.comm_rank()) {
329  //delegate_bcast(vw.m_visitor);
330  push(vw.m_visitor);
331  /* This was working, trying new way for master bcast
332  vw.set_bcast(true);
333  vw.set_intercept(false);
334  m_mailbox.bcast(vw, visitor_queue_inserter(this));
335  m_termination_detection.inc_queued(m_mailbox.comm_size());*/
336  //} else {
337  // delegate_parent(vw.m_visitor);
338  //}
339  } else {
341  }
342  }
343  } else {
344  assert(vw.m_visitor.vertex.owner() == uint32_t(m_mailbox.comm_rank()));
345  //
346  // Now handle owned vertices
347  if(vw.m_visitor.pre_visit()) {
348  push(vw.m_visitor);
349  } else {
351  }
352  }
353  }
354 
355  void push(const visitor_type& v) {
356  /*if(v.vertex.is_delegate()) {
357  m_localqueue_delegates.push(v);
358  } else {
359  m_localqueue_owned.push(v);
360  }*/
361  m_localqueue_owned.push(v);
362  }
363 
364  visitor_type pop_top() {
365  check_mailbox();
366  visitor_type to_return;
367  assert(!(m_localqueue_delegates.empty() && m_localqueue_owned.empty()));
368 
369  /*if(m_localqueue_delegates.empty()) {
370  to_return = m_localqueue_owned.top();
371  m_localqueue_owned.pop();
372  } else {
373  if(m_localqueue_owned.empty()) {
374  to_return = m_localqueue_delegates.top();
375  m_localqueue_delegates.pop();
376  } else {
377  if(m_localqueue_delegates.top() < m_localqueue_owned.top()) {
378  to_return = m_localqueue_delegates.top();
379  m_localqueue_delegates.pop();
380  } else {
381  to_return = m_localqueue_owned.top();
382  m_localqueue_owned.pop();
383  }
384  }
385  }*/
386  to_return = m_localqueue_owned.top(); m_localqueue_owned.pop();
387  return to_return;
388  }
389 
390 
391  void check_mailbox() {
393  }
394 
395  bool empty() {
396  if(m_localqueue_owned.empty() && m_localqueue_delegates.empty()) {
397  check_mailbox();
398  }
399  return m_localqueue_owned.empty() && m_localqueue_delegates.empty();
400  }
401 
402 /* void init_visitor_traversal() {
403  typedef typename graph_type::vertex_iterator vitr_type;
404  std::pair< vitr_type, vitr_type > vitr = vertices(*m_ptr_graph);
405 
406  do {
407  do {
408  do {
409  if(vitr.first != vitr.second) {
410  uint64_t sampled_vertex = *(vitr.first);
411  uint64_t my_rank = m_mailbox.comm_rank();
412  if(m_ptr_graph->is_local(vertex(sampled_vertex, *m_ptr_graph))) {
413  sampled_vertex |= (my_rank << owner_shift);
414  queue_visitor( visitor_type( sampled_vertex ) );
415  }
416  ++vitr.first;
417  }
418  while(!empty()) {
419  visitor_type this_visitor = top(); pop();
420  vertex_locator v = this_visitor.vertex;
421  this_visitor.visit((*m_ptr_graph)[v], *m_ptr_graph, this);
422  m_termination_detection.inc_completed();
423  }
424  } while( vitr.first != vitr.second);
425  m_mailbox.flush_buffers_if_idle();
426  } while(!m_mailbox.is_idle() );
427  } while(!m_termination_detection.test_for_termination());
428  }*/
429 
430 
431 
432 
433 
434  mailbox_type m_mailbox;
435  termination_detection_type m_termination_detection;
436  local_queue_type m_localqueue_owned;
437  local_queue_type m_localqueue_delegates;
438  TGraph* m_ptr_graph;
439  std::queue<TVisitor> m_local_controller_queue;
440 };
441 
442 
443 }} //namespace havoqgt::mpi
444 
445 #endif //HAVOQGT_MPI_VISITOR_QUEUE_HPP_INCLUDED
termination_detection< uint64_t > termination_detection_type
void receive(OutputIterator _oitr, bool aggregsive=false)
Definition: mailbox.hpp:364
std::queue< TVisitor > m_local_controller_queue
visitor_queue_inserter & operator++()
Simply returns *this. (This iterator does not "move".)
TGraph::vertex_locator vertex_locator
Queue< visitor_type > local_queue_type
void queue_visitor(const visitor_type &v)
mailbox_routed< visitor_wrapper > mailbox_type
void local_delegate_visit(const visitor_type &v)
void do_visit(visitor_type &this_visitor)
void bcast(TMsg _raw_msg, OutputIterator _oitr)
Definition: mailbox.hpp:288
visitor_queue_inserter & operator=(const visitor_wrapper &__value)
local_queue_type m_localqueue_delegates
void handle_mailbox_receive(visitor_wrapper vw)
visitor_queue_inserter & operator*()
Simply returns *this.
bool intercept(const visitor_wrapper &__value)
void send(int raw_dest, const TMsg &_raw_msg, OutputIterator _oitr, bool fast=true)
Definition: mailbox.hpp:330
void init_visitor_traversal(vertex_locator _source_v)
termination_detection_type m_termination_detection
visitor_queue_inserter operator++(int)
Simply returns *this. (This iterator does not "move".)
local_queue_type m_localqueue_owned
void push(const visitor_type &v)