Hi all,
I have some code which returns me the weighted yield and uncertainty from a TTree like so:
TH1D *tmpWeightHisto = new TH1D("tmpWeightHisto","tmpWeightHisto",1,-3.0,3.0);
tmpWeightHisto->Sumw2();
if(*cut != ""){
procNtuple->Draw(*cut+">>tmpWeightHisto","("+*cut+")*("+perEventWeightVar+")");
}else{
procNtuple->Draw("1>>tmpWeightHisto","("+perEventWeightVar+")");
}
*Entries = tmpWeightHisto->Integral();
*d_Entries = sqrt(tmpWeightHisto->GetSumw2()->At(1));
tmpWeightHisto->Delete();
In my use case, I perform this operation over several ntuples many times. It’s an ideal candidate for paralellisation, so I threw OMP at it. To my surprise the rest of the code works beautifully with OMP, except for this one part, which segfaults unless I put a critical directive around it like so:
//Needed to make a unique histo per thread
TString n("tmpWeightHisto_");
#ifdef _OPENMP
char uniq = 'a'+(omp_get_thread_num()%26);
n+=uniq;
n+=+"_";
#endif
TH1D *tmpWeightHisto = new TH1D(n,n,1,-3.0,3.0);
tmpWeightHisto->Sumw2();
if(*cut != ""){
//Critical directives added here to prevent crashing. Literally only these two calls seem to cause crashes
#pragma omp critical(crasheswithoutme)
{
procNtuple->Draw(*cut+">>"+n,"("+*cut+")*("+perEventWeightVar+")");
}
}else{
#pragma omp critical(crasheswithoutme)
{
procNtuple->Draw("1>>"+n,"("+perEventWeightVar+")");
}
}
TH1D *tmpWeightHisto = (TH1D*)gDirectory->Get(n);
*Entries = tmpWeightHisto->Integral();
*d_Entries = sqrt(tmpWeightHisto->GetSumw2()->At(1));
tmpWeightHisto->Delete();
Adding the critical directives means that now, my rather large codebase works multithreaded, even with TMVA running in each thread. Unfortunately, the Draw() is where the code spends most of its time, so performance is actually reduced by a factor of almost 2 when running with 4 threads on a 4-core machine compared to running single-threaded as the critical is adding a huge overhead. I have two questions:
1: Is this a dumb way to obtain a weighted yield from an ntuple with cuts? Ie: is there a more efficient and thread-safe method of applying a cut string and getting back a weighted yield +/- uncert?
2: If this is the best way to do it, is there a way I can make it thread safe without locking? I’m open to other multithreading options than OMP, but it’s the one I’m most familiar with and given that everything nearly works with only a couple of additional lines of pragma, I’d be happiest with a solution that still makes use of it.
Thanks!