46 ResetListOfVolumesToOptimise();
51 delete fWallClockTimer;
60void G4VoxelisationHelper::ReSetParallelOptimisation(
G4bool verbose)
64 G4cout <<
"** G4VoxelisationHelper::ReSetParallelOptimisation() called. "
65 <<
" All the work (of voxel optimisation) WAS LEFT to the threads/tasks !"
66 <<
G4endl <<
" Clearing the state for this work." <<
G4endl;
69 fParallelVoxelOptimisationUnderway =
false;
70 fParallelVoxelOptimisationFinished =
false;
73 fVerboseParallel = verbose;
77 fNumberThreadsReporting = 0;
78 fTotalNumberVolumesOptimised = 0;
80 fWallClockStarted =
false;
82 fLogVolumeIterator = fVolumesToOptimise.cbegin();
98G4VoxelisationHelper::CreateListOfVolumesToOptimise(
G4bool allOpts,
G4bool verbose)
104 if( !fVolumesToOptimise.empty() )
106 ResetListOfVolumesToOptimise();
109 for (
auto & n : *Store)
111 G4LogicalVolume* volume=
n;
119 fVolumesToOptimise.push_back(volume);
127#ifdef G4GEOMETRY_VOXELDEBUG
129 <<
" daughters and name = '" << volume->
GetName() <<
"' "
130 <<
" -- for optimisation (ie voxels will be built for it). " <<
G4endl;
135#ifdef G4GEOMETRY_VOXELDEBUG
137 <<
" daughters and name = '" << volume->
GetName() <<
"' " <<
G4endl;
143 G4cout <<
"** G4VoxelisationHelper::PrepareOptimisationWork: "
144 <<
" Number of volumes for voxelisation = "
145 << fVolumesToOptimise.size() <<
G4endl;
147 fLogVolumeIterator = fVolumesToOptimise.cbegin();
158 G4cout <<
"** G4VoxelisationHelper::PrepareParallelOptimisation() called."
159 <<
" LEAVING all the work (of voxel optimisation) to the threads/tasks !"
162 CreateListOfVolumesToOptimise(allOpts, verbose);
163 ReSetParallelOptimisation(verbose);
197 G4bool verbose = fVerboseParallel;
204 fParallelVoxelOptimisationUnderway =
true;
208 if( ( !fWallClockStarted ) && verbose )
210 G4AutoLock startTimeLock(wallClockTimerMutex);
211 if( !fWallClockStarted )
213 fWallClockTimer->Start();
214 fWallClockStarted=
true;
219 unsigned int numVolumesOptimised = 0;
221 while( (logVolume = ObtainVolumeToOptimise()) !=
nullptr )
223 if (verbose) fetimer.
Start();
235 ++numVolumesOptimised;
240 message <<
"VoxelHeader allocation error." <<
G4endl
241 <<
"Allocation of new VoxelHeader" <<
G4endl
242 <<
"for logical volume " << logVolume->
GetName() <<
" failed.";
243 G4Exception(
"G4VoxelisationHelper::BuildOptimisationsParallel()",
255 fGlobVoxelStats.emplace_back( logVolume, head,
258 fSumVoxelTime += feRealElapsed;
265 myCount = ReportWorkerIsDoneOptimising(numVolumesOptimised);
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()",
285 fWallClockTimer->Stop();
287 std::ostream& report_stream = std::cout;
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."
296 report_stream <<
" - Sum voxel time (real) = " << fSumVoxelTime
298 report_stream << std::setprecision(6) <<
G4endl <<
G4endl;
301 report_stream.flush();
306 WaitForVoxelisationFinish(
false);
323 if( fLogVolumeIterator != fVolumesToOptimise.cend() )
325 logVolume = *fLogVolumeIterator;
326 ++fLogVolumeIterator;
335void G4VoxelisationHelper::ResetListOfVolumesToOptimise()
339 std::vector<G4LogicalVolume*>().swap(fVolumesToOptimise);
344 assert(fVolumesToOptimise.empty());
345 fLogVolumeIterator = fVolumesToOptimise.cbegin();
347 fGlobVoxelStats.clear();
362G4VoxelisationHelper::ReportWorkerIsDoneOptimising(
unsigned int numVolumesOptimised)
365 G4int orderReporting;
368 orderReporting = ++fNumberThreadsReporting;
369 fTotalNumberVolumesOptimised += numVolumesOptimised;
371 if( fVerboseParallel )
372 std::cout <<
"G4GeometryManager: the " << orderReporting <<
" worker has finished. "
373 <<
" Total volumes voxelised = " << fTotalNumberVolumesOptimised
374 <<
" out of " << fVolumesToOptimise.size() <<
G4endl;
377 || fTotalNumberVolumesOptimised == fVolumesToOptimise.size()
384 if( fTotalNumberVolumesOptimised != fVolumesToOptimise.size() )
387 errmsg <<
" [thread " << tid <<
" ] "
388 <<
" WARNING: Number of volumes 'voxelised' = " << fTotalNumberVolumesOptimised
389 <<
" is not equal to the total number requested " << fVolumesToOptimise.size() <<
" !! " <<
G4endl;
390 G4Exception(
"G4GeometryManager::ReportWorkerIsDoneOptimising",
"G4GeomMgr0999",
394 if( fNumberThreadsReporting > TotalThreads )
397 errmsg <<
" [thread " << tid <<
" ] "
398 <<
" WARNING: Number of threads 'reporting' = " << fNumberThreadsReporting
399 <<
" exceeds the total number of threads " << TotalThreads <<
" !! " <<
G4endl
400 <<
" *Missed* calling the method ConfigureParallelOptimisation() to reset. ";
401 G4Exception(
"G4GeometryManager::ReportWorkerIsDoneOptimising",
"G4GeomMgr0999",
406 if( fTotalNumberVolumesOptimised == fVolumesToOptimise.size()
407 && ( fNumberThreadsReporting < TotalThreads ) )
410 errmsg <<
" [thread " << tid <<
" ] "
411 <<
" WARNING: All volumes optimised, yet only "
412 << fNumberThreadsReporting <<
" threads reported out of " << TotalThreads;
413 G4Exception(
"G4GeometryManager::ReportWorkerIsDoneOptimising",
"G4GeomMgr099",
422 RecordOptimisationIsFinished(fVerboseParallel);
426 return orderReporting;
433void G4VoxelisationHelper::RecordOptimisationIsFinished(
G4bool verbose)
437 std::cout <<
"** G4VoxelisationHelper: All voxel optimisation work is completed!"
439 std::cout <<
" Total number of volumes optimised = "
440 << fTotalNumberVolumesOptimised
441 <<
" of " << fVolumesToOptimise.size() <<
" expected\n";
442 std::cout <<
" Number of workers reporting = "
443 << fNumberThreadsReporting
447 assert ( fTotalNumberVolumesOptimised == fVolumesToOptimise.size() );
449 fParallelVoxelOptimisationFinished =
true;
451 fParallelVoxelOptimisationUnderway =
false;
459void G4VoxelisationHelper::WaitForVoxelisationFinish(
G4bool verbose)
462 using namespace std::chrono_literals;
463 unsigned int trials = 0;
466 std::ostream& out_stream = std::cout;
470 std::this_thread::sleep_for(250ms);
478 <<
"** UndertakeOptimisation done on tid= " << tid
479 <<
" after waiting for " << trials <<
" trials." <<
G4endl;
493 if( head !=
nullptr )
495 os <<
"** Created optimisations for logical-volume '"
497 <<
"- Result VoxelInfo - START: " <<
" ptr= " << head <<
G4endl
499 <<
"- Result VoxelInfo - END. " <<
G4endl;
503 os <<
"** No optimisation for log-vol " << logVolume->
GetName() <<
G4endl;
505 os <<
"*** Report Voxel Info: END " <<
G4endl;
517 os <<
"--------------------------------------------------------------------------------"
519 os <<
"G4VoxelisationHelper::ReportVoxelStats -- Voxel Statistics"
528 for( i=0; i<nStat; ++i ) { totalMemory += stats[i].GetMemoryUse(); }
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;
539 std::sort( stats.begin(), stats.end(),
542 return a.GetTotalTime() > b.GetTotalTime();
545 const G4int maxPrint = 20;
546 G4int nPrint = std::min ( nStat, maxPrint );
550 os <<
"\n Voxelisation: top CPU users:" <<
G4endl;
551 os <<
" Percent Total CPU System CPU Memory Volume\n"
552 <<
" ------- ---------- ---------- -------- ----------"
556 for(i=0; i<nPrint; ++i)
558 G4double total = stats[i].GetTotalTime();
559 G4double system = stats[i].GetSysTime();
562 if (system < 0) { system = 0.0; }
563 if ((total < 0) || (totalCpuTime < CLHEP::perMillion))
566 { perc = total*100/totalCpuTime; }
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)
584 std::sort( stats.begin(), stats.end(),
587 return a.GetMemoryUse() > b.GetMemoryUse();
592 os <<
"\n Voxelisation: top memory users:" <<
G4endl;
593 os <<
" Percent Memory Heads Nodes Pointers Total CPU Volume\n"
594 <<
" ------- -------- ------ ------ -------- ---------- ----------"
598 for(i=0; i<nPrint; ++i)
600 G4long memory = stats[i].GetMemoryUse();
601 G4double totTime = stats[i].GetTotalTime();
602 if (totTime < 0) { totTime = 0.0; }
604 os << std::setprecision(2)
605 << std::setiosflags(std::ios::fixed|std::ios::right)
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)
618 os <<
"--------------------------------------------------------------------------------"
625 return fParallelVoxelOptimisationFinished;
634 unsigned int numErrors = 0;
635 for (
const auto& logical : fVolumesToOptimise )
637 if( logical->GetVoxelHeader() ==
nullptr ) { ++numErrors; }
G4TemplateAutoLock< G4Mutex > G4AutoLock
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
#define G4MUTEX_INITIALIZER
G4GLOB_DLL std::ostream G4cout
static G4LogicalVolumeStore * GetInstance()
G4LogicalVolume represents a leaf node or unpositioned subtree in the geometry hierarchy....
void SetVoxelHeader(G4SmartVoxelHeader *pVoxel)
std::size_t GetNoDaughters() const
G4VPhysicalVolume * GetDaughter(const std::size_t i) const
G4bool IsToOptimise() const
const G4String & GetName() const
G4SmartVoxelHeader * GetVoxelHeader() const
G4SmartVoxelStat stores the information on the performance of the smart voxel optimisation algorithm ...
G4double GetRealElapsed() const
virtual G4bool IsReplicated() const =0
virtual G4int GetRegularStructureId() const =0
G4bool IsParallelOptimisationFinished()
void ReportVoxelInfo(G4LogicalVolume *logVolume, std::ostream &os)
void UndertakeOptimisation()
static void ReportVoxelStats(std::vector< G4SmartVoxelStat > &stats, G4double totalCpuTime, std::ostream &os=G4cout)
void PrepareParallelOptimisation(G4bool allOpts, G4bool verbose)
G4int CheckOptimisation()
G4int GetNumberOfRunningWorkerThreads()
const G4int kMinVoxelVolumesLevel1