Loading...
Searching...
No Matches
Public Member Functions | Protected Member Functions | Private Attributes | List of all members
G4MPIscorerMerger Class Reference

#include <Doxymodules_parallel.h>

Public Member Functions

 G4MPIscorerMerger ()
 
 G4MPIscorerMerger (G4ScoringManager *mgr, G4int destination=G4MPImanager::kRANK_MASTER, G4int verbosity=0)
 
virtual ~G4MPIscorerMerger ()
 
void SetDestinationRank (G4int i)
 
void SetScoringManager (G4ScoringManager *mgr)
 
void SetVerbosity (G4int ver)
 
void Merge ()
 

Protected Member Functions

void SetupOutputBuffer (char *buff, G4int size, G4int position)
 
void DestroyBuffer ()
 
void Pack (const G4ScoringManager *)
 Pack all meshes into buffer.
 
void UnPackAndMerge (const G4ScoringManager *)
 
void Pack (const G4VScoringMesh *)
 Pack a single mesh.
 
void UnPackAndMerge (G4VScoringMesh *)
 
void Pack (const HitStatDoubleMap *)
 Pack a single score map.
 
HitStatDoubleMapUnPackHitStatDoubleMap (const G4String &detName, const G4String &colName)
 
G4int CalculatePackSize (const G4ScoringManager *) const
 
G4int CalculatePackSize (const G4VScoringMesh *) const
 
G4int CalculatePackSize (const HitStatDoubleMap *) const
 
void Send (const unsigned int destination)
 
void Receive (const unsigned int source)
 

Private Attributes

char * outputBuffer
 
G4int outputBufferSize
 
G4int outputBufferPosition
 
long bytesSent
 
G4bool ownsBuffer
 
G4ScoringManagerscoringManager
 
unsigned int commSize
 
unsigned int destinationRank
 
MPI::Intracomm comm
 
G4int verbose
 

Detailed Description

Definition at line 67 of file Doxymodules_parallel.h.

Constructor & Destructor Documentation

◆ G4MPIscorerMerger() [1/2]

G4MPIscorerMerger::G4MPIscorerMerger ( )

◆ G4MPIscorerMerger() [2/2]

G4MPIscorerMerger::G4MPIscorerMerger ( G4ScoringManager mgr,
G4int  destination = G4MPImanager::kRANK_MASTER,
G4int  verbosity = 0 
)

Definition at line 79 of file G4MPIscorerMerger.cc.

81 :
83 ownsBuffer(false),
84 scoringManager(mgr), commSize(0), destinationRank(destination),
85 verbose(verbosity)
86{
87}

◆ ~G4MPIscorerMerger()

G4MPIscorerMerger::~G4MPIscorerMerger ( )
virtual

Definition at line 89 of file G4MPIscorerMerger.cc.

89 {
90 if ( ownsBuffer ) delete[] outputBuffer;
91}

Member Function Documentation

◆ SetDestinationRank()

void G4MPIscorerMerger::SetDestinationRank ( G4int  i)
inline

Definition at line 49 of file G4MPIscorerMerger.hh.

49{ destinationRank = i; }

◆ SetScoringManager()

void G4MPIscorerMerger::SetScoringManager ( G4ScoringManager mgr)
inline

Definition at line 50 of file G4MPIscorerMerger.hh.

50{ scoringManager = mgr; }

◆ SetVerbosity()

void G4MPIscorerMerger::SetVerbosity ( G4int  ver)
inline

Definition at line 51 of file G4MPIscorerMerger.hh.

51{ verbose = ver; }

◆ Merge()

void G4MPIscorerMerger::Merge ( )

Definition at line 123 of file G4MPIscorerMerger.cc.

123 {
124 DMSG(0, "G4MPIscorerMerger::Merge called");
125 const unsigned int myrank = G4MPImanager::GetManager()->GetRank();
127 if ( commSize == 1 ) {
128 DMSG(1,"Comm world size is 1, nothing to do");
129 return;
130 }
131 const MPI::Intracomm* parentComm = G4MPImanager::GetManager()->GetComm();
132 comm = parentComm->Dup();
134
135 //ANDREA:->
136// G4cout<<"Before sending: "<<G4endl;
137// scoringManager->GetMesh(0)->Dump();
138// for ( int i = 0 ; i < scoringManager->GetNumberOfMesh() ; ++i ) {
139// for ( auto e : scoringManager->GetMesh(i)->GetScoreMap() )
140// {
141// G4cout<<e.first<<" : "<<e.second<<G4endl;
142// for ( auto c: *(e.second->GetMap()) ) {
143// G4cout<<c.first<<"="<<*c.second<<G4endl;
144//
145// }
146// }
147// }
148 //ANDREA:<-
149
150 bytesSent=0;
151 const G4double sttime = MPI::Wtime();
152
153 //Use G4MPIutils to optimize communications between ranks
154 typedef std::function<void(unsigned int)> handler_t;
155 using std::placeholders::_1;
156 handler_t sender = std::bind(&G4MPIscorerMerger::Send , this , _1);
157 handler_t receiver = std::bind(&G4MPIscorerMerger::Receive, this, _1);
158 std::function<void(void)> barrier = std::bind(&MPI::Intracomm::Barrier,&comm);
159 G4mpi::Merge( sender , receiver , barrier , commSize , myrank );
160
161 //OLD Style p2p communications
162 /*
163 if ( myrank != destinationRank ) {
164 DMSG(1,"Comm world size: "<<commSize<<" this rank is: "
165 <<myrank<<" sending to rank "<<destinationRank
166 <<" Number of mesh: "<< scoringManager->GetNumberOfMesh() );
167 Send(destinationRank);
168 } else {
169 DMSG(1,"Comm world size: "<<commSize<<" this rank is: "
170 <<myrank<<" receiving "
171 <<" Number of mesh: "<< scoringManager->GetNumberOfMesh() );
172 for ( unsigned int i = 0 ; i < commSize ; ++i ) {
173 if ( i != myrank ) Receive(i);
174 }
175 }
176*/
177 const G4double elapsed = MPI::Wtime() - sttime;
178 long total=0;
179 comm.Reduce(&bytesSent,&total,1,MPI::LONG,MPI::SUM,destinationRank);
180 if ( verbose > 0 && myrank == destinationRank ) {
181 //Collect from ranks how much data was sent around
182 G4cout<<"G4MPIscorerMerger::Merge() -data transfer performances: "
183 <<double(total)/1000./elapsed<<" kB/s"
184 <<" (Total Data Transfer= "<<double(total)/1000.<<" kB in "
185 <<elapsed<<" s)."<<G4endl;
186 }
187 //ANDREA:->
188// G4cout<<"After Receiving: "<<G4endl;
189// scoringManager->GetMesh(0)->Dump();
190// for ( int i = 0 ; i < scoringManager->GetNumberOfMesh() ; ++i ) {
191// for ( auto e : scoringManager->GetMesh(i)->GetScoreMap() )
192// {
193// G4cout<<e.first<<" : "<<e.second<<G4endl;
194// for ( auto c: *(e.second->GetMap()) ) {
195// G4cout<<c.first<<"="<<*c.second<<" (=2x"<<.5*(*c.second)<<")"<<G4endl;
196//
197// }
198// }
199// }
200 //ANDREA:<-
201 comm.Free();
202 DMSG(0,"G4MPIscorerMerger::Merge done.");
203}
#define DMSG(LVL, MSG)
static G4MPImanager * GetManager()
G4int GetActiveSize() const
const MPI::Intracomm * GetComm() const
G4int GetRank() const
void Send(const unsigned int destination)
void Receive(const unsigned int source)
void Merge(std::function< void(unsigned int)> senderF, std::function< void(unsigned int)> receiverF, std::function< void(void)> barrierF, unsigned int commSize, unsigned int myrank)

◆ SetupOutputBuffer()

void G4MPIscorerMerger::SetupOutputBuffer ( char *  buff,
G4int  size,
G4int  position 
)
inlineprotected

Definition at line 57 of file G4MPIscorerMerger.hh.

◆ DestroyBuffer()

void G4MPIscorerMerger::DestroyBuffer ( )
inlineprotected

Definition at line 62 of file G4MPIscorerMerger.hh.

62 {
63 delete[] outputBuffer;
64 outputBuffer = nullptr;
67 ownsBuffer = false;
68 }

◆ Pack() [1/3]

void G4MPIscorerMerger::Pack ( const G4ScoringManager sm)
protected

Pack all meshes into buffer.

Definition at line 259 of file G4MPIscorerMerger.cc.

259 {
260 assert(sm!=nullptr);
262 G4Exception("G4MPIscorerMerger::Pack(const G4ScoringManager*)",
263 "MPI001",FatalException,
264 "Call SetOututBuffer before trying to pack");
265 return;
266 }
267 DMSG(2,"Starting packing of meshes, # meshes: "<<sm->GetNumberOfMesh());
268 /*const*/ size_t numMeshes=sm->GetNumberOfMesh();//TODO: OLD MPI interface
269 MPI_Pack(&numMeshes,1,MPI::UNSIGNED,
272 comm);
273 for (size_t i = 0; i <numMeshes; ++i)
274 {
275 MPI_Pack(&i,1,MPI::UNSIGNED,
278 Pack(sm->GetMesh(i));
279 }
280}
void Pack(const G4ScoringManager *)
Pack all meshes into buffer.

◆ UnPackAndMerge() [1/2]

void G4MPIscorerMerger::UnPackAndMerge ( const G4ScoringManager sm)
protected

Definition at line 282 of file G4MPIscorerMerger.cc.

282 {
283 assert(sm!=nullptr);
285 G4Exception("G4MPIscorerMerger::UnPack(const G4ScroingManager*)",
286 "MPI001",FatalException,
287 "Call SetOututBuffer before trying to un-pack");
288 return;
289 }
290 size_t numMeshes=0;
292 &numMeshes,1,MPI::UNSIGNED,comm);
293 if ( numMeshes != sm->GetNumberOfMesh() ) {
294 G4ExceptionDescription msg;
295 msg << "Number of meshes to unpack ("<<numMeshes;
296 msg <<") does not correspond to expected number ("<<sm->GetNumberOfMesh();
297 msg<<")";
298 G4Exception("G4MPIscorerMerger::UnPack(const G4ScroingManager*)",
299 "MPI001",FatalException,msg);
300 return;
301 }
302
303 size_t meshid=0;
304 for ( size_t i = 0 ; i < numMeshes ; ++i ) {
306 &meshid,1,MPI::UNSIGNED,comm);
307 if ( meshid != i ) {
308 G4ExceptionDescription msg;
309 msg<<"Cannot unpack: expecting mesh "<<i<<" and found "<<meshid;
310 msg<<" during unpack.";
311 G4Exception("G4MPIscorerMerger::UnPack(const G4ScroingManager*)",
312 "MPI001",FatalException,msg);
313 return;
314 }
315 G4VScoringMesh* original = sm->GetMesh(i);
316 UnPackAndMerge(original);
317 }
318}
void UnPackAndMerge(const G4ScoringManager *)

◆ Pack() [2/3]

void G4MPIscorerMerger::Pack ( const G4VScoringMesh mesh)
protected

Pack a single mesh.

Definition at line 320 of file G4MPIscorerMerger.cc.

320 {
321 assert(mesh!=nullptr);
322 assert(outputBuffer!=nullptr);
324 DMSG(3,"Packing mesh: "<<mesh);
325
326 auto map = mesh->GetScoreMap();
327 /*const*/ size_t nummaps = map.size();//TODO: old MPI interface
328 MPI_Pack(&nummaps,1,MPI::UNSIGNED,
331 for ( const auto& ele: map ) {
332 const G4String& name = ele.first;
333 /*const*/ size_t ss = name.size();
334 MPI_Pack(&ss,1,MPI::UNSIGNED,
337#ifdef G4MPI_USE_MPI_PACK_NOT_CONST
338 char* nn = new char[name.length()];
339 std::copy(name.begin(),name.end(),nn);
340#else
341 const char* nn = name.c_str();
342#endif
343 MPI_Pack(nn,ss,MPI::CHAR,outputBuffer,outputBufferSize,&outputBufferPosition,comm);
344 Pack(ele.second);
345#ifdef G4MPI_USE_MPI_PACK_NOT_CONST
346 delete[] nn;
347#endif
348 }
349}

◆ UnPackAndMerge() [2/2]

void G4MPIscorerMerger::UnPackAndMerge ( G4VScoringMesh inmesh)
protected

Definition at line 351 of file G4MPIscorerMerger.cc.

351 {
352 assert(outputBuffer!=nullptr);
354 assert(inmesh!=nullptr);
355 DMSG(3,"Preparing to unpack a mesh and merge into: "<<inmesh);
356 const G4String& detName = inmesh->GetWorldName();
357 size_t nummaps = 0;
359 &nummaps,1,MPI::UNSIGNED,comm);
360 for ( size_t i = 0 ; i < nummaps ; ++i ) {
361 size_t nameSize = 0;
363 &nameSize,1,MPI::UNSIGNED,comm);
364 //Create a null-terminated c-string: needed later when converting this to a G4String
365 //(Not sure: but issue reported by valgrind with the use of MPI_Unpack)
366 char* name = new char[nameSize+1];
367 std::fill(name,name+nameSize+1,0);
369 name,nameSize,MPI::CHAR,comm);
370 const G4String colname(name,nameSize);
371 delete[] name;
372 //This memory churn is very inefficient, but we cannot reuse the HitMap
373 //because we cannot change the names
374 //TODO: Evaluate change in HitMap class to allow for change of names
375 //HitMap* hm = UnPackHitMap(detName,colname);
376 HitStatDoubleMap* hm = UnPackHitStatDoubleMap(detName,colname);
377 inmesh->Accumulate(hm);
378 delete hm;
379 }
380}
HitStatDoubleMap * UnPackHitStatDoubleMap(const G4String &detName, const G4String &colName)

◆ Pack() [3/3]

void G4MPIscorerMerger::Pack ( const HitStatDoubleMap sm)
protected

Pack a single score map.

Definition at line 408 of file G4MPIscorerMerger.cc.

408 {
409 assert(sm!=nullptr);
410 assert(outputBuffer!=nullptr);
412 DMSG(3,"Packing hitmap: "<<sm<<" with: "<<sm->GetSize()<<" elements.");
413 /*const*/ size_t numEl = sm->GetSize();//TODO: old MPI implementation
414 MPI_Pack(&numEl,1,MPI::UNSIGNED,
417 const auto& theMap = *sm->GetMap();
418 std::vector<G4int> ids;
419 std::transform(theMap.begin(),theMap.end(),std::back_inserter(ids),
420 [](decltype(*theMap.begin())& e){ return e.first;});
421 assert(/*ids.size()==vals.size()&&*/ids.size()==numEl);
422 MPI_Pack(ids.data(),ids.size(),MPI::INT,outputBuffer,outputBufferSize,
424 for( const auto& e : theMap) {
425 const MPIStatDouble sd(*e.second,verbose);
427 }
428}

◆ UnPackHitStatDoubleMap()

HitStatDoubleMap * G4MPIscorerMerger::UnPackHitStatDoubleMap ( const G4String detName,
const G4String colName 
)
protected

Definition at line 451 of file G4MPIscorerMerger.cc.

453{
454 assert(outputBuffer!=nullptr);
456 DMSG(3,"Preparing to unpack a hit map for: "<<detName<<","<<colName);
457 size_t numEl =0 ;
459 &numEl,1,MPI::UNSIGNED,comm);
460 DMSG(3,"Will receive "<<numEl<<" values");
461 G4int* ids = new G4int[numEl];
463 ids,numEl,MPI::INT,comm);
464 HitStatDoubleMap* result = new HitStatDoubleMap(detName,colName);
465 for ( unsigned int i = 0; i<numEl;++i) {
466 MPIStatDouble sd(verbose);
468 result->set(ids[i],sd);
469 }
470 delete[] ids;
471 return result;
472}
G4THitsMap< G4StatDouble > HitStatDoubleMap

◆ CalculatePackSize() [1/3]

G4int G4MPIscorerMerger::CalculatePackSize ( const G4ScoringManager sm) const
protected

Definition at line 475 of file G4MPIscorerMerger.cc.

476{
477 DMSG(3,"Calculating dimension of data to send");
478 if ( sm == nullptr ) return 0;
479 //Calcualte how much data each call to Pack* appends to the buffer
480 //e.g. sizeof(data)
481 //The number of sizeof here should match the number of calls to MPI_Pack
482
483 //Pack(ScoringMgr)
484 G4int size = sizeof(unsigned int);
485 DMSG(3,"There are "<<sm->GetNumberOfMesh()<<" meshes.");
486 //Loop on mesh
487 for ( size_t i = 0 ; i<sm->GetNumberOfMesh() ; ++i ) {
488 size += sizeof(unsigned int);//ID
489 size += CalculatePackSize(sm->GetMesh(i));
490 }
491 return size;
492}
G4int CalculatePackSize(const G4ScoringManager *) const

◆ CalculatePackSize() [2/3]

G4int G4MPIscorerMerger::CalculatePackSize ( const G4VScoringMesh mesh) const
protected

Definition at line 494 of file G4MPIscorerMerger.cc.

495{
496 DMSG(3,"Calculating size for mesh: "<<mesh);
497 //PackSingleMesh(Mesh)
498 G4int size = sizeof(unsigned int);//num maps
499 auto map = mesh->GetScoreMap();
500 for (const auto& ele : map ) {
501 //PackHitsMap
502 size += sizeof(unsigned int);//name size
503 const G4String& name = ele.first;
504 size += sizeof(char)*name.size();//name
505 size += CalculatePackSize(ele.second);
506 }
507 DMSG(3,"mesh "<<mesh<<" size: "<<size);
508 return size;
509}

◆ CalculatePackSize() [3/3]

G4int G4MPIscorerMerger::CalculatePackSize ( const HitStatDoubleMap map) const
protected

Definition at line 520 of file G4MPIscorerMerger.cc.

520 {
521 const G4int numEls = map->GetSize();
522 G4int size = sizeof(unsigned int);
523 size += sizeof(G4int)*numEls;
524 //G4StatDouble: 5 doubles and 1 int
525 //Can I use sizeof(G4StatDouble)? NO sizeof(G4StatDouble)==56
526 size += numEls*(sizeof(G4double)*5+sizeof(G4int));
527 DMSG(3,"HitStatDoubleMap "<<map<<" size: "<<size<<" in "<<numEls<<" elements.");
528 return size;
529}

◆ Send()

void G4MPIscorerMerger::Send ( const unsigned int  destination)
protected

Definition at line 233 of file G4MPIscorerMerger.cc.

233 {
234 DMSG(1,"Sending scorers "<<this);
235 //Step 1: Setup buffer to pack/unpack data
236 const G4int newbuffsize = CalculatePackSize(scoringManager);
237 //DestroyBuffer();
238 char* buffer = outputBuffer;
239 if ( newbuffsize > outputBufferSize ) {
240 delete[] outputBuffer;
241 buffer = new char[newbuffsize];
242 //Avoid complains from valgrind (i'm not really sure why this is needed, but, beside the
243 //small cpu penalty, we can live with that).)
244 std::fill( buffer , buffer+newbuffsize,0);
245 ownsBuffer = true;
246 }
247 SetupOutputBuffer(buffer,newbuffsize,0);
248 DMSG(3,"Buffer Size: "<<newbuffsize<< " bytes at: "<<(void*)outputBuffer);
251
252 //Version 1: p2p communication
253 comm.Send(outputBuffer, outputBufferSize, MPI::PACKED, destination, G4MPImanager::kTAG_CMDSCR);
254 bytesSent += newbuffsize;
255 //Receiver should use probe to get size of the package being sent
256 DMSG(1,"Sending done");
257}
void SetupOutputBuffer(char *buff, G4int size, G4int position)

◆ Receive()

void G4MPIscorerMerger::Receive ( const unsigned int  source)
protected

Definition at line 205 of file G4MPIscorerMerger.cc.

205 {
206 DMSG(1,"Receiving scorers");
207 // DestroyBuffer();
208 DMSG(2,"Receiving from: "<<source);
209 MPI::Status status;
210 comm.Probe(source, G4MPImanager::kTAG_CMDSCR, status);
211 const G4int newbuffsize = status.Get_count(MPI::PACKED);
212 DMSG(2,"Preparing to receive buffer of size: "<<newbuffsize);
213 char* buffer = outputBuffer;
214 if ( newbuffsize > outputBufferSize ) {
215 DMSG(3,"New larger buffer expected, resize");
216 //New larger buffer incoming, recreate buffer
217 //TODO: use realloc?
218 delete[] outputBuffer;
219 buffer = new char[newbuffsize];
220 //Avoid complains from valgrind (i'm not really sure why this is needed, but, beside the
221 //small cpu penalty, we can live with that).)
222 std::fill( buffer , buffer + newbuffsize , 0 );
223 ownsBuffer = true;
224 }
225 SetupOutputBuffer(buffer,newbuffsize,0);
226 comm.Recv(buffer, newbuffsize, MPI::PACKED, source,
228 DMSG(3,"Buffer Size: "<<outputBufferSize<< " bytes at: "<<(void*)outputBuffer);
230 DMSG(1,"Receiving of comamnd line scorers done");
231}

Member Data Documentation

◆ outputBuffer

char* G4MPIscorerMerger::outputBuffer
private

Definition at line 95 of file G4MPIscorerMerger.hh.

◆ outputBufferSize

G4int G4MPIscorerMerger::outputBufferSize
private

Definition at line 96 of file G4MPIscorerMerger.hh.

◆ outputBufferPosition

G4int G4MPIscorerMerger::outputBufferPosition
private

Definition at line 97 of file G4MPIscorerMerger.hh.

◆ bytesSent

long G4MPIscorerMerger::bytesSent
private

Definition at line 98 of file G4MPIscorerMerger.hh.

◆ ownsBuffer

G4bool G4MPIscorerMerger::ownsBuffer
private

Definition at line 99 of file G4MPIscorerMerger.hh.

◆ scoringManager

G4ScoringManager* G4MPIscorerMerger::scoringManager
private

Definition at line 100 of file G4MPIscorerMerger.hh.

◆ commSize

unsigned int G4MPIscorerMerger::commSize
private

Definition at line 101 of file G4MPIscorerMerger.hh.

◆ destinationRank

unsigned int G4MPIscorerMerger::destinationRank
private

Definition at line 102 of file G4MPIscorerMerger.hh.

◆ comm

MPI::Intracomm G4MPIscorerMerger::comm
private

Definition at line 103 of file G4MPIscorerMerger.hh.

◆ verbose

G4int G4MPIscorerMerger::verbose
private

Definition at line 104 of file G4MPIscorerMerger.hh.


The documentation for this class was generated from the following files:

Applications | User Support | Publications | Collaboration