Hi,
While working with RooAddPdf, I found that computing integrals was surprisingly slow, compared to performing the integrals on its component PDFs.
Basically the goal is to compute the fraction of the RooAddPdf within a subrange of the observable. This can be done by computing a normalized integral of the RooAddPdf for this range. Alternatively, one can perform these integrals on each of the PDFs that go into the sum, and then combining them by hand. I was expecting the latter to be slightly slower (due to the overhead of performing multiple independent computations instead of a single one) but it seems instead to be significantly faster.
I have tried to reproduce the effect in a simple example, which is given below and shows the “by hand” method to be about 50% faster than using RooAddPdf directly.
Would anybody know what is causing this, and if there is a way to work around it ? (the performance problems are a major issue in the real-life situation which prompted this).
Thanks,
- Nicolas
{
RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR);
RooRealVar mgg("mgg", "", 105, 160);
RooConstVar mH("mH", "", 125);
RooConstVar sigmaH("sigmaH", "", 1.5);
RooConstVar slope("slope", "", -0.02);
RooGaussian sigPdf("sigPdf", "", mgg, mH, sigmaH);
RooGenericPdf bkgPdf("bkgPdf", "", "exp(slope*mgg)", RooArgList(mgg, slope));
RooConstVar nSig("nSig", "", 100);
RooConstVar nBkg("nBkg", "", 10000);
RooAddPdf totPdf("totPdf", "", RooArgList(sigPdf, bkgPdf), RooArgList(nSig, nBkg));
f = mgg.frame();
totPdf.plotOn(f);
f->Draw();
mgg.setRange("peak", 120, 130);
TStopwatch t;
t.Start();
for (unsigned int i = 0; i < 50000; i++) {
RooAbsReal* integral = totPdf.createIntegral(mgg, mgg, "peak");
double value = integral->getVal();
if (i ==0) cout << value << endl;
delete integral;
}
cout << "elapsed time (RooAddPdf method) = " << t.RealTime() << " s." << endl;
t.Reset();
t.Start();
for (unsigned int i = 0; i < 50000; i++) {
RooAbsReal* sigInt = sigPdf.createIntegral(mgg, mgg, "peak");
RooAbsReal* bkgInt = bkgPdf.createIntegral(mgg, mgg, "peak");
double value = (nSig.getVal()*sigInt->getVal() + nBkg.getVal()*bkgInt->getVal())/(nSig.getVal() + nBkg.getVal());
if (i ==0) cout << value << endl;
delete sigInt;
delete bkgInt;
}
cout << "elapsed time (component method) = " << t.RealTime() << " s." << endl;
}