source: trunk/examples/extended/parallel/MPI/mpi_interface/src/G4MPImanager.cc@ 1347

Last change on this file since 1347 was 1337, checked in by garnier, 15 years ago

tag geant4.9.4 beta 1 + modifs locales

File size: 16.5 KB
Line 
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// $Id: G4MPImanager.cc,v 1.2 2010/05/18 06:06:21 kmura Exp $
27// $Name: geant4-09-04-beta-01 $
28//
29// ====================================================================
30// G4MPImanager.cc
31//
32// 2007 Q
33// ====================================================================
34#include "G4MPImanager.hh"
35#include "G4MPImessenger.hh"
36#include "G4MPIsession.hh"
37#include "G4MPIbatch.hh"
38#include "G4MPIstatus.hh"
39#include "G4MPIrandomSeedGenerator.hh"
40#include "G4UImanager.hh"
41#include "G4RunManager.hh"
42#include "G4StateManager.hh"
43#include "G4Run.hh"
44#include <time.h>
45#include <stdio.h>
46#include <getopt.h>
47
48G4MPImanager* G4MPImanager::theManager= 0;
49
50// ====================================================================
51// wrappers for thread functions
52// ====================================================================
53
54////////////////////////////////////////////////////////////////
55static void thread_ExecuteThreadCommand(const G4String* command)
56////////////////////////////////////////////////////////////////
57{
58 G4MPImanager::GetManager()-> ExecuteThreadCommand(*command);
59}
60
61
62// ====================================================================
63//
64// class description
65//
66// ====================================================================
67
68////////////////////////////
69G4MPImanager::G4MPImanager()
70 : verbose(0),
71 qfcout(false),
72 qinitmacro(false),
73 qbatchmode(false),
74 threadID(0),
75 masterWeight(1.)
76////////////////////////////
77{
78 //MPI::Init();
79 MPI::Init_thread(MPI::THREAD_SERIALIZED);
80 Initialize();
81}
82
83
84/////////////////////////////////////////////////
85G4MPImanager::G4MPImanager(int argc, char** argv)
86 : verbose(0), qfcout(false),
87 qinitmacro(false), qbatchmode(false),
88 threadID(0),
89 masterWeight(1.)
90/////////////////////////////////////////////////
91{
92 //MPI::Init(argc, argv);
93 MPI::Init_thread(argc, argv, MPI::THREAD_SERIALIZED);
94 Initialize();
95 ParseArguments(argc, argv);
96}
97
98
99/////////////////////////////
100G4MPImanager::~G4MPImanager()
101/////////////////////////////
102{
103 if(isSlave && qfcout) fscout.close();
104
105 delete status;
106 delete messenger;
107 delete session;
108
109 COMM_G4COMMAND.Free();
110
111 MPI::Finalize();
112
113 theManager= 0;
114}
115
116
117////////////////////////////////////////
118G4MPImanager* G4MPImanager::GetManager()
119////////////////////////////////////////
120{
121 if(theManager==0) {
122 G4Exception("G4MPImanager is not created.");
123 }
124 return theManager;
125}
126
127
128///////////////////////////////
129void G4MPImanager::Initialize()
130///////////////////////////////
131{
132 if(theManager != 0) {
133 G4Exception("G4MPImanager is constructed twice.");
134 }
135 theManager= this;
136
137 // get rank information
138 size= MPI::COMM_WORLD.Get_size();
139 rank= MPI::COMM_WORLD.Get_rank();
140 isMaster= (rank == RANK_MASTER);
141 isSlave= (rank != RANK_MASTER);
142
143 // initialize MPI communicator
144 COMM_G4COMMAND= MPI::COMM_WORLD.Dup();
145
146 // new G4MPI stuffs
147 messenger= new G4MPImessenger(this);
148
149 session= new G4MPIsession;
150
151 status= new G4MPIstatus;
152
153 // default seed generator is random generator.
154 seedGenerator= new G4MPIrandomSeedGenerator;
155 DistributeSeeds();
156
157}
158
159
160////////////////////////////////////////////////////////
161void G4MPImanager::ParseArguments(int argc, char** argv)
162////////////////////////////////////////////////////////
163{
164 G4int qhelp= 0;
165 G4String ofprefix="mpi";
166
167 G4int c;
168 while (1) {
169 G4int option_index= 0;
170 static struct option long_options[] = {
171 {"help", 0, 0, 0},
172 {"verbose", 0, 0, 0},
173 {"init", 1, 0, 0},
174 {"ofile", 2, 0, 0},
175 {0, 0, 0, 0}
176 };
177
178 opterr= 0; // suppress message
179 c= getopt_long(argc, argv, "hvi:o", long_options, &option_index);
180 opterr= 1;
181
182 if(c == -1) break;
183
184 switch (c) {
185 case 0:
186 switch(option_index) {
187 case 0 : // --help
188 qhelp= 1;
189 break;
190 case 1 : // --verbose
191 verbose= 1;
192 break;
193 case 2 : // --init
194 qinitmacro= true;
195 initFileName= optarg;
196 break;
197 case 3 : // --ofile
198 qfcout= true;
199 if(optarg) ofprefix= optarg;
200 break;
201 }
202 break;
203 case 'h' :
204 qhelp=1;
205 break;
206 case 'v' :
207 verbose= 1;
208 break;
209 case 'i' :
210 qinitmacro= true;
211 initFileName= optarg;
212 break;
213 case 'o' :
214 qfcout= true;
215 break;
216 default:
217 break;
218 }
219 }
220
221 // show help
222 if(qhelp) {
223 if(isMaster) ShowHelp();
224 MPI::Finalize();
225 exit(0);
226 }
227
228 // file output
229 if(isSlave && qfcout) {
230 G4String prefix= ofprefix+".%03d"+".cout";
231 char str[1024];
232 sprintf(str, prefix.c_str(), rank);
233 G4String fname(str);
234 fscout.open(fname.c_str(), std::ios::out);
235 }
236
237 // non-option ARGV-elements ...
238 if (optind < argc ) {
239 qbatchmode= true;
240 macroFileName= argv[optind];
241 }
242}
243
244
245//////////////////////////////////////////
246void G4MPImanager::Wait(G4int ausec) const
247//////////////////////////////////////////
248{
249 struct timespec treq, trem;
250 treq.tv_sec = 0;
251 treq.tv_nsec = ausec*1000;
252
253 nanosleep(&treq, &trem);
254}
255
256// ====================================================================
257
258/////////////////////////////////
259void G4MPImanager::UpdateStatus()
260/////////////////////////////////
261{
262 G4RunManager* runManager= G4RunManager::GetRunManager();
263 const G4Run* run= runManager-> GetCurrentRun();
264
265 G4int runid, eventid, neventTBP;
266
267 G4StateManager* stateManager= G4StateManager::GetStateManager();
268 G4ApplicationState g4state= stateManager-> GetCurrentState();
269
270 if (run) {
271 runid= run-> GetRunID();
272 neventTBP= run -> GetNumberOfEventToBeProcessed();
273 eventid= run-> GetNumberOfEvent();
274 if(g4state == G4State_GeomClosed || g4state == G4State_EventProc) {
275 status-> StopTimer();
276 }
277 } else {
278 runid= 0;
279 eventid= 0;
280 neventTBP= 0;
281 }
282
283 status-> SetStatus(rank, runid, neventTBP, eventid, g4state);
284}
285
286
287///////////////////////////////
288void G4MPImanager::ShowStatus()
289///////////////////////////////
290{
291 G4int buff[G4MPIstatus::NSIZE];
292
293 UpdateStatus();
294 G4bool gstatus= CheckThreadStatus();
295
296 if(isMaster) {
297 status-> Print(); // for maser itself
298
299 G4int nev= status-> GetEventID();
300 G4int nevtp= status-> GetNEventToBeProcessed();
301 G4double cputime= status-> GetCPUTime();
302
303 // receive from each slave
304 for (G4int islave=1; islave< size; islave++) {
305 COMM_G4COMMAND.Recv(buff, G4MPIstatus::NSIZE, MPI::INT,
306 islave, TAG_G4STATUS);
307 status-> UnPack(buff);
308 status-> Print();
309
310 // aggregation
311 nev+= status-> GetEventID();
312 nevtp+= status-> GetNEventToBeProcessed();
313 cputime+= status-> GetCPUTime();
314 }
315
316 G4String strStatus;
317 if(gstatus) {
318 strStatus= "Run";
319 } else {
320 strStatus= "Idle";
321 }
322
323 G4cout << "-------------------------------------------------------"
324 << G4endl
325 << "* #ranks= " << size
326 << " event= " << nev << "/" << nevtp
327 << " state= " << strStatus
328 << " time= " << cputime << "s"
329 << G4endl;
330 } else {
331 status-> Pack(buff);
332 COMM_G4COMMAND.Send(buff, G4MPIstatus::NSIZE, MPI::INT,
333 RANK_MASTER, TAG_G4STATUS);
334 }
335}
336
337// ====================================================================
338
339////////////////////////////////////
340void G4MPImanager::DistributeSeeds()
341////////////////////////////////////
342{
343 std::vector<G4long> seedList= seedGenerator-> GetSeedList();
344 CLHEP::HepRandom::setTheSeed(seedList[rank]);
345}
346
347
348//////////////////////////////
349void G4MPImanager::ShowSeeds()
350//////////////////////////////
351{
352 G4long buff;
353
354 if(isMaster) {
355 // print master
356 G4cout << "* rank= " << rank
357 << " seed= " << CLHEP::HepRandom::getTheSeed()
358 << G4endl;
359 // receive from each slave
360 for (G4int islave=1; islave< size; islave++) {
361 COMM_G4COMMAND.Recv(&buff, 1, MPI::LONG, islave, TAG_G4SEED);
362 G4cout << "* rank= " << islave
363 << " seed= " << buff
364 << G4endl;
365 }
366 } else { // slaves
367 buff= CLHEP::HepRandom::getTheSeed();
368 COMM_G4COMMAND.Send(&buff, 1, MPI::LONG, RANK_MASTER, TAG_G4SEED);
369 }
370}
371
372
373////////////////////////////////////////////////////
374void G4MPImanager::SetSeed(G4int inode, G4long seed)
375////////////////////////////////////////////////////
376{
377 if(rank==inode) {
378 CLHEP::HepRandom::setTheSeed(seed);
379 }
380}
381
382// ====================================================================
383
384////////////////////////////////////////
385G4bool G4MPImanager::CheckThreadStatus()
386////////////////////////////////////////
387{
388 unsigned buff;
389 G4bool qstatus= false;
390
391 if(isMaster) {
392 qstatus= threadID;
393 // get slave status
394 for (G4int islave=1; islave< size; islave++) {
395 MPI::Request request= COMM_G4COMMAND.Irecv(&buff, 1, MPI::UNSIGNED,
396 islave, TAG_G4STATUS);
397 MPI::Status status;
398 while(! request.Test(status)) {
399 Wait(100);
400 }
401 qstatus |= buff;
402 }
403 } else {
404 buff= unsigned(threadID);
405 COMM_G4COMMAND.Send(&buff, 1, MPI::UNSIGNED, RANK_MASTER, TAG_G4STATUS);
406 }
407
408 // broadcast
409 buff= qstatus; // for master
410 COMM_G4COMMAND.Bcast(&buff, 1, MPI::UNSIGNED, RANK_MASTER);
411 qstatus= buff; // for slave
412
413 return qstatus;
414}
415
416
417////////////////////////////////////////////////////////////////
418void G4MPImanager::ExecuteThreadCommand(const G4String& command)
419////////////////////////////////////////////////////////////////
420{
421 // this method is a thread function.
422 G4UImanager* UI= G4UImanager::GetUIpointer();
423 G4int rc= UI-> ApplyCommand(command);
424
425 G4int commandStatus = rc - (rc%100);
426
427 switch(commandStatus) {
428 case fCommandSucceeded:
429 break;
430 case fIllegalApplicationState:
431 G4cerr << "illegal application state -- command refused" << G4endl;
432 break;
433 default:
434 G4cerr << "command refused (" << commandStatus << ")" << G4endl;
435 break;
436 }
437
438 // thread is joined
439 if(threadID) {
440 pthread_join(threadID, 0);
441 threadID= 0;
442 }
443
444 return;
445}
446
447
448///////////////////////////////////////////////////////////////
449void G4MPImanager::ExecuteBeamOnThread(const G4String& command)
450///////////////////////////////////////////////////////////////
451{
452 G4bool threadStatus= CheckThreadStatus();
453
454 if (threadStatus) {
455 if(isMaster) {
456 G4cout << "G4MPIsession:: beamOn is still running." << G4endl;
457 }
458 } else { // ok
459 static G4String cmdstr;
460 cmdstr= command;
461 G4int rc= pthread_create(&threadID, 0,
462 (Func_t)thread_ExecuteThreadCommand,
463 (void*)&cmdstr);
464 if (rc != 0)
465 G4Exception("G4MPIsession:: failed to create a beamOn thread.");
466 }
467}
468
469
470/////////////////////////////////////
471void G4MPImanager::JoinBeamOnThread()
472/////////////////////////////////////
473{
474 if(threadID) {
475 pthread_join(threadID, 0);
476 threadID= 0;
477 }
478}
479
480
481// ====================================================================
482
483////////////////////////////////////////////////////////////
484G4String G4MPImanager::BcastCommand(const G4String& command)
485////////////////////////////////////////////////////////////
486{
487 enum { BUFF_SIZE= 512 };
488 static char sbuff[BUFF_SIZE];
489 command.copy(sbuff,BUFF_SIZE);
490 G4int len= command.size();
491 sbuff[len]='\0'; // no boundary check
492
493 // "command" is not yet fixed in slaves at this time.
494
495 // waiting message exhausts CPU in LAM!
496 //COMM_G4COMMAND.Bcast(sbuff, ssize, MPI::CHAR, RANK_MASTER);
497
498 // another implementation
499 if( isMaster ) {
500 for (G4int islave=1; islave< size; islave++) {
501 COMM_G4COMMAND.Send(sbuff, BUFF_SIZE, MPI::CHAR, islave, TAG_G4COMMAND);
502 }
503 } else {
504 // try non-blocking receive
505 MPI::Request request= COMM_G4COMMAND.Irecv(sbuff, BUFF_SIZE, MPI::CHAR,
506 RANK_MASTER, TAG_G4COMMAND);
507 // polling...
508 MPI::Status status;
509 while(! request.Test(status)) {
510 Wait(100);
511 }
512 }
513
514 return G4String(sbuff);
515}
516
517// ====================================================================
518
519/////////////////////////////////////////////////////////////////////////
520void G4MPImanager::ExecuteMacroFile(const G4String& fname, G4bool qbatch)
521/////////////////////////////////////////////////////////////////////////
522{
523 G4bool currentmode= qbatchmode;
524 qbatchmode= true;
525 G4MPIbatch* batchSession= new G4MPIbatch(fname, qbatch);
526 batchSession-> SessionStart();
527 delete batchSession;
528 qbatchmode= currentmode;
529}
530
531
532///////////////////////////////////////////////////////
533void G4MPImanager::BeamOn(G4int nevent, G4bool qdivide)
534///////////////////////////////////////////////////////
535{
536 G4RunManager* runManager= G4RunManager::GetRunManager();
537
538 if(qdivide) { // events are divided
539 G4double ntot= masterWeight+size-1.;
540 G4int nproc= G4int(nevent/ntot);
541 G4int nproc0= nevent-nproc*(size-1);
542
543 if(verbose>0 && isMaster) {
544 G4cout << "#events in master=" << nproc0 << " / "
545 << "#events in slave=" << nproc << G4endl;
546 }
547
548 status-> StartTimer(); // start timer
549 if(isMaster) runManager-> BeamOn(nproc0);
550 else runManager-> BeamOn(nproc);
551 status-> StopTimer(); // stop timer
552
553 } else { // same events are generated in each node (for test use)
554 if(verbose>0 && isMaster) {
555 G4cout << "#events in master=" << nevent << " / "
556 << "#events in slave=" << nevent << G4endl;
557 }
558 status-> StartTimer(); // start timer
559 runManager-> BeamOn(nevent);
560 status-> StopTimer(); // stop timer
561 }
562}
563
564///////////////////////////////
565void G4MPImanager::WaitBeamOn()
566///////////////////////////////
567{
568 G4int buff= 0;
569 if (qbatchmode) { // valid only in batch mode
570 if(isMaster) {
571 // receive from each slave
572 for (G4int islave=1; islave< size; islave++) {
573 MPI::Request request= COMM_G4COMMAND.Irecv(&buff, 1, MPI::INT,
574 islave, TAG_G4STATUS);
575 MPI::Status status;
576 while(! request.Test(status)) {
577 Wait(1000);
578 }
579 }
580 } else {
581 buff= 1;
582 COMM_G4COMMAND.Send(&buff, 1, MPI::INT, RANK_MASTER, TAG_G4STATUS);
583 }
584 }
585}
586
587/////////////////////////////////////////////////
588void G4MPImanager::Print(const G4String& message)
589/////////////////////////////////////////////////
590{
591 if(isMaster){
592 std::cout << message << std::flush;
593 } else {
594 if(qfcout) { // output to a file
595 fscout << message << std::flush;
596 } else { // output to stdout
597 std::cout << rank << ":" << message << std::flush;
598 }
599 }
600}
601
602
603///////////////////////////////////
604void G4MPImanager::ShowHelp() const
605///////////////////////////////////
606{
607 if(isSlave) return;
608
609 G4cout << "Geant4 MPI interface" << G4endl;
610 G4cout << "usage:" << G4endl;
611 G4cout << "<app> [options] [macro file]"
612 << G4endl << G4endl;
613 G4cout << " -h, --help show this message."
614 << G4endl;
615 G4cout << " -v, --verbose show verbose message"
616 << G4endl;
617 G4cout << " -i, --init=FNAME set an init macro file"
618 << G4endl;
619 G4cout << " -o, --ofile[=FNAME] set slave output to a flie"
620 << G4endl;
621 G4cout << G4endl;
622
623}
624
Note: See TracBrowser for help on using the repository browser.