28 #ifndef util_ParallelComm_hpp 
   29 #define util_ParallelComm_hpp 
   33 #include <util/Basics.hpp> 
   34 #include <util/Parallel.hpp> 
   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 );
 
   76                        const unsigned * 
const send_size ,
 
   77                              unsigned * 
const recv_size ,
 
   78                        bool local_flag = 
false );
 
   86   template<
typename T> 
void pack( 
const T & value );
 
   89   template<
typename T> 
void pack( 
const T * value , 
size_t number );
 
   92   template<
typename T> 
void unpack( T & value );
 
   95   template<
typename T> 
void unpack( T * value , 
size_t number );
 
   98   template<
typename T> 
void peek( T & value );
 
  101   template<
typename T> 
void peek( T * value , 
size_t number );
 
  104   template<
typename T> 
void skip( 
size_t number );
 
  112   size_t capacity() 
const ;
 
  118   size_t size() 
const ;
 
  126   ptrdiff_t remaining() 
const ;
 
  129   void * buffer() 
const ;
 
  135   friend class CommAll ;
 
  136   friend class CommGather ;
 
  137   friend class CommBroadcast ;
 
  139   static CommBuffer * allocate( 
const unsigned, 
const unsigned * 
const );
 
  140   static void deallocate( 
const unsigned , CommBuffer * );
 
  142   void pack_overflow() 
const ;
 
  143   void unpack_overflow() 
const ;
 
  145   CommBuffer( 
const CommBuffer & );
 
  146   CommBuffer & operator = ( 
const CommBuffer & );
 
  148   typedef unsigned char * ucharp ;
 
  160   ParallelMachine parallel()
      const { 
return m_comm ; }
 
  161   unsigned        parallel_size()
 const { 
return m_size ; }
 
  162   unsigned        parallel_rank()
 const { 
return m_rank ; }
 
  165   CommBuffer & send_buffer( 
unsigned ) 
const ;
 
  168   CommBuffer & recv_buffer( 
unsigned ) 
const ;
 
  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 );
 
  202   explicit CommAll( ParallelMachine );
 
  210   bool allocate_buffers( 
const unsigned num_msg_bounds ,
 
  211                          const bool symmetric = 
false ,
 
  212                          const bool local_flag = 
false );
 
  220   void swap_send_recv();
 
  225   void reset_buffers();
 
  231   CommAll( 
const CommAll & );
 
  232   CommAll & operator = ( 
const CommAll & );
 
  234   void rank_error( 
const char * , 
unsigned ) 
const ;
 
  236   bool allocate_buffers( 
const unsigned * 
const send_size ,
 
  237                          const unsigned * 
const recv_size ,
 
  240   ParallelMachine m_comm ;
 
  245   CommBuffer    * m_send ;
 
  246   CommBuffer    * m_recv ;
 
  251 class CommBroadcast {
 
  254   ParallelMachine parallel()
      const { 
return m_comm ; }
 
  255   unsigned        parallel_size()
 const { 
return m_size ; }
 
  256   unsigned        parallel_rank()
 const { 
return m_rank ; }
 
  259   CommBuffer & send_buffer();
 
  262   CommBuffer & recv_buffer();
 
  266   CommBroadcast( ParallelMachine , 
unsigned root_rank );
 
  270   bool allocate_buffer( 
const bool local_flag = 
false );
 
  277   CommBroadcast( 
const CommBroadcast & );
 
  278   CommBroadcast & operator = ( 
const CommBroadcast & );
 
  280   ParallelMachine m_comm ;
 
  283   unsigned        m_root_rank ;
 
  284   CommBuffer      m_buffer ;
 
  292   ParallelMachine parallel()
      const { 
return m_comm ; }
 
  293   unsigned        parallel_size()
 const { 
return m_size ; }
 
  294   unsigned        parallel_rank()
 const { 
return m_rank ; }
 
  298   CommGather( ParallelMachine , 
unsigned root_rank , 
unsigned send_size );
 
  300   CommBuffer & send_buffer() { 
return m_send ; }
 
  304   CommBuffer & recv_buffer( 
unsigned );
 
  311   CommGather( 
const CommBroadcast & );
 
  312   CommGather & operator = ( 
const CommBroadcast & );
 
  314   ParallelMachine m_comm ;
 
  317   unsigned        m_root_rank ;
 
  319   CommBuffer    * m_recv ;
 
  332 template<
unsigned N> 
struct CommBufferAlign ;
 
  335 struct CommBufferAlign<1> {
 
  336   static size_t align( 
size_t ) { 
return 0 ; }
 
  340 struct CommBufferAlign {
 
  341   static size_t align( 
size_t i ) { i %= N ; 
return i ? ( N - i ) : 0 ; }
 
  346 void CommBuffer::pack( 
const T & value )
 
  348   enum { Size = 
sizeof(T) };
 
  349   size_t nalign = CommBufferAlign<Size>::align( m_ptr - 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);
 
  355     m_ptr = 
reinterpret_cast<ucharp
>( ++tmp );
 
  358     m_ptr += nalign + Size ;
 
  364 void CommBuffer::pack( 
const T * value , 
size_t number )
 
  366   enum { Size = 
sizeof(T) };
 
  367   size_t nalign = CommBufferAlign<Size>::align( m_ptr - 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 );
 
  376     m_ptr += nalign + number * Size ;
 
  382 void CommBuffer::skip( 
size_t number )
 
  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(); }
 
  391 void CommBuffer::unpack( T & value )
 
  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 );
 
  397   m_ptr = 
reinterpret_cast<ucharp
>( ++tmp );
 
  398   if ( m_end < m_ptr ) { unpack_overflow(); }
 
  403 void CommBuffer::unpack( T * value , 
size_t number )
 
  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(); }
 
  415 void CommBuffer::peek( T & value )
 
  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 );
 
  421   if ( m_end < reinterpret_cast<ucharp>(++tmp) ) { unpack_overflow(); }
 
  426 void CommBuffer::peek( T * value , 
size_t number )
 
  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(); }
 
  436 void CommBuffer::reset()
 
  440 size_t CommBuffer::capacity()
 const 
  441 { 
return m_end - m_beg ; }
 
  444 size_t CommBuffer::size()
 const 
  445 { 
return m_ptr - m_beg ; }
 
  448 ptrdiff_t CommBuffer::remaining()
 const 
  449 { 
return m_end - m_ptr ; }
 
  452 void * CommBuffer::buffer()
 const 
  453 { 
return static_cast<void*
>( m_beg ); }
 
  459 CommBuffer & CommAll::send_buffer( 
unsigned p )
 const 
  461   if ( m_size <= p ) { rank_error(
"send_buffer",p); }
 
  466 CommBuffer & CommAll::recv_buffer( 
unsigned p )
 const 
  468   if ( m_size <= p ) { rank_error(
"recv_buffer",p); }
 
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)