Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4VoxelisationHelper Class Reference

G4VoxelisationHelper is a helper class to undertake voxelisation in parallel, aiding and off-loading the work of G4GeometryManager. More...

#include <G4VoxelisationHelper.hh>

Public Member Functions

 G4VoxelisationHelper ()
 ~G4VoxelisationHelper ()
void PrepareParallelOptimisation (G4bool allOpts, G4bool verbose)
void UndertakeOptimisation ()
void ReportVoxelInfo (G4LogicalVolume *logVolume, std::ostream &os)
void SetVerbosity (G4bool verbose)
G4bool IsParallelOptimisationFinished ()
G4int CheckOptimisation ()

Static Public Member Functions

static void ReportVoxelStats (std::vector< G4SmartVoxelStat > &stats, G4double totalCpuTime, std::ostream &os=G4cout)

Detailed Description

G4VoxelisationHelper is a helper class to undertake voxelisation in parallel, aiding and off-loading the work of G4GeometryManager.

Definition at line 59 of file G4VoxelisationHelper.hh.

Constructor & Destructor Documentation

◆ G4VoxelisationHelper()

G4VoxelisationHelper::G4VoxelisationHelper ( )

Constructor & Destructor.

Definition at line 42 of file G4VoxelisationHelper.cc.

43{
44 fWallClockTimer = new G4Timer;
45
46 ResetListOfVolumesToOptimise();
47}

◆ ~G4VoxelisationHelper()

G4VoxelisationHelper::~G4VoxelisationHelper ( )

Definition at line 49 of file G4VoxelisationHelper.cc.

50{
51 delete fWallClockTimer;
52}

Member Function Documentation

◆ CheckOptimisation()

G4int G4VoxelisationHelper::CheckOptimisation ( )

Check that volumes marked to optimise are done, and report number of those that are missing voxel header.

Definition at line 632 of file G4VoxelisationHelper.cc.

633{
634 unsigned int numErrors = 0;
635 for ( const auto& logical : fVolumesToOptimise )
636 {
637 if( logical->GetVoxelHeader() == nullptr ) { ++numErrors; }
638 }
639 return numErrors;
640}

Referenced by UndertakeOptimisation().

◆ IsParallelOptimisationFinished()

G4bool G4VoxelisationHelper::IsParallelOptimisationFinished ( )

Returns true if all workers are finished (or all work is done).

Definition at line 622 of file G4VoxelisationHelper.cc.

623{
624 G4AutoLock lock(&statResultsMutex);
625 return fParallelVoxelOptimisationFinished;
626}
G4TemplateAutoLock< G4Mutex > G4AutoLock

Referenced by UndertakeOptimisation().

◆ PrepareParallelOptimisation()

void G4VoxelisationHelper::PrepareParallelOptimisation ( G4bool allOpts,
G4bool verbose )

Key method that creates a list of volumes and resets the state to prepare for the parallel optimisation.

Definition at line 154 of file G4VoxelisationHelper.cc.

155{
156 if( verbose )
157 {
158 G4cout << "** G4VoxelisationHelper::PrepareParallelOptimisation() called."
159 << " LEAVING all the work (of voxel optimisation) to the threads/tasks !"
160 << G4endl;
161 }
162 CreateListOfVolumesToOptimise(allOpts, verbose);
163 ReSetParallelOptimisation(verbose);
164}
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout

◆ ReportVoxelInfo()

void G4VoxelisationHelper::ReportVoxelInfo ( G4LogicalVolume * logVolume,
std::ostream & os )

Definition at line 490 of file G4VoxelisationHelper.cc.

491{
492 G4SmartVoxelHeader* head = logVolume->GetVoxelHeader();
493 if( head != nullptr )
494 {
495 os << "** Created optimisations for logical-volume '"
496 << std::setw(50) << logVolume->GetName() << "'" << G4endl
497 << "- Result VoxelInfo - START: " << " ptr= " << head << G4endl
498 << *head
499 << "- Result VoxelInfo - END. " << G4endl;
500 }
501 else
502 {
503 os << "** No optimisation for log-vol " << logVolume->GetName() << G4endl;
504 }
505 os << "*** Report Voxel Info: END " << G4endl;
506}
const G4String & GetName() const
G4SmartVoxelHeader * GetVoxelHeader() const

◆ ReportVoxelStats()

void G4VoxelisationHelper::ReportVoxelStats ( std::vector< G4SmartVoxelStat > & stats,
G4double totalCpuTime,
std::ostream & os = G4cout )
static

Methods to report statistics on the voxelisation process.

Definition at line 513 of file G4VoxelisationHelper.cc.

516{
517 os << "--------------------------------------------------------------------------------"
518 << G4endl;
519 os << "G4VoxelisationHelper::ReportVoxelStats -- Voxel Statistics"
520 << G4endl << G4endl;
521
522 //
523 // Get total memory use
524 //
525 G4int i, nStat = (G4int)stats.size();
526 G4long totalMemory = 0;
527
528 for( i=0; i<nStat; ++i ) { totalMemory += stats[i].GetMemoryUse(); }
529
530 os << " Total memory consumed for geometry optimisation: "
531 << totalMemory/1024 << " kByte" << G4endl;
532 os << " Total CPU time elapsed for geometry optimisation: "
533 << std::setprecision(4) << totalCpuTime << " seconds"
534 << std::setprecision(6) << G4endl;
535
536 //
537 // First list: sort by total CPU time
538 //
539 std::sort( stats.begin(), stats.end(),
540 [](const G4SmartVoxelStat& a, const G4SmartVoxelStat& b)
541 {
542 return a.GetTotalTime() > b.GetTotalTime();
543 } );
544
545 const G4int maxPrint = 20;
546 G4int nPrint = std::min ( nStat, maxPrint );
547
548 if (nPrint != 0)
549 {
550 os << "\n Voxelisation: top CPU users:" << G4endl;
551 os << " Percent Total CPU System CPU Memory Volume\n"
552 << " ------- ---------- ---------- -------- ----------"
553 << G4endl;
554 }
555
556 for(i=0; i<nPrint; ++i)
557 {
558 G4double total = stats[i].GetTotalTime();
559 G4double system = stats[i].GetSysTime();
560 G4double perc = 0.0;
561
562 if (system < 0) { system = 0.0; }
563 if ((total < 0) || (totalCpuTime < CLHEP::perMillion))
564 { total = 0; }
565 else
566 { perc = total*100/totalCpuTime; }
567
568 os << std::setprecision(2)
569 << std::setiosflags(std::ios::fixed|std::ios::right)
570 << std::setw(11) << perc
571 << std::setw(13) << total
572 << std::setw(13) << system
573 << std::setw(13) << (stats[i].GetMemoryUse()+512)/1024
574 << "k " << std::setiosflags(std::ios::left)
575 << stats[i].GetVolume()->GetName()
576 << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
577 << std::setprecision(6)
578 << G4endl;
579 }
580
581 //
582 // Second list: sort by memory use
583 //
584 std::sort( stats.begin(), stats.end(),
585 [](const G4SmartVoxelStat& a, const G4SmartVoxelStat& b)
586 {
587 return a.GetMemoryUse() > b.GetMemoryUse();
588 } );
589
590 if (nPrint != 0)
591 {
592 os << "\n Voxelisation: top memory users:" << G4endl;
593 os << " Percent Memory Heads Nodes Pointers Total CPU Volume\n"
594 << " ------- -------- ------ ------ -------- ---------- ----------"
595 << G4endl;
596 }
597
598 for(i=0; i<nPrint; ++i)
599 {
600 G4long memory = stats[i].GetMemoryUse();
601 G4double totTime = stats[i].GetTotalTime();
602 if (totTime < 0) { totTime = 0.0; }
603
604 os << std::setprecision(2)
605 << std::setiosflags(std::ios::fixed|std::ios::right)
606 << std::setw(11) << G4double(memory*100)/G4double(totalMemory)
607 << std::setw(11) << memory/1024 << "k "
608 << std::setw( 9) << stats[i].GetNumberHeads()
609 << std::setw( 9) << stats[i].GetNumberNodes()
610 << std::setw(11) << stats[i].GetNumberPointers()
611 << std::setw(13) << totTime << " "
612 << std::setiosflags(std::ios::left)
613 << stats[i].GetVolume()->GetName()
614 << std::resetiosflags(std::ios::floatfield|std::ios::adjustfield)
615 << std::setprecision(6)
616 << G4endl;
617 }
618 os << "--------------------------------------------------------------------------------"
619 << G4endl << G4endl;
620}
double G4double
Definition G4Types.hh:83
long G4long
Definition G4Types.hh:87
int G4int
Definition G4Types.hh:85
G4double total(Particle const *const p1, Particle const *const p2)

Referenced by UndertakeOptimisation().

◆ SetVerbosity()

void G4VoxelisationHelper::SetVerbosity ( G4bool verbose)
inline

Sets verbosity mode.

Definition at line 95 of file G4VoxelisationHelper.hh.

95{ fVerboseParallel = verbose; }

◆ UndertakeOptimisation()

void G4VoxelisationHelper::UndertakeOptimisation ( )

Contributes to voxel optimisation until all work is done. To be called by a worker thread initialisation, not by the user.

Definition at line 195 of file G4VoxelisationHelper.cc.

196{
197 G4bool verbose = fVerboseParallel;
198 G4LogicalVolume* logVolume = nullptr;
199
200 // Use a mutex to protect parallel writes, but may be better to use atomic,
201 // or do away with this entirely since it's not practically used?
202 {
203 G4AutoLock uo_lock(&statResultsMutex);
204 fParallelVoxelOptimisationUnderway = true;
205 }
206
207 // Start timer - if not already done
208 if( ( !fWallClockStarted ) && verbose )
209 {
210 G4AutoLock startTimeLock(wallClockTimerMutex);
211 if( !fWallClockStarted )
212 {
213 fWallClockTimer->Start();
214 fWallClockStarted= true;
215 }
216 }
217
218 G4Timer fetimer;
219 unsigned int numVolumesOptimised = 0;
220
221 while( (logVolume = ObtainVolumeToOptimise()) != nullptr )
222 {
223 if (verbose) fetimer.Start();
224
225 G4SmartVoxelHeader* head = logVolume->GetVoxelHeader();
226 delete head;
227 logVolume->SetVoxelHeader(nullptr);
228
229 head = new G4SmartVoxelHeader(logVolume);
230 // *********************************
231 logVolume->SetVoxelHeader(head);
232
233 if (head != nullptr)
234 {
235 ++numVolumesOptimised;
236 }
237 else
238 {
240 message << "VoxelHeader allocation error." << G4endl
241 << "Allocation of new VoxelHeader" << G4endl
242 << "for logical volume " << logVolume->GetName() << " failed.";
243 G4Exception("G4VoxelisationHelper::BuildOptimisationsParallel()",
244 "GeomMgt0003", FatalException, message);
245 }
246
247 if(verbose)
248 {
249 fetimer.Stop();
250 auto feRealElapsed = fetimer.GetRealElapsed();
251 // Must use 'real' elapsed time -- cannot trust user/system time
252 // (it accounts for all threads)
253
254 G4AutoLock lock(voxelStatsMutex);
255 fGlobVoxelStats.emplace_back( logVolume, head,
256 0.0, // Cannot estimate system time
257 feRealElapsed ); // Use real time instead of user time
258 fSumVoxelTime += feRealElapsed;
259 }
260 }
261
262 G4bool allDone = false;
263 G4int myCount= -1;
264
265 myCount = ReportWorkerIsDoneOptimising(numVolumesOptimised);
267
268 if( allDone && (myCount == G4Threading::GetNumberOfRunningWorkerThreads()) )
269 {
270 G4int badVolumes = CheckOptimisation(); // Check all voxels are created!
271 if( badVolumes > 0 )
272 {
274 errmsg <<" Expected that all voxelisation work is done, "
275 << "but found that voxels headers are missing in "
276 << badVolumes << " volumes.";
277 G4Exception("G4VoxelisationHelper::UndertakeOptimisation()",
278 "GeomMng002", FatalException, errmsg);
279 }
280
281 // Create report
282
283 if( verbose )
284 {
285 fWallClockTimer->Stop();
286
287 std::ostream& report_stream = std::cout; // G4cout; does not work!
288 report_stream << G4endl
289 << "G4VoxelisationHelper::UndertakeOptimisation"
290 << " -- Timing for Voxel Optimisation" << G4endl;
291 report_stream << " - Elapsed time (real) = " << std::setprecision(4)
292 << fWallClockTimer->GetRealElapsed() << "s (wall clock)"
293 << ", user " << fWallClockTimer->GetUserElapsed() << "s"
294 << ", system " << fWallClockTimer->GetSystemElapsed() << "s."
295 << G4endl;
296 report_stream << " - Sum voxel time (real) = " << fSumVoxelTime
297 << "s.";
298 report_stream << std::setprecision(6) << G4endl << G4endl;
299
300 ReportVoxelStats( fGlobVoxelStats, fSumVoxelTime, report_stream );
301 report_stream.flush();
302 }
303 }
304 else
305 {
306 WaitForVoxelisationFinish(false);
307 }
308}
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
bool G4bool
Definition G4Types.hh:86
void SetVoxelHeader(G4SmartVoxelHeader *pVoxel)
void Stop()
void Start()
G4double GetRealElapsed() const
Definition G4Timer.cc:113
static void ReportVoxelStats(std::vector< G4SmartVoxelStat > &stats, G4double totalCpuTime, std::ostream &os=G4cout)
G4int GetNumberOfRunningWorkerThreads()

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