Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
LikelihoodJob.cxx
Go to the documentation of this file.
1/*
2 * Project: RooFit
3 * Authors:
4 * PB, Patrick Bos, Netherlands eScience Center, p.bos@esciencecenter.nl
5 *
6 * Copyright (c) 2021, CERN
7 *
8 * Redistribution and use in source and binary forms,
9 * with or without modification, are permitted according to the terms
10 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)
11 */
12
13#include "LikelihoodJob.h"
14
26#include "RooRealVar.h"
27
28namespace RooFit {
29namespace TestStatistics {
30
32 std::shared_ptr<RooAbsL> likelihood,
33 std::shared_ptr<WrapperCalculationCleanFlags> calculation_is_clean)
34 : LikelihoodWrapper(std::move(likelihood), std::move(calculation_is_clean)),
35 n_event_tasks_(MultiProcess::Config::LikelihoodJob::defaultNEventTasks),
36 n_component_tasks_(MultiProcess::Config::LikelihoodJob::defaultNComponentTasks)
37{
38 init_vars();
39 // determine likelihood type
40 if (dynamic_cast<RooUnbinnedL *>(likelihood_.get()) != nullptr) {
42 } else if (dynamic_cast<RooBinnedL *>(likelihood_.get()) != nullptr) {
44 } else if (dynamic_cast<RooSumL *>(likelihood_.get()) != nullptr) {
46 } else if (dynamic_cast<RooSubsidiaryL *>(likelihood_.get()) != nullptr) {
48 } else {
49 throw std::logic_error("in LikelihoodJob constructor: likelihood is not of a valid subclass!");
50 }
51 // Note to future maintainers: take care when storing the minimizer_fcn pointer. The
52 // RooAbsMinimizerFcn subclasses may get cloned inside MINUIT, which means the pointer
53 // should also somehow be updated in this class.
54}
55
57{
58 return new LikelihoodJob(*this);
59}
60
61// This is a separate function (instead of just in ctor) for historical reasons.
62// Its predecessor RooRealMPFE::initVars() was used from multiple ctors, but also
63// from RooRealMPFE::constOptimizeTestStatistic at the end, which makes sense,
64// because it might change the set of variables. We may at some point want to do
65// this here as well.
67{
68 // Empty current lists
71
72 // Retrieve non-constant parameters
73 std::unique_ptr<RooArgSet> vars{likelihood_->getParameters()};
74 // TODO: make sure this is the right list of parameters, compare to original
75 // implementation in RooRealMPFE.cxx
76
77 RooArgList varList(*vars);
78
79 // Save in lists
80 vars_.add(varList);
81 save_vars_.addClone(varList);
82}
83
85{
86 if (get_manager()->process_manager().is_worker()) {
88 switch (mode) {
91 auto message = get_manager()->messenger().receive_from_master_on_worker<zmq::message_t>();
92 auto message_begin = message.data<update_state_t>();
93 auto message_end = message_begin + message.size() / sizeof(update_state_t);
94 std::vector<update_state_t> to_update(message_begin, message_end);
95 for (auto const &item : to_update) {
96 RooRealVar *rvar = static_cast<RooRealVar *>(vars_.at(item.var_index));
97 rvar->setVal(static_cast<double>(item.value));
98 if (rvar->isConstant() != item.is_constant) {
99 rvar->setConstant(static_cast<bool>(item.is_constant));
100 }
101 }
102 break;
103 }
105 LikelihoodWrapper::enableOffsetting(get_manager()->messenger().receive_from_master_on_worker<bool>());
106 break;
107 }
108 }
109 }
110}
111
112/// \warning In automatic mode, this function can start MultiProcess (forks, starts workers, etc)!
114{
115 std::size_t val = n_event_tasks_;
118 }
119 if (val > likelihood_->getNEvents()) {
120 val = likelihood_->getNEvents();
121 }
122 return val;
123}
124
125
127{
128 std::size_t val = n_component_tasks_;
130 val = 1;
131 }
132 if (val > likelihood_->getNComponents()) {
133 val = likelihood_->getNComponents();
134 }
135 return val;
136}
137
139{
140 if (get_manager()->process_manager().is_master()) {
141 bool valChanged = false;
142 bool constChanged = false;
143 std::vector<update_state_t> to_update;
144 for (std::size_t ix = 0u; ix < static_cast<std::size_t>(vars_.size()); ++ix) {
145 valChanged = !vars_[ix].isIdentical(save_vars_[ix], true);
146 constChanged = (vars_[ix].isConstant() != save_vars_[ix].isConstant());
147
148 if (valChanged || constChanged) {
149 if (constChanged) {
150 (static_cast<RooRealVar *>(&save_vars_[ix]))->setConstant(vars_[ix].isConstant());
151 }
152 // TODO: Check with Wouter why he uses copyCache in MPFE; makes it very difficult to extend, because
153 // copyCache is protected (so must be friend). Moved setting value to if-block below.
154 // _saveVars[ix].copyCache(&_vars[ix]);
155
156 // send message to queue (which will relay to workers)
157 RooAbsReal *rar_val = dynamic_cast<RooAbsReal *>(&vars_[ix]);
158 if (rar_val) {
159 double val = rar_val->getVal();
160 dynamic_cast<RooRealVar *>(&save_vars_[ix])->setVal(val);
161 bool isC = vars_[ix].isConstant();
162 to_update.push_back(update_state_t{ix, val, isC});
163 }
164 }
165 }
166 if (!to_update.empty()) {
167 ++state_id_;
168 zmq::message_t message(to_update.begin(), to_update.end());
169 // always send Job id first! This is used in worker_loop to route the
170 // update_state call to the correct Job.
172 }
173 }
174}
175
177{
179}
180
182{
183 if (get_manager()->process_manager().is_master()) {
184 // update parameters that changed since last calculation (or creation if first time)
186
187 // master fills queue with tasks
188 auto N_tasks = getNEventTasks() * getNComponentTasks();
189 for (std::size_t ix = 0; ix < N_tasks; ++ix) {
190 get_manager()->queue()->add({id_, state_id_, ix});
191 }
192 n_tasks_at_workers_ = N_tasks;
193
194 // wait for task results back from workers to master
196
198// printf("Master evaluate: ");
199 for (auto const &item : results_) {
200 result_ += item;
201 }
203 results_.clear();
204 }
205}
206
207// --- RESULT LOGISTICS ---
208
210{
211 task_result_t task_result{id_, result_.Result(), result_.Carry()};
212 zmq::message_t message(sizeof(task_result_t));
213 memcpy(message.data(), &task_result, sizeof(task_result_t));
214 get_manager()->messenger().send_from_worker_to_master(std::move(message));
215}
216
217bool LikelihoodJob::receive_task_result_on_master(const zmq::message_t &message)
218{
219 auto task_result = message.data<task_result_t>();
220 results_.emplace_back(task_result->value, task_result->carry);
222 bool job_completed = (n_tasks_at_workers_ == 0);
223 return job_completed;
224}
225
226// --- END OF RESULT LOGISTICS ---
227
228void LikelihoodJob::evaluate_task(std::size_t task)
229{
230 assert(get_manager()->process_manager().is_worker());
231
232 double section_first = 0;
233 double section_last = 1;
234 if (getNEventTasks() > 1) {
235 std::size_t event_task = task % getNEventTasks();
236 std::size_t N_events = likelihood_->numDataEntries();
237 if (event_task > 0) {
238 std::size_t first = N_events * event_task / getNEventTasks();
239 section_first = static_cast<double>(first) / N_events;
240 }
241 if (event_task < getNEventTasks() - 1) {
242 std::size_t last = N_events * (event_task + 1) / getNEventTasks();
243 section_last = static_cast<double>(last) / N_events;
244 }
245 }
246
247 switch (likelihood_type_) {
250 result_ = likelihood_->evaluatePartition({section_first, section_last}, 0, 0);
251 break;
252 }
253 case LikelihoodType::sum: {
254 std::size_t components_first = 0;
255 std::size_t components_last = likelihood_->getNComponents();
256 if (getNComponentTasks() > 1) {
257 std::size_t component_task = task / getNEventTasks();
258 components_first = likelihood_->getNComponents() * component_task / getNComponentTasks();
259 if (component_task == getNComponentTasks() - 1) {
260 components_last = likelihood_->getNComponents();
261 } else {
262 components_last = likelihood_->getNComponents() * (component_task + 1) / getNComponentTasks();
263 }
264 }
265 result_ = likelihood_->evaluatePartition({section_first, section_last}, components_first, components_last);
266 break;
267 }
268
269 default: {
270 throw std::logic_error(
271 "in LikelihoodJob::evaluate_task: likelihood types other than binned and unbinned not yet implemented!");
272 break;
273 }
274 }
275}
276
278{
281 printf("WARNING: when calling MinuitFcnGrad::setOffsetting after the run has already been started the MinuitFcnGrad::likelihood_in_gradient object (a LikelihoodSerial) on the workers can no longer be updated! This function (LikelihoodJob::enableOffsetting) can in principle be used outside of MinuitFcnGrad, but be aware of this limitation. To do a minimization with a different offsetting setting, please delete all RooFit::MultiProcess based objects so that the forked processes are killed and then set up a new RooMinimizer.\n");
283 }
284}
285
286#define PROCESS_VAL(p) \
287 case (p): s = #p; break;
288
289std::ostream &operator<<(std::ostream &out, const LikelihoodJob::update_state_mode value)
290{
291 std::string s;
292 switch (value) {
295 default: s = std::to_string(static_cast<int>(value));
296 }
297 return out << s;
298}
299
300#undef PROCESS_VAL
301
302} // namespace TestStatistics
303} // namespace RooFit
#define PROCESS_VAL(p)
TBuffer & operator<<(TBuffer &buf, const Tmpl *obj)
Definition TBuffer.h:397
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char mode
The Kahan summation is a compensated summation algorithm, which significantly reduces numerical error...
Definition Util.h:122
T Result() const
Definition Util.h:245
T Carry() const
Definition Util.h:250
bool isConstant() const
Check if the "Constant" attribute is set.
Definition RooAbsArg.h:361
virtual void removeAll()
Remove all arguments from our set, deleting them if we own them.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
virtual RooAbsArg * addClone(const RooAbsArg &var, bool silent=false)
Add a clone of the specified argument to list.
void setConstant(bool value=true)
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:103
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
Definition RooArgList.h:110
ProcessManager & process_manager() const
std::size_t id_
Definition Job.h:45
std::size_t state_id_
Definition Job.h:46
JobManager * get_manager()
Get JobManager instance; create and activate if necessary.
Definition Job.cxx:110
void gather_worker_results()
Wait for all tasks to be retrieved for the current Job.
Definition Job.cxx:124
value_t receive_from_master_on_worker(bool *more=nullptr)
Definition Messenger.h:176
void publish_from_master_to_workers(T &&item)
specialization that sends the final message
Definition Messenger.h:150
virtual void add(JobTask job_task)=0
Enqueue a task.
void enableOffsetting(bool flag) override
bool receive_task_result_on_master(const zmq::message_t &message) override
void evaluate_task(std::size_t task) override
std::vector< ROOT::Math::KahanSum< double > > results_
void send_back_task_result_from_worker(std::size_t task) override
void update_state() override
Virtual function to update any necessary state on workers.
void evaluate() override
Triggers (possibly asynchronous) evaluation of the likelihood.
LikelihoodJob(std::shared_ptr< RooAbsL > _likelihood, std::shared_ptr< WrapperCalculationCleanFlags > calculation_is_clean)
ROOT::Math::KahanSum< double > result_
LikelihoodJob * clone() const override
Virtual base class for implementation of likelihood calculation strategies.
ROOT::Math::KahanSum< double > applyOffsetting(ROOT::Math::KahanSum< double > current_value)
Likelihood class that sums over multiple -log components.
Definition RooSumL.h:25
Variable that can be changed from the outside.
Definition RooRealVar.h:37
void setVal(double value) override
Set value of variable to 'value'.
std::size_t State
Definition types.h:23
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition JSONIO.h:26
static constexpr std::size_t automaticNEventTasks
Definition Config.h:34
static constexpr std::size_t automaticNComponentTasks
Definition Config.h:35