mt103_fillNtupleFromMultipleThreads

Fill the same TNtuple from different threads. This tutorial illustrates the basics of how it's possible with ROOT to write simultaneously to a single output file using TBufferMerger.

Author: Guilherme Amadio
This notebook tutorial was automatically generated with ROOTBOOK-izer from the macro found in the ROOT repository on Sunday, October 02, 2022 at 09:33 AM.

Avoid unnecessary output

In [1]:
gROOT->SetBatch();

Make ROOT thread-safe

In [2]:
ROOT::EnableThreadSafety();

Total number of events

In [3]:
const size_t nEntries = 65535;

Match number of threads to what the hardware can do

In [4]:
const size_t nWorkers = 4;

Split work in equal parts

In [5]:
const size_t nEventsPerWorker = nEntries / nWorkers;

Create the TBufferMerger: this class orchestrates the parallel writing

In [6]:
auto fileName = "mt103_fillNtupleFromMultipleThreads.root";
ROOT::TBufferMerger merger(fileName);

Define what each worker will do We obtain from a merger a TBufferMergerFile, which is nothing more than a file which is held in memory and that flushes to the TBufferMerger its content.

In [7]:
auto work_function = [&](int seed) {
   auto f = merger.GetFile();
   TNtuple ntrand("ntrand", "Random Numbers", "r");

   TRandom rnd(seed);
   for (auto i : ROOT::TSeqI(nEntries))
      ntrand.Fill(rnd.Gaus());
   f->Write();
};

Create worker threads

In [8]:
std::vector<std::thread> workers;

for (auto i : ROOT::TSeqI(nWorkers))
   workers.emplace_back(work_function, i + 1); // seed==0 means random seed :)

// Make sure workers are done
for (auto &&worker : workers)
   worker.join();

Draw all canvases

In [9]:
gROOT->GetListOfCanvases()->Draw()