Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
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
19  ROOT::EnableThreadSafety();
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 }