ug4
pcl_layout_tests.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 __H__PCL_TEST_LAYOUTS__
34 #define __H__PCL_TEST_LAYOUTS__
35 
36 #include <vector>
37 #include <iomanip> // for 'std::setw()' etc.
38 #include <map>
39 
40 #include "pcl_base.h"
41 #include "pcl_methods.h"
45 
47 #include "common/log.h"
48 #include "common/assert.h"
49 #include "common/serialization.h"
51 
52 #include <boost/function.hpp>
53 
54 namespace pcl
55 {
56 
59 
61 
62 template <class TElem>
63 TElem TrivialToValue(TElem e)
64 {
65  return e;
66 }
67 inline void PrintPC(const pcl::ProcessCommunicator &processCommunicator)
68 {
69  UG_LOG(processCommunicator.size() << " involved procs: ");
70  for(size_t i=0; i<processCommunicator.size(); i++)
71  { UG_LOG(processCommunicator.get_proc_id(i) << " "); }
72  UG_LOG("\n");
73 
74 }
75 
76 #define PRINTPC(com) UG_LOG(__FUNCTION__ << " : " << __LINE__ << "\n"); PrintPC(com)
78 // TestLayoutIsDoubleEnded
80 
83 template<typename TLayout>
84 bool TestLayoutIsDoubleEnded(const pcl::ProcessCommunicator processCommunicator,
86  const TLayout &masterLayout, const TLayout &slaveLayout)
87 {
88  PROFILE_FUNC_GROUP("debug");
89  //PRINTPC(processCommunicator);
90 // check if connections are double-ended
91  std::vector<char> bMasterToProcess; bMasterToProcess.resize(processCommunicator.size(), 0x00);
92  std::vector<char> bSlaveToProcess; bSlaveToProcess.resize(processCommunicator.size(), 0x00);
93 
94  for(typename TLayout::const_iterator iter = masterLayout.begin(); iter != masterLayout.end(); ++iter)
95  {
96  int id = processCommunicator.get_local_proc_id(masterLayout.proc_id(iter));
97  if(id == -1)
98  UG_LOG("Processor " << masterLayout.proc_id(iter) << " not in processCommunicator, but in MasterLayout\n")
99  else bMasterToProcess[id] = true;
100  }
101  for(typename TLayout::const_iterator iter = slaveLayout.begin(); iter != slaveLayout.end(); ++iter)
102  {
103  int id = processCommunicator.get_local_proc_id(slaveLayout.proc_id(iter));
104  if(id == -1)
105  UG_LOG("Processor " << slaveLayout.proc_id(iter) << " not in processCommunicator, but in SlaveLayout\n")
106  else bSlaveToProcess[id] = true;
107  }
108 
109  for(size_t i=0; i<processCommunicator.size(); i++)
110  {
111  com.send_raw(processCommunicator.get_proc_id(i), &bMasterToProcess[i], sizeof(char));
112  com.send_raw(processCommunicator.get_proc_id(i), &bSlaveToProcess[i], sizeof(char));
113  }
114 
115  std::vector<ug::BinaryBuffer> masterToThisProcessMap(processCommunicator.size());
116  std::vector<ug::BinaryBuffer> slaveToThisProcessMap(processCommunicator.size());
117  for(size_t i=0; i < processCommunicator.size(); i++)
118  {
119  com.receive_raw(processCommunicator.get_proc_id(i), masterToThisProcessMap[i]);
120  com.receive_raw(processCommunicator.get_proc_id(i), slaveToThisProcessMap[i]);
121  }
122 
123  com.communicate();
124 
125  for(size_t i=0; i<processCommunicator.size(); i++)
126  {
127  char bMasterToThisProcess, bSlaveToThisProcess;
128  ug::Deserialize(masterToThisProcessMap[i], bMasterToThisProcess);
129  ug::Deserialize(slaveToThisProcessMap[i], bSlaveToThisProcess);
130 
131  int pid = processCommunicator.get_proc_id(i);
132  if(bMasterToThisProcess != bSlaveToProcess[i])
133  {
134  UG_LOG("Process " << std::setw(4) << pid << " has " << (bMasterToThisProcess ? "a" : "no") << " master connection to this process (" << std::setw(4) << pcl::ProcRank()
135  << "), but we have " << (bSlaveToProcess[i] ? "a" : "no") << " slave connection to " << std::setw(4) << pid << std::endl);
136  return false;
137  }
138  if(bSlaveToThisProcess != bMasterToProcess[i]){
139  UG_LOG("Process " << std::setw(4) << pid << " has " << (bSlaveToThisProcess ? "a" : "no") << " slave connection to this process (" << pcl::ProcRank()
140  << "), but we have " << (bMasterToProcess[i] ? "a" : "no") << " master connection to " << std::setw(4) << pid << std::endl);
141  return false;
142  }
143  }
144 
145  return true;
146 }
147 
149 
159 template<typename TLayout, typename TValue>
161  const TLayout &masterLayout,
162  const TLayout &slaveLayout, bool bPrint=false,
163  boost::function<TValue (typename TLayout::Element)> cbToValue
164  = TrivialToValue<typename TLayout::Element>,
165  bool compareValues = false)
166 {
167  PROFILE_FUNC_GROUP("debug");
168  typedef std::map<int, ug::BinaryBuffer> BufferMap;
169  typedef typename TLayout::Interface Interface;
170 
171  BufferMap sendMap, receiveMap;
172 
173  for(typename TLayout::const_iterator iter = slaveLayout.begin(); iter != slaveLayout.end(); ++iter)
174  {
175  const Interface &interface = slaveLayout.interface(iter);
176  int pid = slaveLayout.proc_id(iter);
177  ug::BinaryBuffer& buffer = sendMap[pid];
178 
179  for(typename TLayout::Interface::const_iterator iter2 = interface.begin(); iter2 != interface.end(); ++iter2)
180  {
181  const typename Interface::Element &element = interface.get_element(iter2);
182  Serialize(buffer, cbToValue(element));
183  }
184  com.send_raw(pid, buffer.buffer(), buffer.write_pos(), false);
185  }
186 
187 
188  for(typename TLayout::const_iterator iter = masterLayout.begin(); iter != masterLayout.end(); ++iter)
189  {
190  int pid = masterLayout.proc_id(iter);
191  com.receive_raw(pid, receiveMap[pid]);
192  }
193 
194  com.communicate();
195 
196  bool layoutBroken=false;
197  bool valueMismatch = false;
198 
199  for(typename TLayout::const_iterator iter = masterLayout.begin(); iter != masterLayout.end(); ++iter)
200  {
201  int pid = masterLayout.proc_id(iter);
202  ug::BinaryBuffer &buffer = receiveMap[pid];
203  bool broken=false;
204  if(bPrint) { UG_LOG(" Interface processor " << pcl::ProcRank() << " <-> processor " << pid << " (Master <-> Slave):\n"); }
205  const typename TLayout::Interface &interface = masterLayout.interface(iter);
206  std::stringstream brokenInformation;
207  size_t onMaster=0, onSlave=0;
208  for(typename TLayout::Interface::const_iterator iter2 = interface.begin(); iter2 != interface.end(); ++iter2)
209  {
210  TValue val1 = cbToValue(interface.get_element(iter2));
211 
212  if(buffer.eof())
213  {
214  broken =true;
215  if(bPrint){
216  UG_LOG(" " << onMaster << ": " << std::setw(9) << val1 << " <-> " << "-?-" << "\n");
217  }
218  }
219  else
220  {
221  TValue val2;
222  Deserialize(buffer, val2);
223  onSlave++;
224 
225  bool mismatch = false;
226  if(compareValues){
227  mismatch = (val1 != val2);
228  }
229 
230  if(mismatch){
231  UG_LOG(" " << std::setw(9) << val1 << " <-> " << val2 << " --- MISMATCH! ---"
232  << " (interface to proc " << pid << ")" << std::endl);
233  }
234  valueMismatch |= mismatch;
235  if(bPrint)
236  {
237  UG_LOG(" " << onMaster << ": " << std::setw(9) << val1 << " <-> " << val2 << "\n");
238  }
239  }
240  onMaster++;
241  }
242 
243  if(!buffer.eof())
244  {
245  while(!buffer.eof())
246  {
247  TValue val2;
248  Deserialize(buffer, val2);
249  if(bPrint)
250  {UG_LOG(" " << onSlave << ": " << std::setw(9) << "-?-" << " <-> " << val2 << "\n");}
251  onSlave++;
252  }
253  broken =true;
254  }
255 
256  if(onMaster!=onSlave)
257  {
258  UG_LOG(" Interface sizes do not match:\n");
259  UG_LOG(" - Slave Interface " << pid << " -> " << pcl::ProcRank() << ", size = " << onSlave << "\n");
260  UG_LOG(" - Master Interface " << pcl::ProcRank() << " -> " << pid << ", size = " << onMaster << "\n");
261  }
262  else if(bPrint)
263  { UG_LOG(" In total " << std::setw(9) << onMaster << " entries in this interface." << std::endl); }
264 
265  if(broken)
266  {
267  layoutBroken=true;
268  UG_LOG(" Interface from processor " << std::setw(4) << pcl::ProcRank() << " to processor " << std::setw(4) << pid << " is BROKEN!\n");
269 
270  }
271 
272  }
273 
274  if(layoutBroken == true)
275  {
276  UG_LOG("One or more interfaces are broken\n");
277  return false;
278  }
279 
280  if(valueMismatch){
281  UG_LOG("MISMATCH! Not all values at connected interface elements did match!\n");
282  return false;
283  }
284  return true;
285 }
286 
288 
299 template<typename TLayout, typename TValue>
300 bool TestLayout(const pcl::ProcessCommunicator &processCommunicator,
302  const TLayout &masterLayout,
303  const TLayout &slaveLayout, bool bPrint=false,
304  boost::function<TValue (typename TLayout::Element)> cbToValue
305  = TrivialToValue<typename TLayout::Element>,
306  bool compareValues = false)
307 {
308  PROFILE_FUNC_GROUP("debug");
309  if(bPrint)
310  {
311  UG_LOG("proc " << std::setw(4) << pcl::ProcRank() << ":\n");
312  UG_LOG(" MasterLayout is to processes ");
313  for(typename TLayout::const_iterator iter = masterLayout.begin(); iter != masterLayout.end(); ++iter) {
314  UG_LOG(" " << std::setw(4) << masterLayout.proc_id(iter) << " ");
315  }
316  UG_LOG("\n Slave Layout is to processes ");
317  for(typename TLayout::const_iterator iter = slaveLayout.begin(); iter != slaveLayout.end(); ++iter) {
318  UG_LOG(" " << std::setw(4) << slaveLayout.proc_id(iter) << " ");
319  }
320  UG_LOG("\n");
321  }
322  bool bDoubleEnded = TestLayoutIsDoubleEnded(processCommunicator,
323  com, masterLayout, slaveLayout);
324  if(!pcl::AllProcsTrue(bDoubleEnded, processCommunicator))
325  return false;
326 
327  bool bSuccess = TestSizeOfInterfacesInLayoutsMatch<TLayout, TValue>(com, masterLayout,
328  slaveLayout, bPrint, cbToValue, compareValues);
329  return pcl::AllProcsTrue(bSuccess, processCommunicator);
330 }
331 
332 template<typename TLayout>
333 bool TestLayout(const pcl::ProcessCommunicator &processCommunicator,
334  pcl::InterfaceCommunicator<TLayout> &com, const TLayout &masterLayout,
335  const TLayout &slaveLayout, bool bPrint=false,
336  bool compareValues = false)
337 {
338  return TestLayout<TLayout, typename TLayout::Element>(processCommunicator, com,
339  masterLayout, slaveLayout, bPrint,
340  TrivialToValue<typename TLayout::Element>, compareValues);
341 }
342 
343 template<typename TLayout, typename TValue>
344 bool PrintLayout(const pcl::ProcessCommunicator &processCommunicator,
345  pcl::InterfaceCommunicator<TLayout> &com, const TLayout &masterLayout,
346  const TLayout &slaveLayout,
347  boost::function<TValue (typename TLayout::Element)> cbToValue
348  = TrivialToValue<typename TLayout::Element>)
349 {
350  return TestLayout(processCommunicator, com, masterLayout, slaveLayout, true, cbToValue);
351 }
352 
353 
354 template<typename TLayout>
355 inline bool PrintLayout(const pcl::ProcessCommunicator &processCommunicator,
357  const TLayout &masterLayout,
358  const TLayout &slaveLayout)
359 {
360  return TestLayout(processCommunicator, com, masterLayout, slaveLayout, true);
361 }
362 
363 
364 
365 template<typename TLayout>
366 inline void PrintLayout(const TLayout &layout)
367 {
368  for(typename TLayout::const_iterator iter = layout.begin(); iter != layout.end(); ++iter)
369  {
370  size_t pid = layout.proc_id(iter);
371  UG_LOG("to processor " << pid << ": ");
372  const typename TLayout::Interface &interface = layout.interface(iter);
373  for(typename TLayout::Interface::const_iterator iter2 = interface.begin(); iter2 != interface.end(); ++iter2)
374  UG_LOG(interface.get_element(iter2) << " ");
375  UG_LOG("\n");
376  }
377 }
378 
379 #define TESTLAYOUT(processCommunicator, com, master, slave) { if(TestLayout(processCommunicator,\
380  com, master, slave) == false) { PrintLayout(processCommunicator, com, master, slave); UG_COND_THROW(true, "layout broken"); } }
381 
382 #ifndef NDEBUG
383 #define DEBUG_TESTLAYOUT(processCommunicator, com, master, slave) TESTLAYOUT(processCommunicator, com, master, slave)
384 #else
385  #define DEBUG_TESTLAYOUT(processCommunicator, com, master, slave)
386 #endif
387 
388 #define DEBUG_TESTLAYOUTS(layout) DEBUG_TESTLAYOUT(layout->proc_comm(), layout->comm(), layout->master(), layout->slave())
389 #define TESTLAYOUTS(layout) TESTLAYOUT(layout->proc_comm(), layout->comm(), layout->master(), layout->slave())
390 
391 // end group pcl
393 
394 } // end namespace pcl
395 
396 #endif
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
Definition: pcl_process_communicator.h:70
int get_proc_id(size_t index) const
returns the i-th process in the communicator
Definition: pcl_process_communicator.cpp:86
size_t size() const
returns the size of the communicator
Definition: pcl_process_communicator.cpp:71
int get_local_proc_id(int globalProcID=pcl::ProcRank()) const
returns the proc-id relative to this communicator
Definition: pcl_process_communicator.cpp:95
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
bool eof()
returns true if the read-position reached the write-position
Definition: binary_buffer_impl.h:99
bool TestLayoutIsDoubleEnded(const pcl::ProcessCommunicator processCommunicator, pcl::InterfaceCommunicator< TLayout > &com, const TLayout &masterLayout, const TLayout &slaveLayout)
tests if masterLayouts proc id's find a match in corresponding slaveLayouts proc ids.
Definition: pcl_layout_tests.h:84
int ProcRank()
returns the rank of the process
Definition: pcl_base.cpp:83
TElem TrivialToValue(TElem e)
Trivial implementation of a to-value callback.
Definition: pcl_layout_tests.h:63
bool TestLayout(const pcl::ProcessCommunicator &processCommunicator, pcl::InterfaceCommunicator< TLayout > &com, const TLayout &masterLayout, const TLayout &slaveLayout, bool bPrint=false, boost::function< TValue(typename TLayout::Element)> cbToValue=TrivialToValue< typename TLayout::Element >, bool compareValues=false)
Checks whether the given layouts are consistent.
Definition: pcl_layout_tests.h:300
bool AllProcsTrue(bool bFlag, ProcessCommunicator comm)
Definition: pcl_util.cpp:54
bool PrintLayout(const pcl::ProcessCommunicator &processCommunicator, pcl::InterfaceCommunicator< TLayout > &com, const TLayout &masterLayout, const TLayout &slaveLayout, boost::function< TValue(typename TLayout::Element)> cbToValue=TrivialToValue< typename TLayout::Element >)
Definition: pcl_layout_tests.h:344
bool TestSizeOfInterfacesInLayoutsMatch(pcl::InterfaceCommunicator< TLayout > &com, const TLayout &masterLayout, const TLayout &slaveLayout, bool bPrint=false, boost::function< TValue(typename TLayout::Element)> cbToValue=TrivialToValue< typename TLayout::Element >, bool compareValues=false)
if processor P1 has a interface to P2, then the size of the interface P1->P2 has to be the same as th...
Definition: pcl_layout_tests.h:160
void PrintPC(const pcl::ProcessCommunicator &processCommunicator)
Definition: pcl_layout_tests.h:67
#define UG_LOG(msg)
Definition: log.h:367
Definition: parallel_grid_layout.h:46
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
#define PROFILE_FUNC_GROUP(groups)
Definition: profiler.h:258