|
phdMesh Version of the Day
|
00001 /*------------------------------------------------------------------------*/ 00002 /* phdMesh : Parallel Heterogneous Dynamic unstructured Mesh */ 00003 /* Copyright (2007) Sandia Corporation */ 00004 /* */ 00005 /* Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive */ 00006 /* license for use of this work by or on behalf of the U.S. Government. */ 00007 /* */ 00008 /* This library is free software; you can redistribute it and/or modify */ 00009 /* it under the terms of the GNU Lesser General Public License as */ 00010 /* published by the Free Software Foundation; either version 2.1 of the */ 00011 /* License, or (at your option) any later version. */ 00012 /* */ 00013 /* This library is distributed in the hope that it will be useful, */ 00014 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 00015 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ 00016 /* Lesser General Public License for more details. */ 00017 /* */ 00018 /* You should have received a copy of the GNU Lesser General Public */ 00019 /* License along with this library; if not, write to the Free Software */ 00020 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */ 00021 /* USA */ 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 // Inlined template implementations for the CommBuffer 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 // Inline implementations for the CommAll 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
1.7.4