Logo ROOT   6.14/05
Reference Guide
mt103_fillNtupleFromMultipleThreads.C
Go to the documentation of this file.
1 /// \file
2 /// \ingroup tutorial_multicore
3 /// \notebook
4 /// Fill the same TNtuple from different threads.
5 /// This tutorial illustrates the basics of how it's possible with ROOT
6 /// to write simultaneously to a single output file using TBufferMerger.
7 ///
8 /// \macro_code
9 ///
10 /// \date May 2017
11 /// \author Guilherme Amadio
12 
13 void mt103_fillNtupleFromMultipleThreads()
14 {
15  // Avoid unnecessary output
16  gROOT->SetBatch();
17 
18  // Make ROOT thread-safe
20 
21  // Total number of events
22  const size_t nEntries = 65535;
23 
24  // Match number of threads to what the hardware can do
25  const size_t nWorkers = 4;
26 
27  // Split work in equal parts
28  const size_t nEventsPerWorker = nEntries / nWorkers;
29 
30  // Create the TBufferMerger: this class orchestrates the parallel writing
31  auto fileName = "mt103_fillNtupleFromMultipleThreads.root";
32  ROOT::Experimental::TBufferMerger merger(fileName);
33 
34  // Define what each worker will do
35  // We obtain from a merger a TBufferMergerFile, which is nothing more than
36  // a file which is held in memory and that flushes to the TBufferMerger its
37  // content.
38  auto work_function = [&](int seed) {
39  auto f = merger.GetFile();
40  TNtuple ntrand("ntrand", "Random Numbers", "r");
41 
42  // The resetting of the kCleanup bit below is necessary to avoid leaving
43  // the management of this object to ROOT, which leads to a race condition
44  // that may cause a crash once all threads are finished and the final
45  // merge is happening
46  ntrand.ResetBit(kMustCleanup);
47 
48  TRandom rnd(seed);
49  for (auto i : ROOT::TSeqI(nEntries))
50  ntrand.Fill(rnd.Gaus());
51  f->Write();
52  };
53 
54  // Create worker threads
55  std::vector<std::thread> workers;
56 
57  for (auto i : ROOT::TSeqI(nWorkers))
58  workers.emplace_back(work_function, i + 1); // seed==0 means random seed :)
59 
60  // Make sure workers are done
61  for (auto &&worker : workers)
62  worker.join();
63 }
#define gROOT
Definition: TROOT.h:410
#define f(i)
Definition: RSha256.hxx:104
This is the base class for the ROOT Random number generators.
Definition: TRandom.h:27
A simple TTree restricted to a list of float variables only.
Definition: TNtuple.h:28
TBufferMerger is a class to facilitate writing data in parallel from multiple threads, while writing to a single output file.
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