Loading [MathJax]/extensions/tex2jax.js
ug4
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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"
51
52#include <boost/function.hpp>
53
54namespace pcl
55{
56
59
61
62template <class TElem>
63TElem TrivialToValue(TElem e)
64{
65 return e;
66}
67inline 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
83template<typename TLayout>
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
159template<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
299template<typename TLayout, typename TValue>
300bool 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
332template<typename TLayout>
333bool 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
343template<typename TLayout, typename TValue>
344bool 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
354template<typename TLayout>
355inline 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
365template<typename TLayout>
366inline 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