ug4
communication_scheme.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2015: G-CSC, Goethe University Frankfurt
3  * Author: Martin Rupp
4  *
5  * This file is part of UG4.
6  *
7  * UG4 is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License version 3 (as published by the
9  * Free Software Foundation) with the following additional attribution
10  * requirements (according to LGPL/GPL v3 §7):
11  *
12  * (1) The following notice must be displayed in the Appropriate Legal Notices
13  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14  *
15  * (2) The following notice must be displayed at a prominent place in the
16  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17  *
18  * (3) The following bibliography is recommended for citation and must be
19  * preserved in all covered files:
20  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21  * parallel geometric multigrid solver on hierarchically distributed grids.
22  * Computing and visualization in science 16, 4 (2013), 151-164"
23  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24  * flexible software system for simulating pde based models on high performance
25  * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  */
32 
33 #ifndef COMMUNICATION_SCHEME_H_
34 #define COMMUNICATION_SCHEME_H_
35 
36 #include "pcl/pcl.h"
37 
38 #ifdef UG_PARALLEL
39 namespace ug
40 {
41 
49 // CommunicationScheme
50 //----------------------
103 template<typename TDerived, typename TValue>
105 {
106 public:
108  TDerived& derived() {
109  return static_cast<TDerived&>(*this);
110  }
111 
120  virtual bool
121  collect(ug::BinaryBuffer& buff, const Interface& interface)
122 
123  {
124  int pid = interface.get_target_proc();
125  for(IndexLayout::Interface::const_iterator iter = interface.begin(); iter != interface.end(); ++iter)
126  Serialize(buff, derived().send(pid, interface.get_element(iter)));
127  return true;
128  }
129 
130 
138  virtual bool
139  extract(ug::BinaryBuffer& buff, const Interface& interface)
140  {
141  int pid = interface.get_target_proc();
142  TValue val;
143  for(IndexLayout::Interface::const_iterator iter = interface.begin(); iter != interface.end(); ++iter)
144  {
145  Deserialize(buff, val);
146  derived().receive(pid, interface.get_element(iter), val);
147  }
148  return true;
149  }
150 
157  virtual int
159  {
160  int s = derived().get_element_size();
161  if(s == -1)
162  return -1;
163  else
164  return s * interface.size();
165  }
166 };
167 
169 
176 template<typename TDerived>
177 class CommunicationScheme<TDerived, bool> : public pcl::ICommunicationPolicy<IndexLayout>
178 {
179 public:
180  TDerived& derived() { return static_cast<TDerived&>(*this); }
181 
182  virtual bool
183  collect(ug::BinaryBuffer& buff, const Interface& interface)
184  {
185  int pid = interface.get_target_proc();
186  int j=0;
187  char a=0;
188  for(IndexLayout::Interface::const_iterator iter = interface.begin(); iter != interface.end(); ++iter)
189  {
190  bool b = derived().send(pid, interface.get_element(iter));
191  if(b) a |= (1 << j);
192  j++;
193  if(j == 8)
194  {
195  Serialize(buff, a);
196  a = 0;
197  j = 0;
198  }
199  }
200  if(j) Serialize(buff, a);
201  return true;
202  }
203 
204  virtual bool
205  extract(ug::BinaryBuffer& buff, const Interface& interface)
206  {
207  int pid = interface.get_target_proc();
208  int j=8;
209  char a=0;
210  for(IndexLayout::Interface::const_iterator iter = interface.begin(); iter != interface.end(); ++iter)
211  {
212  size_t index = interface.get_element(iter);
213  if(j==8)
214  {
215  Deserialize(buff, a);
216  j=0;
217  }
218  bool b = a & (1 << j);
219  j++;
220  derived().receive(pid, index, b);
221  }
222  return true;
223  }
224 
225  virtual int
227  {
228  return sizeof(char) * (interface.size()/8 + (interface.size()%8==0?0:1) );
229  }
230 
231 };
232 
234 
235 
236 // StdArrayCommunicationScheme
237 //------------------------------
250 template<typename TArray>
251 class StdArrayCommunicationScheme : public CommunicationScheme<StdArrayCommunicationScheme<TArray>,
252  typename TArray::value_type >
253 {
254  typedef typename TArray::value_type value_type;
255 public:
257  {
258 
259  }
260 
261  inline const value_type &send(int pid, size_t index) const
262  {
263  return m_arr[index];
264  }
265 
266  inline void receive(int pid, size_t index, value_type &v)
267  {
268  m_arr[index] = v;
269  }
270 
271  inline int get_element_size() const
272  {
274  else
275  return -1;
276  }
277 private:
278  TArray &m_arr;
279 };
280 
282 
291 template<typename TCommunicationScheme>
293  const IndexLayout &sendingLayout, const IndexLayout &receivingLayout, TCommunicationScheme &scheme)
294 {
295  AMG_PROFILE_FUNC();
296  int i=0;
297 
298  for(IndexLayout::const_iterator it = sendingLayout.begin(); it != sendingLayout.end(); ++it, ++i)
299  {
300  BinaryBuffer buff;
301  const IndexLayout::Interface &interface = sendingLayout.interface(it);
302  scheme.collect(buff, interface);
303  // todo: don't use parallelcommunicator send_raw
304  // todo: reserve and reuse buff
305  communicator.send_raw(interface.get_target_proc(), buff.buffer(), buff.write_pos(),
306  scheme.get_required_buffer_size(interface) != -1);
307  }
308 
309  int receivingLayoutSize=0;
310  for(IndexLayout::const_iterator it = receivingLayout.begin(); it != receivingLayout.end(); ++it)
311  receivingLayoutSize++;
312 
313  stdvector< BinaryBuffer > bufs(receivingLayoutSize);
314  i=0;
315  for(IndexLayout::const_iterator it = receivingLayout.begin(); it != receivingLayout.end(); ++it, ++i)
316  communicator.receive_raw(receivingLayout.proc_id(it), bufs[i],
317  scheme.get_required_buffer_size(receivingLayout.interface(it)));
318 
319  communicator.communicate();
320  i=0;
321  for(IndexLayout::const_iterator it = receivingLayout.begin(); it != receivingLayout.end(); ++it, ++i)
322  scheme.extract(bufs[i], receivingLayout.interface(it));
323 }
324 
325 template<typename TCommunicationScheme>
326 void CommunicateFromSlaveToMaster(HorizontalAlgebraLayouts &layouts, TCommunicationScheme &scheme)
327 {
328  CommunicateOnInterfaces(layouts.proc_comm(), layouts.slave(), layouts.master(), scheme);
329 }
330 template<typename TCommunicationScheme>
331 void CommunicateFromMasterToSlave(HorizontalAlgebraLayouts &layouts, TCommunicationScheme &scheme)
332 {
333  CommunicateOnInterfaces(layouts.proc_comm(), layouts.master(), layouts.slave(), scheme);
334 }
336 
346 template<typename TSendingScheme, typename TPIDs>
348  IndexLayout &layout, TSendingScheme &sender)
349 {
350  AMG_PROFILE_FUNC();
351 
352  for(size_t i=0; i<pids.size(); i++)
353  {
354  int pid = pids[i];
355  IndexLayout::Interface &interface = layout.interface(pid);
356 
357  BinaryBuffer buff;
358  sender.collect(buff, interface);
359  // todo: don't use parallelcommunicator send_raw
360  // todo: reserve and reuse buff
361  communicator.send_raw(pid, buff.buffer(), buff.write_pos(),
362  sender.get_required_buffer_size(interface) != -1);
363  }
364  communicator.communicate();
365 
366 }
367 
377 template<typename TPIDs, typename TReceiveScheme>
379  IndexLayout &layout, TReceiveScheme &receiver)
380 {
381  stdvector< BinaryBuffer > bufs(pids.size());
382  for(size_t i=0; i<pids.size(); i++)
383  communicator.receive_raw(pids[i], bufs[i], receiver.get_required_buffer_size(layout.interface(pids[i])));
384 
385  communicator.communicate();
386 
387  for(size_t i=0; i<pids.size(); i++)
388  receiver.extract(bufs[i], layout.interface(pids[i]));
389 }
390 
392 
393 
394 
396 
397 #if 0
398 template<typename TDerived, typename TValue>
399 class SparseCommunicationScheme : public pcl::ICommunicationPolicy<IndexLayout>
400 {
401 public:
403  TDerived& derived() {
404  return static_cast<TDerived&>(*this);
405  }
406 
415  virtual bool
416  collect(ug::BinaryBuffer& buff, const Interface& interface)
417 
418  {
419  int pid = interface.get_target_proc();
420  for(IndexLayout::Interface::const_iterator iter = interface.begin(); iter != interface.end(); ++iter)
421  {
422  int index;
423  char a = 0;
424  if(derived().need_send(pid, index))
425  a = 1;
426  Serialize(buff, a);
427  if(a) Serialize(buff, derived().send(pid, index);
428  }
429  }
430 
431 
439  virtual bool
440  extract(ug::BinaryBuffer& buff, const Interface& interface)
441  {
442  int pid = interface.get_target_proc();
443  TValue val;
444  for(IndexLayout::Interface::const_iterator iter = interface.begin(); iter != interface.end(); ++iter)
445  {
446  char a;
447  Deserialize(buff, a);
448  if(a)
449  {
450  Deserialize(buff, val);
451  derived().receive(pid, interface.get_element(iter), val);
452  }
453  }
454  }
455 
462  virtual int
463  get_required_buffer_size(const Interface& interface)
464  {
465  int s = derived().get_element_size();
466  if(s == -1)
467  return -1;
468  else
469  return s * interface.size();
470  }
471 };
472 #endif
473 
474 // end group lib_algebra_parallelization_scheme
476 
477 } // namespace ug
478 #endif /* SEND_INTERFACE_H_ */
479 
480 #endif /* UG_PARALLEL */
parameterString s
specializations are responsible to pack and unpack interface data during communication.
Definition: pcl_communication_structs.h:790
Performs communication between interfaces on different processes.
Definition: pcl_interface_communicator.h:68
void send_raw(int targetProc, const void *pBuff, int bufferSize, bool bSizeKnownAtTarget=false)
sends raw data to a target-proc.
Definition: pcl_interface_communicator_impl.hpp:61
void receive_raw(int srcProc, ug::BinaryBuffer &bufOut, int bufSize=-1)
registers a binary-stream to receive data from a source-proc.
Definition: pcl_interface_communicator_impl.hpp:166
bool communicate(int tag=749345)
sends and receives the collected data.
Definition: pcl_interface_communicator_impl.hpp:409
You may add elements to this interface and iterate over them.
Definition: pcl_communication_structs.h:207
ElemContainer::const_iterator const_iterator
Definition: pcl_communication_structs.h:237
iterator end()
Definition: pcl_communication_structs.h:293
iterator begin()
Definition: pcl_communication_structs.h:292
Element & get_element(iterator iter)
Definition: pcl_communication_structs.h:298
int get_target_proc() const
Definition: pcl_communication_structs.h:309
size_t size() const
returns the number of elements that are stored in the interface.
Definition: pcl_communication_structs.h:306
iterator end(size_t level=0)
returns the iterator to the last interface of the layout.
Definition: pcl_communication_structs.h:492
iterator begin(size_t level=0)
returns the iterator to the first interface of the layout.
Definition: pcl_communication_structs.h:486
int proc_id(iterator iter) const
returns the target process of the interface given in iterator
Definition: pcl_communication_structs.h:509
Interface & interface(iterator iter)
returns the interface to the given iterator.
Definition: pcl_communication_structs.h:505
InterfaceMap::const_iterator const_iterator
Definition: pcl_communication_structs.h:477
A Buffer for binary data.
Definition: binary_buffer.h:56
char * buffer()
returns the raw buffer pointer or NULL if the buffer is empty (capacity() == 0)
Definition: binary_buffer_impl.h:94
size_t write_pos() const
returns the current write-pos (in bytes)
Definition: binary_buffer_impl.h:53
virtual bool collect(ug::BinaryBuffer &buff, const Interface &interface)
should write data which is associated with the interface elements to the buffer.
Definition: communication_scheme.h:183
TDerived & derived()
Definition: communication_scheme.h:180
virtual bool extract(ug::BinaryBuffer &buff, const Interface &interface)
extract data from the buffer and assigns it to the interface-elements.
Definition: communication_scheme.h:205
virtual int get_required_buffer_size(const Interface &interface)
returns the size of the buffer in bytes, that will be required for interface-communication.
Definition: communication_scheme.h:226
CRTP Base class for communications on layout/interfaces.
Definition: communication_scheme.h:105
TDerived & derived()
get the derived class
Definition: communication_scheme.h:108
virtual int get_required_buffer_size(const Interface &interface)
get the size of the required buffer for an interface
Definition: communication_scheme.h:158
virtual bool extract(ug::BinaryBuffer &buff, const Interface &interface)
receive data on the interface and hand it over to TDerived::receive
Definition: communication_scheme.h:139
virtual bool collect(ug::BinaryBuffer &buff, const Interface &interface)
send data on the interface based on TDerived::send
Definition: communication_scheme.h:121
Holds Interfaces and communicators for horizontal communication.
Definition: algebra_layouts.h:48
const pcl::ProcessCommunicator & proc_comm() const
returns process communicator
Definition: algebra_layouts.h:68
const IndexLayout & slave() const
Definition: algebra_layouts.h:63
const IndexLayout & master() const
Definition: algebra_layouts.h:61
Communication Scheme for synchronization of arrays or similar datastructures.
Definition: communication_scheme.h:253
StdArrayCommunicationScheme(TArray &t)
Definition: communication_scheme.h:256
TArray::value_type value_type
Definition: communication_scheme.h:254
int get_element_size() const
Definition: communication_scheme.h:271
const value_type & send(int pid, size_t index) const
Definition: communication_scheme.h:261
TArray & m_arr
Definition: communication_scheme.h:278
void receive(int pid, size_t index, value_type &v)
Definition: communication_scheme.h:266
Definition: stl_debug.h:45
void SendOnInterfaces(pcl::InterfaceCommunicator< IndexLayout > &communicator, TPIDs &pids, IndexLayout &layout, TSendingScheme &sender)
sends data over a interface based on a CommunicationScheme to a subgroup of processes
Definition: communication_scheme.h:347
void CommunicateOnInterfaces(pcl::InterfaceCommunicator< IndexLayout > &communicator, const IndexLayout &sendingLayout, const IndexLayout &receivingLayout, TCommunicationScheme &scheme)
sends data over a CommunicationScheme from a sendingLayout to a receivingLayout
Definition: communication_scheme.h:292
void ReceiveOnInterfaces(pcl::InterfaceCommunicator< IndexLayout > &communicator, TPIDs &pids, IndexLayout &layout, TReceiveScheme &receiver)
receives data over a interface based on a CommunicationScheme on a subgroup of processes
Definition: communication_scheme.h:378
void CommunicateFromMasterToSlave(HorizontalAlgebraLayouts &layouts, TCommunicationScheme &scheme)
Definition: communication_scheme.h:331
void CommunicateFromSlaveToMaster(HorizontalAlgebraLayouts &layouts, TCommunicationScheme &scheme)
Definition: communication_scheme.h:326
the ug namespace
void Deserialize(TIStream &buf, ParallelVector< T > &v)
Deerialize for ParallelVector<T>
Definition: restart_bridge.cpp:112
void Serialize(TOStream &buf, const ParallelVector< T > &v)
Serialize for ParallelVector<T>
Definition: restart_bridge.cpp:103
T value_type
Definition: sparsematrix_interface.h:2
Definition: communication_policies.h:58