Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4TaskRunManager.cc
Go to the documentation of this file.
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//
27
28#include "G4TaskRunManager.hh"
29#include "G4AutoLock.hh"
30#include "G4EnvironmentUtils.hh"
32#include "G4Run.hh"
33#include "G4ScoringManager.hh"
34#include "G4StateManager.hh"
35#include "G4Task.hh"
36#include "G4TaskGroup.hh"
37#include "G4TaskManager.hh"
39#include "G4ThreadPool.hh"
40#include "G4Threading.hh"
41#include "G4TiMemory.hh"
42#include "G4Timer.hh"
44#include "G4UImanager.hh"
45#include "G4UserRunAction.hh"
50#include "G4WorkerThread.hh"
51#include "G4UserTaskQueue.hh"
52#include "G4TiMemory.hh"
54
55#include <cstdlib>
56#include <cstring>
57#include <iterator>
58
59//============================================================================//
60
61namespace
62{
63 G4Mutex scorerMergerMutex;
64 G4Mutex runMergerMutex;
65 G4Mutex setUpEventMutex;
66} // namespace
67
68//============================================================================//
69
71{
72 return GetMasterRunManager()->MTkernel;
73}
74
75//============================================================================//
76
78 G4int grainsize)
80 , PTL::TaskRunManager(useTBB)
81 , eventGrainsize(grainsize)
82 , numberOfEventsPerTask(-1)
83 , numberOfTasks(-1)
84 , masterRNGEngine(nullptr)
85 , workTaskGroup(nullptr)
86{
87 if(task_queue)
88 taskQueue = task_queue;
89
90 // override default of 2 from G4MTRunManager
92 fMasterRM = this;
93 MTkernel = static_cast<G4TaskRunManagerKernel*>(kernel);
94
95 G4int numberOfStaticAllocators = kernel->GetNumberOfStaticAllocators();
96 if(numberOfStaticAllocators > 0)
97 {
99 msg1 << "There are " << numberOfStaticAllocators
100 << " static G4Allocator objects detected.\n"
101 << "In multi-threaded mode, all G4Allocator objects must "
102 << "be dynamicly instantiated.";
103 G4Exception("G4TaskRunManager::G4TaskRunManager", "Run1035", FatalException,
104 msg1);
105 }
106
109
110 // use default RandomNumberGenerator if created by user, or create default
111 masterRNGEngine = G4Random::getTheEngine();
112
115
116 //------------------------------------------------------------------------//
117 // handle threading
118 //------------------------------------------------------------------------//
119 G4String _nthread_env = G4GetEnv<G4String>("G4FORCENUMBEROFTHREADS", "");
120 for(auto& itr : _nthread_env)
121 itr = (char)std::tolower(itr);
122
123 if(_nthread_env == "max")
125 else if(!_nthread_env.empty())
126 {
127 std::stringstream ss;
128 G4int _nthread_val = -1;
129 ss << _nthread_env;
130 ss >> _nthread_val;
131 if(_nthread_val > 0)
132 forcedNwokers = _nthread_val;
133
134 if(forcedNwokers > 0)
136 }
137
138 //------------------------------------------------------------------------//
139 // option for forcing TBB
140 //------------------------------------------------------------------------//
141#ifdef GEANT4_USE_TBB
142 G4int _useTBB = G4GetEnv<G4int>("G4FORCE_TBB", (G4int) useTBB);
143 if(_useTBB > 0)
144 useTBB = true;
145#else
146 if(useTBB)
147 {
149 msg << "TBB was requested but Geant4 was not built with TBB support";
150 G4Exception("G4TaskRunManager::G4TaskRunManager(...)", "Run0131",
151 JustWarning, msg);
152 }
153 useTBB = false;
154#endif
155
156 // handle TBB
158}
159
160//============================================================================//
161
163 : G4TaskRunManager(nullptr, useTBB, 0)
164{}
165
166//============================================================================//
167
169{
170 // finalize profiler before shutting down the threads
172
173 // terminate all the workers
175
176 // trigger all G4AutoDelete instances
178
179 // delete the task-group
180 delete workTaskGroup;
181 workTaskGroup = nullptr;
182
183 // destroy the thread-pool
184 if(threadPool)
186
188}
189
190//============================================================================//
191
193{
195}
196
197//============================================================================//
198
200{
201 std::ostringstream os;
202 os << randomNumberStatusDir << "G4Master_" << fn << ".rndm";
203 G4Random::saveEngineStatus(os.str().c_str());
204}
205
206//============================================================================//
207
209{
210 if(forcedNwokers > 0)
211 {
212 if(verboseLevel > 0)
213 {
215 msg << "\n### Number of threads is forced to " << forcedNwokers
216 << " by G4FORCENUMBEROFTHREADS environment variable. G4TaskRunManager::"
217 << __FUNCTION__ << "(" << n << ") ignored ###";
218 G4Exception("G4TaskRunManager::SetNumberOfThreads(G4int)", "Run0132",
219 JustWarning, msg);
220 }
222 }
223 else
224 {
225 nworkers = n;
227 {
228 if(verboseLevel > 0)
229 {
230 std::stringstream ss;
231 ss << "\n### Thread-pool already initialized. Resizing to " << nworkers
232 << "threads ###";
233 G4cout << ss.str() << "\n" << G4endl;
234 }
235 GetThreadPool()->resize(n);
236 }
237 }
238}
239
240//============================================================================//
241
243{
244 G4bool firstTime = (!threadPool);
245 if(firstTime)
247
249
250 // make sure all worker threads are set up.
252 if(firstTime)
254 // G4UImanager::GetUIpointer()->SetIgnoreCmdNotFound(true);
255}
256
257//============================================================================//
258
260{
262 {
263 G4Exception("G4TaskRunManager::InitializeThreadPool", "Run1040",
264 JustWarning, "Threadpool already initialized. Ignoring...");
265 return;
266 }
267
270
271 // create the joiners
272 if(!workTaskGroup)
274
275 if(verboseLevel > 0)
276 {
277 std::stringstream ss;
278 ss.fill('=');
279 ss << std::setw(90) << "";
280 G4cout << "\n" << ss.str() << G4endl;
281
283 {
284 G4cout << "G4TaskRunManager :: Using TBB..." << G4endl;
285 }
286 else
287 {
288 G4cout << "G4TaskRunManager :: Using G4ThreadPool..." << G4endl;
289 }
290
291 G4cout << ss.str() << "\n" << G4endl;
292 }
293}
294
295//============================================================================//
296
298{
299 // Nothing to do
300}
301
302//============================================================================//
303
305{
306 // Nothing to do
307}
308
309//============================================================================//
310
312{
313 G4int grainSize = (eventGrainsize == 0)
314 ? (G4int)threadPool->size() : eventGrainsize;
315 grainSize =
316 G4GetEnv<G4int>("G4FORCE_GRAINSIZE", grainSize, "Forcing grainsize...");
317 if(grainSize == 0)
318 grainSize = 1;
319
320 G4int nEvtsPerTask = (numberOfEventToBeProcessed > grainSize)
321 ? (numberOfEventToBeProcessed / grainSize)
322 : 1;
323
324 if(eventModuloDef > 0)
325 {
327 }
328 else
329 {
331 if(eventModulo < 1)
332 eventModulo = 1;
333 }
334 if(eventModulo > nEvtsPerTask)
335 {
336 G4int oldMod = eventModulo;
337 eventModulo = nEvtsPerTask;
338
340 msgd << "Event modulo is reduced to " << eventModulo << " (was " << oldMod
341 << ")"
342 << " to distribute events to all threads.";
343 G4Exception("G4TaskRunManager::InitializeEventLoop()", "Run10035",
344 JustWarning, msgd);
345 }
346 nEvtsPerTask = eventModulo;
347
348 if(fakeRun)
349 nEvtsPerTask = G4GetEnv<G4int>(
350 "G4FORCE_EVENTS_PER_TASK", nEvtsPerTask,
351 "Forcing number of events per task (overrides grainsize)...");
352 else
353 nEvtsPerTask = G4GetEnv<G4int>("G4FORCE_EVENTS_PER_TASK", nEvtsPerTask);
354
355 if(nEvtsPerTask < 1)
356 nEvtsPerTask = 1;
357
358 numberOfTasks = numberOfEventToBeProcessed / nEvtsPerTask;
359 numberOfEventsPerTask = nEvtsPerTask;
360 eventModulo = numberOfEventsPerTask;
361
362 if(fakeRun && verboseLevel > 1)
363 {
364 std::stringstream msg;
365 msg << "--> G4TaskRunManager::ComputeNumberOfTasks() --> " << numberOfTasks
366 << " tasks with " << numberOfEventsPerTask << " events/task...";
367
368 std::stringstream ss;
369 ss.fill('=');
370 ss << std::setw((G4int)msg.str().length()) << "";
371 G4cout << "\n"
372 << ss.str() << "\n"
373 << msg.str() << "\n"
374 << ss.str() << "\n"
375 << G4endl;
376 }
377}
378
379//============================================================================//
380
382{
383 // Now loop on requested number of workers
384 // This will also start the workers
385 // Currently we do not allow to change the
386 // number of threads: threads area created once
387 // Instead of pthread based workers, create tbbTask
388 static bool initializeStarted = false;
389
391
392 if(fakeRun)
393 {
394 if(initializeStarted)
395 {
396 auto initCmdStack = GetCommandStack();
397 if(!initCmdStack.empty())
398 {
399 threadPool->execute_on_all_threads([initCmdStack]() {
400 for(auto& itr : initCmdStack)
401 G4UImanager::GetUIpointer()->ApplyCommand(itr);
403 });
404 }
405 }
406 else
407 {
408 std::stringstream msg;
409 msg << "--> G4TaskRunManager::CreateAndStartWorkers() --> "
410 << "Initializing workers...";
411
412 std::stringstream ss;
413 ss.fill('=');
414 ss << std::setw((G4int)msg.str().length()) << "";
415 G4cout << "\n"
416 << ss.str() << "\n"
417 << msg.str() << "\n"
418 << ss.str() << "\n"
419 << G4endl;
420
424 }
425 initializeStarted = true;
426 }
427 else
428 {
429 auto initCmdStack = GetCommandStack();
430 if(!initCmdStack.empty())
431 {
432 threadPool->execute_on_all_threads([initCmdStack]() {
433 for(auto& itr : initCmdStack)
434 G4UImanager::GetUIpointer()->ApplyCommand(itr);
435 });
436 }
437
438 // cleans up a previous run and events in case a thread
439 // does not execute any tasks
442
443 {
444 std::stringstream msg;
445 msg << "--> G4TaskRunManager::CreateAndStartWorkers() --> "
446 << "Creating " << numberOfTasks << " tasks with "
447 << numberOfEventsPerTask << " events/task...";
448
449 std::stringstream ss;
450 ss.fill('=');
451 ss << std::setw((G4int)msg.str().length()) << "";
452 G4cout << "\n"
453 << ss.str() << "\n"
454 << msg.str() << "\n"
455 << ss.str() << "\n"
456 << G4endl;
457 }
458
460 for(G4int nt = 0; nt < numberOfTasks + 1; ++nt)
461 {
462 if(remaining > 0)
463 AddEventTask(nt);
464 remaining -= numberOfEventsPerTask;
465 }
467 }
468}
469
470//============================================================================//
471
473{
474 if(verboseLevel > 1)
475 G4cout << "Adding task " << nt << " to task-group..." << G4endl;
477}
478
479//============================================================================//
480
482{
484 G4int nFill = 0;
486 {
487 case 0:
489 break;
490 case 1:
491 nFill = numberOfTasks - nSeedsFilled;
492 break;
493 case 2:
494 default:
497 1;
498 }
499 // Generates up to nSeedsMax seed pairs only.
500 if(nFill > nSeedsMax)
501 nFill = nSeedsMax;
502 masterRNGEngine->flatArray(nSeedsPerEvent * nFill, randDbl);
503 helper->Refill(randDbl, nFill);
504 nSeedsFilled += nFill;
505}
506
507//============================================================================//
508
509void G4TaskRunManager::InitializeEventLoop(G4int n_event, const char* macroFile,
510 G4int n_select)
511{
512 MTkernel->SetUpDecayChannels();
515
516 if(!fakeRun)
517 {
518 nSeedsUsed = 0;
519 nSeedsFilled = 0;
520
521 if(verboseLevel > 0)
522 timer->Start();
523
524 n_select_msg = n_select;
525 if(macroFile != nullptr)
526 {
527 if(n_select_msg < 0)
528 n_select_msg = n_event;
529
530 msgText = "/control/execute ";
531 msgText += macroFile;
532 selectMacro = macroFile;
533 }
534 else
535 {
536 n_select_msg = -1;
537 selectMacro = "";
538 }
539
541
542 // initialize seeds
543 // If user did not implement InitializeSeeds,
544 // use default: nSeedsPerEvent seeds per event
545
546 if(n_event > 0)
547 {
548 G4bool _overload = InitializeSeeds(n_event);
549 G4bool _functor = false;
550 if(!_overload)
551 _functor = initSeedsCallback(n_event, nSeedsPerEvent, nSeedsFilled);
552 if(_overload == false && _functor == false)
553 {
556 {
557 case 0:
558 nSeedsFilled = n_event;
559 break;
560 case 1:
561 nSeedsFilled = numberOfTasks;
562 break;
563 case 2:
564 nSeedsFilled = n_event / eventModulo + 1;
565 break;
566 default:
568 msgd << "Parameter value <" << SeedOncePerCommunication()
569 << "> of seedOncePerCommunication is invalid. It is reset "
570 "to 0.";
571 G4Exception("G4TaskRunManager::InitializeEventLoop()", "Run10036",
572 JustWarning, msgd);
574 nSeedsFilled = n_event;
575 }
576
577 // Generates up to nSeedsMax seed pairs only.
580 masterRNGEngine->flatArray(nSeedsPerEvent * nSeedsFilled, randDbl);
581 helper->Fill(randDbl, nSeedsFilled, n_event, nSeedsPerEvent);
582 }
583 }
584 }
585
586 // Now initialize workers. Check if user defined a WorkerThreadInitialization
587 if(userWorkerThreadInitialization == nullptr)
589
590 // Prepare UI commands for threads
592
593 // Start worker threads
595}
596
597//============================================================================//
598
600{
601 // Wait for all worker threads to have finished the run
602 // i.e. wait for them to return from RunTermination()
603 // This guarantee that userrunaction for workers has been called
604
605 // Wait now for all threads to finish event-loop
607 // Now call base-class methof
610}
611
612//============================================================================//
613
615{
617 // Call base class stuff...
619
620 masterWorlds.clear();
621 G4int nWorlds = (G4int)
623 std::vector<G4VPhysicalVolume*>::iterator itrW =
625 for(G4int iWorld = 0; iWorld < nWorlds; ++iWorld)
626 {
627 addWorld(iWorld, *itrW);
628 ++itrW;
629 }
630}
631
632//============================================================================//
633
634void G4TaskRunManager::MergeScores(const G4ScoringManager* localScoringManager)
635{
636 G4AutoLock l(&scorerMergerMutex);
637 if(masterScM)
638 masterScM->Merge(localScoringManager);
639}
640
641//============================================================================//
642
644{
645 G4AutoLock l(&runMergerMutex);
646 if(currentRun)
647 currentRun->Merge(localRun);
648}
649
650//============================================================================//
651
653 G4long& s3, G4bool reseedRequired)
654{
655 G4AutoLock l(&setUpEventMutex);
657 {
659 if(reseedRequired)
660 {
662 G4int idx_rndm = nSeedsPerEvent * nSeedsUsed;
663 s1 = helper->GetSeed(idx_rndm);
664 s2 = helper->GetSeed(idx_rndm + 1);
665 if(nSeedsPerEvent == 3)
666 s3 = helper->GetSeed(idx_rndm + 2);
667 ++nSeedsUsed;
669 RefillSeeds();
670 }
672 return true;
673 }
674 return false;
675}
676
677//============================================================================//
678
680 G4bool reseedRequired)
681{
682 G4AutoLock l(&setUpEventMutex);
684 {
685 G4int nevt = numberOfEventsPerTask;
686 G4int nmod = eventModulo;
688 {
691 }
693
694 if(reseedRequired)
695 {
697 G4int nevRnd = nmod;
699 nevRnd = 1;
700 for(G4int i = 0; i < nevRnd; ++i)
701 {
702 seedsQueue->push(helper->GetSeed(nSeedsPerEvent * nSeedsUsed));
703 seedsQueue->push(helper->GetSeed(nSeedsPerEvent * nSeedsUsed + 1));
704 if(nSeedsPerEvent == 3)
705 seedsQueue->push(helper->GetSeed(nSeedsPerEvent * nSeedsUsed + 2));
706 nSeedsUsed++;
708 RefillSeeds();
709 }
710 }
712 return nevt;
713 }
714 return 0;
715}
716
717//============================================================================//
718
720{
721 // Force workers to execute (if any) all UI commands left in the stack
723
724 if(workTaskGroup)
725 {
727 if(!fakeRun)
730 }
731}
732
733//============================================================================//
734
736{
737 // This method is valid only for GeomClosed or EventProc state
738 G4ApplicationState currentState =
740 if(currentState == G4State_GeomClosed || currentState == G4State_EventProc)
741 {
742 runAborted = true;
743 MTkernel->BroadcastAbortRun(softAbort);
744 }
745 else
746 {
747 G4cerr << "Run is not in progress. AbortRun() ignored." << G4endl;
748 }
749}
750
751//============================================================================//
752
754{
755 // nothing to do in the master thread
756}
757
758//============================================================================//
759
761{
762 if(workTaskGroup)
763 {
765 if(!fakeRun)
768 }
769}
770
771//============================================================================//
772
774{
776
777 auto process_commands_stack = []() {
779 if(mrm)
780 {
781 auto cmds = mrm->GetCommandStack();
782 for(const auto& itr : cmds)
783 G4UImanager::GetUIpointer()->ApplyCommand(itr); // TLS instance
785 }
786 };
787
788 if(threadPool)
789 threadPool->execute_on_all_threads(process_commands_stack);
790}
791
792//============================================================================//
793
795
796//============================================================================//
G4ApplicationState
@ G4State_EventProc
@ G4State_GeomClosed
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
std::queue< G4long > G4SeedsQueue
Definition: G4RNGHelper.hh:136
G4Thread::id G4ThreadId
Definition: G4Threading.hh:286
std::mutex G4Mutex
Definition: G4Threading.hh:81
double G4double
Definition: G4Types.hh:83
long G4long
Definition: G4Types.hh:87
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
virtual void flatArray(const int size, double *vect)=0
void SetEventID(G4int i)
Definition: G4Event.hh:80
static G4int SeedOncePerCommunication()
static void SetSeedOncePerCommunication(G4int val)
G4int numberOfEventToBeProcessed
virtual void ThisWorkerProcessCommandsStackDone()
static void addWorld(G4int counter, G4VPhysicalVolume *w)
virtual void PrepareCommandsStack()
static G4MTRUN_DLL G4ScoringManager * masterScM
static G4MTRUN_DLL G4MTRunManager * fMasterRM
G4double * randDbl
static G4MTRUN_DLL masterWorlds_t masterWorlds
static G4MTRunManager * GetMasterRunManager()
static G4ThreadId GetMasterThreadId()
std::vector< G4String > GetCommandStack()
static void Finalize()
Definition: G4Profiler.cc:331
G4int GetNumberOfStaticAllocators() const
virtual void Initialize()
G4Timer * timer
void SetRunIDCounter(G4int i)
G4UserWorkerThreadInitialization * userWorkerThreadInitialization
G4int n_select_msg
G4int numberOfEventProcessed
G4RunManagerKernel * kernel
G4int verboseLevel
G4Run * currentRun
G4bool runAborted
G4String msgText
virtual void BeamOn(G4int n_event, const char *macroFile=nullptr, G4int n_select=-1)
G4String selectMacro
virtual void RunTermination()
G4String randomNumberStatusDir
virtual void TerminateEventLoop()
virtual void ConstructScoringWorlds()
Definition: G4Run.hh:49
virtual void Merge(const G4Run *)
Definition: G4Run.cc:67
void Merge(const G4ScoringManager *scMan)
static G4ScoringManager * GetScoringManagerIfExist()
const G4ApplicationState & GetCurrentState() const
static G4StateManager * GetStateManager()
void BroadcastAbortRun(G4bool softAbort)
static std::vector< G4String > & InitCommandStack()
virtual void ConstructScoringWorlds() override
virtual void InitializeThreadPool() override
virtual void CreateAndStartWorkers() override
static G4TaskRunManager * GetMasterRunManager()
virtual G4bool InitializeSeeds(G4int) override
virtual void ThisWorkerProcessCommandsStackDone() override
virtual G4int SetUpNEvents(G4Event *, G4SeedsQueue *seedsQueue, G4bool reseedRequired=true) override
G4VUserTaskQueue *& taskQueue
virtual void SetNumberOfThreads(G4int n) override
virtual void AbortRun(G4bool softAbort=false) override
InitializeSeedsCallback initSeedsCallback
virtual void RefillSeeds() override
virtual void RequestWorkersProcessCommandsStack() override
virtual void AddEventTask(G4int)
static G4ThreadId GetMasterThreadId()
virtual void TerminateOneEvent() override
RunTaskGroup * workTaskGroup
virtual void TerminateWorkers() override
virtual void AbortEvent() override
virtual void InitializeEventLoop(G4int n_event, const char *macroFile=nullptr, G4int n_select=-1) override
virtual ~G4TaskRunManager()
virtual void Initialize() override
virtual void StoreRNGStatus(const G4String &filenamePrefix) override
virtual void RunTermination() override
void MergeScores(const G4ScoringManager *localScoringManager)
virtual void WaitForEndEventLoopWorkers() override
G4TaskGroup< void > RunTaskGroup
G4ThreadPool *& threadPool
static G4TaskRunManagerKernel * GetMTMasterRunManagerKernel()
virtual void ProcessOneEvent(G4int i_event) override
void MergeRun(const G4Run *localRun)
virtual void ComputeNumberOfTasks()
G4TaskRunManager(G4bool useTBB=G4GetEnv< G4bool >("G4USE_TBB", false))
virtual G4bool SetUpAnEvent(G4Event *, G4long &s1, G4long &s2, G4long &s3, G4bool reseedRequired=true) override
static G4TemplateRNGHelper< T > * GetInstance()
Definition: G4RNGHelper.cc:42
virtual const T GetSeed(const G4int &sdId)
Definition: G4RNGHelper.hh:64
void Fill(G4double *dbl, G4int nev, G4int nev_tot, G4int nrpe)
Definition: G4RNGHelper.hh:83
void Refill(G4double *dbl, G4int nev)
Definition: G4RNGHelper.hh:96
void Start()
static G4TransportationManager * GetTransportationManager()
std::vector< G4VPhysicalVolume * >::iterator GetWorldsIterator()
std::size_t GetNoWorlds() const
G4int ApplyCommand(const char *aCommand)
Definition: G4UImanager.cc:495
void SetMasterUIManager(G4bool val)
Definition: G4UImanager.hh:219
static G4UImanager * GetUIpointer()
Definition: G4UImanager.cc:77
virtual void DoWork() override
static G4WorkerTaskRunManager * GetWorkerRunManager()
Up join(Up accum={})
Definition: TaskGroup.hh:654
enable_if_t< std::is_void< Up >::value, void > exec(Func func, Args... args)
Definition: TaskGroup.hh:531
int GetVerbose() const
virtual void Initialize(uint64_t n=std::thread::hardware_concurrency())
virtual void Terminate()
void SetVerbose(int val)
ThreadPool * GetThreadPool() const
void resize(size_type _n)
Definition: ThreadPool.hh:413
bool is_tbb_threadpool() const
Definition: ThreadPool.hh:192
void execute_on_all_threads(FuncT &&_func)
Definition: ThreadPool.hh:493
size_type size() const
Definition: ThreadPool.hh:252
size_type destroy_threadpool()
Definition: ThreadPool.cc:572
static void set_use_tbb(bool _v)
Definition: ThreadPool.cc:159
G4int G4GetNumberOfCores()
Definition: G4Threading.cc:121
Definition: AutoLock.hh:255