00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00028 #ifndef util_ParallelComm_hpp
00029 #define util_ParallelComm_hpp
00030
00031 #include <cstddef>
00032 #include <iosfwd>
00033 #include <util/Basics.hpp>
00034 #include <util/Parallel.hpp>
00035
00036
00037
00038 namespace phdmesh {
00039
00048 class CommAll ;
00049
00052 class CommBuffer ;
00053
00066 bool comm_sizes( ParallelMachine ,
00067 const unsigned num_msg_bound ,
00068 unsigned & num_msg_maximum ,
00069 const unsigned * const send_size ,
00070 unsigned * const recv_size ,
00071 bool local_flag = false );
00072
00075 bool comm_dense_sizes( ParallelMachine ,
00076 const unsigned * const send_size ,
00077 unsigned * const recv_size ,
00078 bool local_flag = false );
00079
00080
00081
00082 class CommBuffer {
00083 public:
00084
00086 template<typename T> void pack( const T & value );
00087
00089 template<typename T> void pack( const T * value , size_t number );
00090
00092 template<typename T> void unpack( T & value );
00093
00095 template<typename T> void unpack( T * value , size_t number );
00096
00098 template<typename T> void peek( T & value );
00099
00101 template<typename T> void peek( T * value , size_t number );
00102
00104 template<typename T> void skip( size_t number );
00105
00107 void reset();
00108
00112 size_t capacity() const ;
00113
00118 size_t size() const ;
00119
00126 ptrdiff_t remaining() const ;
00127
00129 void * buffer() const ;
00130
00131 ~CommBuffer();
00132 CommBuffer();
00133
00134 private:
00135 friend class CommAll ;
00136 friend class CommGather ;
00137 friend class CommBroadcast ;
00138
00139 static CommBuffer * allocate( const unsigned, const unsigned * const );
00140 static void deallocate( const unsigned , CommBuffer * );
00141
00142 void pack_overflow() const ;
00143 void unpack_overflow() const ;
00144
00145 CommBuffer( const CommBuffer & );
00146 CommBuffer & operator = ( const CommBuffer & );
00147
00148 typedef unsigned char * ucharp ;
00149
00150 ucharp m_beg ;
00151 ucharp m_ptr ;
00152 ucharp m_end ;
00153 };
00154
00155
00156
00157 class CommAll {
00158 public:
00159
00160 ParallelMachine parallel() const { return m_comm ; }
00161 unsigned parallel_size() const { return m_size ; }
00162 unsigned parallel_rank() const { return m_rank ; }
00163
00165 CommBuffer & send_buffer( unsigned ) const ;
00166
00168 CommBuffer & recv_buffer( unsigned ) const ;
00169
00170
00174 CommAll();
00175
00183 bool allocate_buffers( ParallelMachine ,
00184 const unsigned num_msg_bounds ,
00185 const unsigned * const send_size ,
00186 const unsigned * const recv_size ,
00187 const bool local_flag = false );
00188
00189
00202 explicit CommAll( ParallelMachine );
00203
00210 bool allocate_buffers( const unsigned num_msg_bounds ,
00211 const bool symmetric = false ,
00212 const bool local_flag = false );
00213
00214
00216 void communicate();
00217
00218
00220 void swap_send_recv();
00221
00225 void reset_buffers();
00226
00227 ~CommAll();
00228
00229 private:
00230
00231 CommAll( const CommAll & );
00232 CommAll & operator = ( const CommAll & );
00233
00234 void rank_error( const char * , unsigned ) const ;
00235
00236 bool allocate_buffers( const unsigned * const send_size ,
00237 const unsigned * const recv_size ,
00238 bool local_flag );
00239
00240 ParallelMachine m_comm ;
00241 unsigned m_size ;
00242 unsigned m_rank ;
00243 unsigned m_bound ;
00244 unsigned m_max ;
00245 CommBuffer * m_send ;
00246 CommBuffer * m_recv ;
00247 };
00248
00249
00250
00251 class CommBroadcast {
00252 public:
00253
00254 ParallelMachine parallel() const { return m_comm ; }
00255 unsigned parallel_size() const { return m_size ; }
00256 unsigned parallel_rank() const { return m_rank ; }
00257
00259 CommBuffer & send_buffer();
00260
00262 CommBuffer & recv_buffer();
00263
00264
00265
00266 CommBroadcast( ParallelMachine , unsigned root_rank );
00267
00268 void communicate();
00269
00270 bool allocate_buffer( const bool local_flag = false );
00271
00272 ~CommBroadcast();
00273
00274 private:
00275
00276 CommBroadcast();
00277 CommBroadcast( const CommBroadcast & );
00278 CommBroadcast & operator = ( const CommBroadcast & );
00279
00280 ParallelMachine m_comm ;
00281 unsigned m_size ;
00282 unsigned m_rank ;
00283 unsigned m_root_rank ;
00284 CommBuffer m_buffer ;
00285 };
00286
00287
00288
00289 class CommGather {
00290 public:
00291
00292 ParallelMachine parallel() const { return m_comm ; }
00293 unsigned parallel_size() const { return m_size ; }
00294 unsigned parallel_rank() const { return m_rank ; }
00295
00296 ~CommGather();
00297
00298 CommGather( ParallelMachine , unsigned root_rank , unsigned send_size );
00299
00300 CommBuffer & send_buffer() { return m_send ; }
00301
00302 void communicate();
00303
00304 CommBuffer & recv_buffer( unsigned );
00305
00306 void reset();
00307
00308 private:
00309
00310 CommGather();
00311 CommGather( const CommBroadcast & );
00312 CommGather & operator = ( const CommBroadcast & );
00313
00314 ParallelMachine m_comm ;
00315 unsigned m_size ;
00316 unsigned m_rank ;
00317 unsigned m_root_rank ;
00318 CommBuffer m_send ;
00319 CommBuffer * m_recv ;
00320 int * m_recv_count ;
00321 int * m_recv_displ ;
00322 };
00323
00324 }
00325
00326
00327
00328
00329
00330 namespace phdmesh {
00331
00332 template<unsigned N> struct CommBufferAlign ;
00333
00334 template<>
00335 struct CommBufferAlign<1> {
00336 static size_t align( size_t ) { return 0 ; }
00337 };
00338
00339 template<unsigned N>
00340 struct CommBufferAlign {
00341 static size_t align( size_t i ) { i %= N ; return i ? ( N - i ) : 0 ; }
00342 };
00343
00344 template<typename T>
00345 inline
00346 void CommBuffer::pack( const T & value )
00347 {
00348 enum { Size = sizeof(T) };
00349 size_t nalign = CommBufferAlign<Size>::align( m_ptr - m_beg );
00350 if ( m_beg ) {
00351 if ( m_end < m_ptr + nalign + Size ) { pack_overflow(); }
00352 while ( nalign ) { --nalign ; *m_ptr = 0 ; ++m_ptr ; }
00353 T * tmp = reinterpret_cast<T*>(m_ptr);
00354 *tmp = value ;
00355 m_ptr = reinterpret_cast<ucharp>( ++tmp );
00356 }
00357 else {
00358 m_ptr += nalign + Size ;
00359 }
00360 }
00361
00362 template<typename T>
00363 inline
00364 void CommBuffer::pack( const T * value , size_t number )
00365 {
00366 enum { Size = sizeof(T) };
00367 size_t nalign = CommBufferAlign<Size>::align( m_ptr - m_beg );
00368 if ( m_beg ) {
00369 if ( m_end < m_ptr + nalign + number * Size ) { pack_overflow(); }
00370 while ( nalign ) { --nalign ; *m_ptr = 0 ; ++m_ptr ; }
00371 T * tmp = reinterpret_cast<T*>(m_ptr);
00372 while ( number ) { --number ; *tmp = *value ; ++tmp ; ++value ; }
00373 m_ptr = reinterpret_cast<ucharp>( tmp );
00374 }
00375 else {
00376 m_ptr += nalign + number * Size ;
00377 }
00378 }
00379
00380 template<typename T>
00381 inline
00382 void CommBuffer::skip( size_t number )
00383 {
00384 enum { Size = sizeof(T) };
00385 m_ptr += CommBufferAlign<Size>::align( m_ptr - m_beg ) + Size * number ;
00386 if ( m_beg && m_end < m_ptr ) { unpack_overflow(); }
00387 }
00388
00389 template<typename T>
00390 inline
00391 void CommBuffer::unpack( T & value )
00392 {
00393 enum { Size = sizeof(T) };
00394 const size_t nalign = CommBufferAlign<Size>::align( m_ptr - m_beg );
00395 T * tmp = reinterpret_cast<T*>( m_ptr + nalign );
00396 value = *tmp ;
00397 m_ptr = reinterpret_cast<ucharp>( ++tmp );
00398 if ( m_end < m_ptr ) { unpack_overflow(); }
00399 }
00400
00401 template<typename T>
00402 inline
00403 void CommBuffer::unpack( T * value , size_t number )
00404 {
00405 enum { Size = sizeof(T) };
00406 const size_t nalign = CommBufferAlign<Size>::align( m_ptr - m_beg );
00407 T * tmp = reinterpret_cast<T*>( m_ptr + nalign );
00408 while ( number ) { --number ; *value = *tmp ; ++tmp ; ++value ; }
00409 m_ptr = reinterpret_cast<ucharp>( tmp );
00410 if ( m_end < m_ptr ) { unpack_overflow(); }
00411 }
00412
00413 template<typename T>
00414 inline
00415 void CommBuffer::peek( T & value )
00416 {
00417 enum { Size = sizeof(T) };
00418 const size_t nalign = CommBufferAlign<Size>::align( m_ptr - m_beg );
00419 T * tmp = reinterpret_cast<T*>( m_ptr + nalign );
00420 value = *tmp ;
00421 if ( m_end < reinterpret_cast<ucharp>(++tmp) ) { unpack_overflow(); }
00422 }
00423
00424 template<typename T>
00425 inline
00426 void CommBuffer::peek( T * value , size_t number )
00427 {
00428 enum { Size = sizeof(T) };
00429 const size_t nalign = CommBufferAlign<Size>::align( m_ptr - m_beg );
00430 T * tmp = reinterpret_cast<T*>( m_ptr + nalign );
00431 while ( number ) { --number ; *value = *tmp ; ++tmp ; ++value ; }
00432 if ( m_end < reinterpret_cast<ucharp>(tmp) ) { unpack_overflow(); }
00433 }
00434
00435 inline
00436 void CommBuffer::reset()
00437 { m_ptr = m_beg ; }
00438
00439 inline
00440 size_t CommBuffer::capacity() const
00441 { return m_end - m_beg ; }
00442
00443 inline
00444 size_t CommBuffer::size() const
00445 { return m_ptr - m_beg ; }
00446
00447 inline
00448 ptrdiff_t CommBuffer::remaining() const
00449 { return m_end - m_ptr ; }
00450
00451 inline
00452 void * CommBuffer::buffer() const
00453 { return static_cast<void*>( m_beg ); }
00454
00455
00456
00457
00458 inline
00459 CommBuffer & CommAll::send_buffer( unsigned p ) const
00460 {
00461 if ( m_size <= p ) { rank_error("send_buffer",p); }
00462 return m_send[p] ;
00463 }
00464
00465 inline
00466 CommBuffer & CommAll::recv_buffer( unsigned p ) const
00467 {
00468 if ( m_size <= p ) { rank_error("recv_buffer",p); }
00469 return m_recv[p] ;
00470 }
00471
00472 }
00473
00474
00475
00476
00477 #endif
00478