Logo ROOT   6.14/05
Reference Guide
mt101_fillNtuples.C
Go to the documentation of this file.
1 /// \file
2 /// \ingroup tutorial_multicore
3 /// \notebook
4 /// Fill n-tuples in distinct workers.
5 /// This tutorial illustrates the basics of how it's possible with ROOT to
6 /// offload heavy operations on multiple threads and how it's possible to write
7 /// simultaneously multiple files. The operation performed in this case is the
8 /// creation of random gaussian numbers.
9 /// NOTE: this code can be executed in a macro, ACLiC'ed or not, but not yet at
10 /// the command line prompt.
11 ///
12 /// \macro_code
13 ///
14 /// \date January 2016
15 /// \author Danilo Piparo
16 
17 // Some useful constants and functions
18 
19 // Total amount of numbers
20 const UInt_t nNumbers = 20000000U;
21 
22 // The number of workers
23 const UInt_t nWorkers = 4U;
24 
25 // We split the work in equal parts
26 const auto workSize = nNumbers / nWorkers;
27 
28 // A simple function to fill ntuples randomly
29 void fillRandom(TNtuple &ntuple, TRandom3 &rndm, UInt_t n)
30 {
31  for (auto i : ROOT::TSeqI(n))
32  ntuple.Fill(rndm.Gaus());
33 }
34 
35 Int_t mt101_fillNtuples()
36 {
37 
38  // No nuisance for batch execution
39  gROOT->SetBatch();
40 
41  // Perform the operation sequentially ---------------------------------------
42 
43  // Create a random generator and and Ntuple to hold the numbers
44  TRandom3 rndm(1);
45  TFile ofile("mp101_singleCore.root", "RECREATE");
46  TNtuple randomNumbers("singleCore", "Random Numbers", "r");
47  fillRandom(randomNumbers, rndm, nNumbers);
48  randomNumbers.Write();
49  ofile.Close();
50 
51  // We now go MT! ------------------------------------------------------------
52 
53  // The first, fundamental operation to be performed in order to make ROOT
54  // thread-aware.
56 
57  // We define our work item
58  auto workItem = [](UInt_t workerID) {
59  // One generator, file and ntuple per worker
60  TRandom3 workerRndm(workerID); // Change the seed
61  TFile ofile(Form("mt101_multiCore_%u.root", workerID), "RECREATE");
62  TNtuple workerRandomNumbers("multiCore", "Random Numbers", "r");
63  fillRandom(workerRandomNumbers, workerRndm, workSize);
64  workerRandomNumbers.Write();
65  return 0;
66  };
67 
68  // Create the collection which will hold the threads, our "pool"
69  std::vector<std::thread> workers;
70 
71  // Fill the "pool" with workers
72  for (auto workerID : ROOT::TSeqI(nWorkers)) {
73  workers.emplace_back(workItem, workerID);
74  }
75 
76  // Now join them
77  for (auto &&worker : workers)
78  worker.join();
79 
80  return 0;
81 }
Random number generator class based on M.
Definition: TRandom3.h:27
virtual Double_t Gaus(Double_t mean=0, Double_t sigma=1)
Samples a random number from the standard Normal (Gaussian) Distribution with the given mean and sigm...
Definition: TRandom.cxx:256
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:47
#define gROOT
Definition: TROOT.h:410
int Int_t
Definition: RtypesCore.h:41
A simple TTree restricted to a list of float variables only.
Definition: TNtuple.h:28
unsigned int UInt_t
Definition: RtypesCore.h:42
char * Form(const char *fmt,...)
void EnableThreadSafety()
Enables the global mutex to make ROOT thread safe/aware.
Definition: TROOT.cxx:546
A pseudo container class which is a generator of indices.
Definition: TSeq.hxx:66
virtual Int_t Fill()
Fill a Ntuple with current values in fArgs.
Definition: TNtuple.cxx:170
const Int_t n
Definition: legend1.C:16