ROOT  6.07/01
Reference Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
mt101_fillNtuples.C
Go to the documentation of this file.
1 /// \file
2 /// \ingroup tutorial_multicore
3 /// Fill n-tuples in distinct workers.
4 /// This tutorial illustrates the basics of how it's possible with ROOT to
5 /// offload heavy operations on multiple threads and how it's possible to write
6 /// simultaneously multiple files. The operation performed in this case is the
7 /// creation of random gaussian numbers.
8 /// NOTE: this code can be executed in a macro, ACLiC'ed or not, but not yet at
9 /// the command line prompt.
10 ///
11 /// \macro_code
12 ///
13 /// \author Danilo Piparo
14 
15 // Measure time in a scope
16 class TimerRAII {
17  TStopwatch fTimer;
18  std::string fMeta;
19 public:
20  TimerRAII(const char *meta): fMeta(meta) {
21  fTimer.Start();
22  }
23  ~TimerRAII() {
24  fTimer.Stop();
25  std::cout << fMeta << " - real time elapsed " << fTimer.RealTime() << "s" << std::endl;
26  }
27 };
28 
29 Int_t mt101_fillNtuples(UInt_t nWorkers = 4)
30 {
31 
32  // No nuisance for batch execution
33  gROOT->SetBatch();
34 
35  // Total amount of numbers
36  const UInt_t nNumbers = 20000000U;
37 
38  // A simple function to fill ntuples randomly
39 
40  auto fillRandom = [](TNtuple & ntuple, TRandom3 & rndm, UInt_t n) {
41  for (UInt_t i = 0; i < n; ++i) ntuple.Fill(rndm.Gaus());
42  };
43 
44  // Perform the operation sequentially ---------------------------------------
45 
46  // Create a random generator and and Ntuple to hold the numbers
47  TRandom3 rndm(1);
48  TFile ofile("mt101_singleCore.root", "RECREATE");
49  TNtuple randomNumbers("singleCore", "Random Numbers", "r");
50 
51  // Now let's measure how much time we need to fill it up
52  {
53  TimerRAII t("Sequential execution");
54  fillRandom(randomNumbers, rndm, nNumbers);
55  randomNumbers.Write();
56  }
57 
58 
59  // We now go MT! ------------------------------------------------------------
60 
61  // The first, fundamental operation to be performed in order to make ROOT
62  // thread-aware.
64 
65  // We define our work item
66  auto workItem = [&fillRandom](UInt_t workerID, UInt_t workSize) {
67  // One generator, file and ntuple per worker
68  TRandom3 workerRndm(workerID); // Change the seed
69  TFile ofile(Form("mt101_multiCore_%u.root", workerID), "RECREATE");
70  TNtuple workerRandomNumbers("multiCore", "Random Numbers", "r");
71  fillRandom(workerRandomNumbers, workerRndm, workSize);
72  workerRandomNumbers.Write();
73  };
74 
75  // Create the collection which will hold the threads, our "pool"
76  std::vector<std::thread> workers;
77 
78  // We measure time here as well
79  {
80  TimerRAII t("Parallel execution");
81 
82  // We split the work in equal parts
83  const auto workSize = nNumbers / nWorkers;
84 
85  // Fill the "pool" with workers
86  for (UInt_t workerID = 0; workerID < nWorkers; ++workerID) {
87  workers.emplace_back(workItem, workerID, workSize);
88  }
89 
90  // Now join them
91  for (auto && worker : workers) worker.join();
92  }
93 
94  return 0;
95 
96 }
tuple ntuple
Definition: hsimple.py:39
Random number generator class based on M.
Definition: TRandom3.h:29
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:45
#define gROOT
Definition: TROOT.h:344
int Int_t
Definition: RtypesCore.h:41
TThread * t[5]
Definition: threadsh1.C:13
A simple TTree restricted to a list of float variables only.
Definition: TNtuple.h:30
unsigned int UInt_t
Definition: RtypesCore.h:42
char * Form(const char *fmt,...)
void fillRandom(std::vector< T > &randomV, const rangeType theRangeType)
Definition: stressVdt.cxx:98
void EnableThreadSafety()
Enables the global mutex to make ROOT thread safe/aware.
Definition: TROOT.cxx:399
virtual Int_t Fill()
[fNvar] Array of variables
Definition: TNtuple.cxx:168
TRandom3 rndm
Definition: fit2dHist.C:44
const Int_t n
Definition: legend1.C:16
Stopwatch class.
Definition: TStopwatch.h:30