Skip to content

Instantly share code, notes, and snippets.

@fwyzard
Last active January 18, 2018 16:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fwyzard/9831080ea903e571c69b8b3f92632f9b to your computer and use it in GitHub Desktop.
Save fwyzard/9831080ea903e571c69b8b3f92632f9b to your computer and use it in GitHub Desktop.
How to migrate a DQMEDanalyzer to a DQMGlobalEDAnalyzer

How to migrate a DQMEDanalyzer to a DQMGlobalEDAnalyzer

A DQMGlobalEDAnalyzer module is similar to a DQMEDanalyzer, with few differences:

  • it is a global module rather than a stream module: there is only one copy of it, no matter how many threads or streams the job is configured to use, and it will "see" all events being processed; the advantage is a significant reduction in memory usage as the number of streams increases; on the other hand this means that its internal state (the data members) are not allowed to change during the analyze() (or dqmAnalyze()) method, unless in a concurrency-safe way. See FWMultithreadedFrameworkGlobalModuleInterface for the details.
  • it uses ConcurrentMonitorElements rather than MonitorElements to expose a concurrecy-safe interface to the DQMStore; these objects are also "global": the DQMStore holds a single copy of the histograms, and there is not merge step at the end fo each lumisection or run; the ConcurrentMonitorElement takes care of preventing multiple events from filling the same histogram at the same time. See Concurrent Monitor Elements for an overview.
  • it provides a special method, dqmBeginRun(...), to cache or setup run-based conditions or confugurations.

If your module is actually a legacy edm::EDAnalyzer, see How to migrate a legacy DQM edm::EDAnalyzer to a DQMGlobalEDAnalyzer.

Update the headers

From

#include "DQMServices/Core/interface/DQMEDAnalyzer.h"
#include "DQMServices/Core/interface/MonitorElement.h"

to

#include "DQMServices/Core/interface/DQMGlobalEDAnalyzer.h"
#include "DQMServices/Core/interface/ConcurrentMonitorElement.h"

Move the histograms to a separate structure

If you had something like

private:
  MonitorElement *              m_histo;
  std::vector<MonitorElement *> m_more_histos;

they need to be moved to a separate struct or class outside the EDAnalyzer itself:

namespace {
  struct Histograms {
    ConcurrentMonitorElement              histo;
    std::vector<ConcurrentMonitorElement> more_histos;
  };
}

Update the class signature

From

class MyDQMModule : public DQMEDAnalyzer {
  
private:
  void dqmBeginRun(edm::Run const&, edm::EventSetup const&) override;
  void bookHistograms(DQMStore::IBooker &, edm::Run const&, edm::EventSetup const&) override;
  void analyze(edm::Event const&, edm::EventSetup const&) override;

to

class MyDQMModule : public DQMGlobalEDAnalyzer<Histograms> {
  
private:
  void dqmBeginRun(edm::Run const&, edm::EventSetup const&, Histograms &) const override;
  void bookHistograms(DQMStore::ConcurrentBooker &, edm::Run const&, edm::EventSetup const&, Histograms &) const override;
  void dqmAnalyze(edm::Event const&, edm::EventSetup const&, Histograms const&) const override;

and similarly in the individual methods definition, from

void MyDQMModule::dqmBeginRun(edm::Run const& run, edm::EventSetup const& setup) {
  ...
}

void MyDQMModule::bookHistograms(DQMStore::IBooker & booker, edm::Run const& run, edm::EventSetup const& setup) {
   ...
}

void MyDQMModule::analyze(edm::Event const& event, edm::EventSetup const& setup) {
   ...
}

to

void MyDQMModule::dqmBeginRun(edm::Run const& run, edm::EventSetup const& setup, Histograms & histograms) const {
  ...
}

void MyDQMModule::bookHistograms(DQMStore::ConcurrentBooker & booker, edm::Run const& run, edm::EventSetup const& setup, Histograms & histograms) const {
   ...
}

void MyDQMModule::dqmAnalyze(edm::Event const& event, edm::EventSetup const& setup, Histograms const& histograms) const {
   ...
}

Update the access to the histograms

Access to the histograms needs to be changed from

m_histo = ...;
m_histo->doSomething();

to

histograms.histo = ...;
histograms.histo.doSomething();

Calls to m_histo->Fill(...) need to be changed to histograms.histo.fill(...).

Calls to m_histo->getTH1F() and similar need to be removed.

Calls to m_histo->GetXaxis()->SetTitle(...) and similar need to be replaced by calls to histograms.histo.setXTitle(...) and similar.

dqmBeginRun(...)

bookHistograms(...) is called once at the beginning of each run, while holding the DQMStore lock - meaning that different modules cannot call their bookHistograms(...) methods at the same time.
For time-consuming per-run initialisation code (e.g. to create a local cache of run-based configurations, or to setup the histograms structure) it is better to use the dqmBeginRun(...) method:

void dqmBeginRun(edm::Run const& run, edm::EventSetup const& setup, H & histograms) const override
{
  ...
}

If you need to customise the ConcurrentmonitorElement in a way which is not supported by the current interface, please send a request to extend the interface or implement a more general solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment