phdMesh  Version of the Day
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Groups
ParallelComm.hpp
1 /*------------------------------------------------------------------------*/
2 /* phdMesh : Parallel Heterogneous Dynamic unstructured Mesh */
3 /* Copyright (2007) Sandia Corporation */
4 /* */
5 /* Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive */
6 /* license for use of this work by or on behalf of the U.S. Government. */
7 /* */
8 /* This library is free software; you can redistribute it and/or modify */
9 /* it under the terms of the GNU Lesser General Public License as */
10 /* published by the Free Software Foundation; either version 2.1 of the */
11 /* License, or (at your option) any later version. */
12 /* */
13 /* This library is distributed in the hope that it will be useful, */
14 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
15 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
16 /* Lesser General Public License for more details. */
17 /* */
18 /* You should have received a copy of the GNU Lesser General Public */
19 /* License along with this library; if not, write to the Free Software */
20 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 */
21 /* USA */
22 /*------------------------------------------------------------------------*/
28 #ifndef util_ParallelComm_hpp
29 #define util_ParallelComm_hpp
30 
31 #include <cstddef>
32 #include <iosfwd>
33 #include <util/Basics.hpp>
34 #include <util/Parallel.hpp>
35 
36 //------------------------------------------------------------------------
37 
38 namespace phdmesh {
39 
48 class CommAll ;
49 
52 class CommBuffer ;
53 
66 bool comm_sizes( ParallelMachine ,
67  const unsigned num_msg_bound ,
68  unsigned & num_msg_maximum ,
69  const unsigned * const send_size ,
70  unsigned * const recv_size ,
71  bool local_flag = false );
72 
75 bool comm_dense_sizes( ParallelMachine ,
76  const unsigned * const send_size ,
77  unsigned * const recv_size ,
78  bool local_flag = false );
79 
80 //------------------------------------------------------------------------
81 
82 class CommBuffer {
83 public:
84 
86  template<typename T> void pack( const T & value );
87 
89  template<typename T> void pack( const T * value , size_t number );
90 
92  template<typename T> void unpack( T & value );
93 
95  template<typename T> void unpack( T * value , size_t number );
96 
98  template<typename T> void peek( T & value );
99 
101  template<typename T> void peek( T * value , size_t number );
102 
104  template<typename T> void skip( size_t number );
105 
107  void reset();
108 
112  size_t capacity() const ;
113 
118  size_t size() const ;
119 
126  ptrdiff_t remaining() const ;
127 
129  void * buffer() const ;
130 
131  ~CommBuffer();
132  CommBuffer();
133 
134 private:
135  friend class CommAll ;
136  friend class CommGather ;
137  friend class CommBroadcast ;
138 
139  static CommBuffer * allocate( const unsigned, const unsigned * const );
140  static void deallocate( const unsigned , CommBuffer * );
141 
142  void pack_overflow() const ;
143  void unpack_overflow() const ;
144 
145  CommBuffer( const CommBuffer & );
146  CommBuffer & operator = ( const CommBuffer & );
147 
148  typedef unsigned char * ucharp ;
149 
150  ucharp m_beg ;
151  ucharp m_ptr ;
152  ucharp m_end ;
153 };
154 
155 //------------------------------------------------------------------------
156 
157 class CommAll {
158 public:
159 
160  ParallelMachine parallel() const { return m_comm ; }
161  unsigned parallel_size() const { return m_size ; }
162  unsigned parallel_rank() const { return m_rank ; }
163 
165  CommBuffer & send_buffer( unsigned ) const ;
166 
168  CommBuffer & recv_buffer( unsigned ) const ;
169 
170  //----------------------------------------
174  CommAll();
175 
183  bool allocate_buffers( ParallelMachine ,
184  const unsigned num_msg_bounds ,
185  const unsigned * const send_size ,
186  const unsigned * const recv_size ,
187  const bool local_flag = false );
188 
189  //----------------------------------------
202  explicit CommAll( ParallelMachine );
203 
210  bool allocate_buffers( const unsigned num_msg_bounds ,
211  const bool symmetric = false ,
212  const bool local_flag = false );
213 
214  //----------------------------------------
216  void communicate();
217 
218  //----------------------------------------
220  void swap_send_recv();
221 
225  void reset_buffers();
226 
227  ~CommAll();
228 
229 private:
230 
231  CommAll( const CommAll & );
232  CommAll & operator = ( const CommAll & );
233 
234  void rank_error( const char * , unsigned ) const ;
235 
236  bool allocate_buffers( const unsigned * const send_size ,
237  const unsigned * const recv_size ,
238  bool local_flag );
239 
240  ParallelMachine m_comm ;
241  unsigned m_size ;
242  unsigned m_rank ;
243  unsigned m_bound ;
244  unsigned m_max ;
245  CommBuffer * m_send ;
246  CommBuffer * m_recv ;
247 };
248 
249 //------------------------------------------------------------------------
250 
251 class CommBroadcast {
252 public:
253 
254  ParallelMachine parallel() const { return m_comm ; }
255  unsigned parallel_size() const { return m_size ; }
256  unsigned parallel_rank() const { return m_rank ; }
257 
259  CommBuffer & send_buffer();
260 
262  CommBuffer & recv_buffer();
263 
264  //----------------------------------------
265 
266  CommBroadcast( ParallelMachine , unsigned root_rank );
267 
268  void communicate();
269 
270  bool allocate_buffer( const bool local_flag = false );
271 
272  ~CommBroadcast();
273 
274 private:
275 
276  CommBroadcast();
277  CommBroadcast( const CommBroadcast & );
278  CommBroadcast & operator = ( const CommBroadcast & );
279 
280  ParallelMachine m_comm ;
281  unsigned m_size ;
282  unsigned m_rank ;
283  unsigned m_root_rank ;
284  CommBuffer m_buffer ;
285 };
286 
287 //----------------------------------------------------------------------
288 
289 class CommGather {
290 public:
291 
292  ParallelMachine parallel() const { return m_comm ; }
293  unsigned parallel_size() const { return m_size ; }
294  unsigned parallel_rank() const { return m_rank ; }
295 
296  ~CommGather();
297 
298  CommGather( ParallelMachine , unsigned root_rank , unsigned send_size );
299 
300  CommBuffer & send_buffer() { return m_send ; }
301 
302  void communicate();
303 
304  CommBuffer & recv_buffer( unsigned );
305 
306  void reset();
307 
308 private:
309 
310  CommGather();
311  CommGather( const CommBroadcast & );
312  CommGather & operator = ( const CommBroadcast & );
313 
314  ParallelMachine m_comm ;
315  unsigned m_size ;
316  unsigned m_rank ;
317  unsigned m_root_rank ;
318  CommBuffer m_send ;
319  CommBuffer * m_recv ;
320  int * m_recv_count ;
321  int * m_recv_displ ;
322 };
323 
324 }
325 
326 //----------------------------------------------------------------------
327 //----------------------------------------------------------------------
328 // Inlined template implementations for the CommBuffer
329 
330 namespace phdmesh {
331 
332 template<unsigned N> struct CommBufferAlign ;
333 
334 template<>
335 struct CommBufferAlign<1> {
336  static size_t align( size_t ) { return 0 ; }
337 };
338 
339 template<unsigned N>
340 struct CommBufferAlign {
341  static size_t align( size_t i ) { i %= N ; return i ? ( N - i ) : 0 ; }
342 };
343 
344 template<typename T>
345 inline
346 void CommBuffer::pack( const T & value )
347 {
348  enum { Size = sizeof(T) };
349  size_t nalign = CommBufferAlign<Size>::align( m_ptr - m_beg );
350  if ( m_beg ) {
351  if ( m_end < m_ptr + nalign + Size ) { pack_overflow(); }
352  while ( nalign ) { --nalign ; *m_ptr = 0 ; ++m_ptr ; }
353  T * tmp = reinterpret_cast<T*>(m_ptr);
354  *tmp = value ;
355  m_ptr = reinterpret_cast<ucharp>( ++tmp );
356  }
357  else {
358  m_ptr += nalign + Size ;
359  }
360 }
361 
362 template<typename T>
363 inline
364 void CommBuffer::pack( const T * value , size_t number )
365 {
366  enum { Size = sizeof(T) };
367  size_t nalign = CommBufferAlign<Size>::align( m_ptr - m_beg );
368  if ( m_beg ) {
369  if ( m_end < m_ptr + nalign + number * Size ) { pack_overflow(); }
370  while ( nalign ) { --nalign ; *m_ptr = 0 ; ++m_ptr ; }
371  T * tmp = reinterpret_cast<T*>(m_ptr);
372  while ( number ) { --number ; *tmp = *value ; ++tmp ; ++value ; }
373  m_ptr = reinterpret_cast<ucharp>( tmp );
374  }
375  else {
376  m_ptr += nalign + number * Size ;
377  }
378 }
379 
380 template<typename T>
381 inline
382 void CommBuffer::skip( size_t number )
383 {
384  enum { Size = sizeof(T) };
385  m_ptr += CommBufferAlign<Size>::align( m_ptr - m_beg ) + Size * number ;
386  if ( m_beg && m_end < m_ptr ) { unpack_overflow(); }
387 }
388 
389 template<typename T>
390 inline
391 void CommBuffer::unpack( T & value )
392 {
393  enum { Size = sizeof(T) };
394  const size_t nalign = CommBufferAlign<Size>::align( m_ptr - m_beg );
395  T * tmp = reinterpret_cast<T*>( m_ptr + nalign );
396  value = *tmp ;
397  m_ptr = reinterpret_cast<ucharp>( ++tmp );
398  if ( m_end < m_ptr ) { unpack_overflow(); }
399 }
400 
401 template<typename T>
402 inline
403 void CommBuffer::unpack( T * value , size_t number )
404 {
405  enum { Size = sizeof(T) };
406  const size_t nalign = CommBufferAlign<Size>::align( m_ptr - m_beg );
407  T * tmp = reinterpret_cast<T*>( m_ptr + nalign );
408  while ( number ) { --number ; *value = *tmp ; ++tmp ; ++value ; }
409  m_ptr = reinterpret_cast<ucharp>( tmp );
410  if ( m_end < m_ptr ) { unpack_overflow(); }
411 }
412 
413 template<typename T>
414 inline
415 void CommBuffer::peek( T & value )
416 {
417  enum { Size = sizeof(T) };
418  const size_t nalign = CommBufferAlign<Size>::align( m_ptr - m_beg );
419  T * tmp = reinterpret_cast<T*>( m_ptr + nalign );
420  value = *tmp ;
421  if ( m_end < reinterpret_cast<ucharp>(++tmp) ) { unpack_overflow(); }
422 }
423 
424 template<typename T>
425 inline
426 void CommBuffer::peek( T * value , size_t number )
427 {
428  enum { Size = sizeof(T) };
429  const size_t nalign = CommBufferAlign<Size>::align( m_ptr - m_beg );
430  T * tmp = reinterpret_cast<T*>( m_ptr + nalign );
431  while ( number ) { --number ; *value = *tmp ; ++tmp ; ++value ; }
432  if ( m_end < reinterpret_cast<ucharp>(tmp) ) { unpack_overflow(); }
433 }
434 
435 inline
436 void CommBuffer::reset()
437 { m_ptr = m_beg ; }
438 
439 inline
440 size_t CommBuffer::capacity() const
441 { return m_end - m_beg ; }
442 
443 inline
444 size_t CommBuffer::size() const
445 { return m_ptr - m_beg ; }
446 
447 inline
448 ptrdiff_t CommBuffer::remaining() const
449 { return m_end - m_ptr ; }
450 
451 inline
452 void * CommBuffer::buffer() const
453 { return static_cast<void*>( m_beg ); }
454 
455 //----------------------------------------------------------------------
456 // Inline implementations for the CommAll
457 
458 inline
459 CommBuffer & CommAll::send_buffer( unsigned p ) const
460 {
461  if ( m_size <= p ) { rank_error("send_buffer",p); }
462  return m_send[p] ;
463 }
464 
465 inline
466 CommBuffer & CommAll::recv_buffer( unsigned p ) const
467 {
468  if ( m_size <= p ) { rank_error("recv_buffer",p); }
469  return m_recv[p] ;
470 }
471 
472 }
473 
474 //----------------------------------------------------------------------
475 //----------------------------------------------------------------------
476 
477 #endif
478 
bool comm_dense_sizes(ParallelMachine, const unsigned *const send_size, unsigned *const recv_size, bool local_flag=false)
bool comm_sizes(ParallelMachine, const unsigned num_msg_bound, unsigned &num_msg_maximum, const unsigned *const send_size, unsigned *const recv_size, bool local_flag=false)