Help with threads - printing canvases


_ROOT Version: 6.10.04-x86_64-slc6-gcc62-opt
_Platform: lxplus


Hi!

I would like to get a bit into using multiple threads. Even though there are a bunch of tutorials out there, I couldn’t find one that helps me with my problem.

I have a very large number of histograms and graphs in a rootfile (extracted from some ntuples), which I extract and plot into pdfs with a larger number of different functions (which allow me to specify the style, ranges, colours,… all that good stuff).
Since the number of plots I do in the end is quite large, I though I might be able to accelerate this using multiple threads…

So as a simplified example, let’s say I have a rootfile with two histograms hist1 and hist2, and I want to plot them differently into pdfs.

I was hoping that something like the following would work:


void plot1(TH1F* hist, TString filename) {
  TCanvas* c = new TCanvas(filename);
  hist->SetLineColor(kBlue);
  hist->Draw("hist");
  c->Print(filename+".pdf");
  delete c;
}

void plot2(TH1F* hist, TString filename) {
  TCanvas* c = new TCanvas(filename);
  hist->SetLineColor(kRed);
  hist->GetXaxis()->SetTitle("x");
  hist->Draw("hist");
  c->Print(filename+".pdf");
  delete c;
}

void multthreadplotting() {

  ROOT::EnableThreadSafety();

  TFile* f = TFile::Open("test.root", "read");

  //no threads, works
  // TH1F* h1 = (TH1F*) f->Get("hist1");
  // plot1(h1, "hist1");
  // TH1F* h2 = (TH1F*) f->Get("hist2");
  // plot2(h2, "hist2");

  //with threads
  TH1F* h1 = (TH1F*) f->Get("hist1");
  std::thread thread1(plot1, h1, "hist1thread");

  TH1F* h2 = (TH1F*) f->Get("hist2");
  std::thread thread2(plot2, h2, "hist2thread");

  thread1.join();
  thread2.join();
  f->Close();
}

This runs with just one thread, crashes when I run both though. Would be thankful if somebody could point me in the right direction (or let me know if this won’t work)!

Thanks a lot!
Alex

Hi, Alex.

It is possible that these operations are not thread-safe. You could try with multiprocessing.

ROOT provides TProcessExecutor, which offers a Map() call that hides most of the concurrent programming complexity (you still need to make your code thread safe) and looks like a good candidate for programming your example.

I never used the std:thread for plotting. But TCanvas seems to be the faulty part of the code. I managed to reduce the problem to:

void plot1() {
   TCanvas* c = new TCanvas();
}

void multthreadplotting() {
   ROOT::EnableThreadSafety();
   std::thread thread1(plot1);
   thread1.join();
}
1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.