Mt 1 0 3_Fill Ntuple From Multiple Threads

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 Thursday, February 25, 2021 at 09:34 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::Experimental::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

In [9]:
for (auto &&worker : workers)
   worker.join();

Draw all canvases

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