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
25#include "RooRealVar.h"
26
27namespace RooFit {
28namespace TestStatistics {
29
31 std::shared_ptr<RooAbsL> likelihood,
32 std::shared_ptr<WrapperCalculationCleanFlags> calculation_is_clean /*, RooMinimizer *minimizer*/)
33 : LikelihoodWrapper(std::move(likelihood), std::move(calculation_is_clean) /*, minimizer*/)
34{
35 init_vars();
36 // determine likelihood type
37 if (dynamic_cast<RooUnbinnedL *>(likelihood_.get()) != nullptr) {
39 } else if (dynamic_cast<RooBinnedL *>(likelihood_.get()) != nullptr) {
41 } else if (dynamic_cast<RooSumL *>(likelihood_.get()) != nullptr) {
43 } else if (dynamic_cast<RooSubsidiaryL *>(likelihood_.get()) != nullptr) {
45 } else {
46 throw std::logic_error("in LikelihoodJob constructor: likelihood is not of a valid subclass!");
47 }
48 // Note to future maintainers: take care when storing the minimizer_fcn pointer. The
49 // RooAbsMinimizerFcn subclasses may get cloned inside MINUIT, which means the pointer
50 // should also somehow be updated in this class.
51}
52
54{
55 return new LikelihoodJob(*this);
56}
57
58// This is a separate function (instead of just in ctor) for historical reasons.
59// Its predecessor RooRealMPFE::initVars() was used from multiple ctors, but also
60// from RooRealMPFE::constOptimizeTestStatistic at the end, which makes sense,
61// because it might change the set of variables. We may at some point want to do
62// this here as well.
64{
65 // Empty current lists
68
69 // Retrieve non-constant parameters
70 auto vars = std::make_unique<RooArgSet>(
71 *likelihood_->getParameters()); // TODO: make sure this is the right list of parameters, compare to original
72 // implementation in RooRealMPFE.cxx
73 RooArgList varList(*vars);
74
75 // Save in lists
76 vars_.add(varList);
77 save_vars_.addClone(varList);
78}
79
81{
82 if (get_manager()->process_manager().is_worker()) {
84 switch (mode) {
87 auto message = get_manager()->messenger().receive_from_master_on_worker<zmq::message_t>();
88 auto message_begin = message.data<update_state_t>();
89 auto message_end = message_begin + message.size() / sizeof(update_state_t);
90 std::vector<update_state_t> to_update(message_begin, message_end);
91 for (auto const &item : to_update) {
92 RooRealVar *rvar = (RooRealVar *)vars_.at(item.var_index);
93 rvar->setVal(static_cast<Double_t>(item.value));
94 if (rvar->isConstant() != item.is_constant) {
95 rvar->setConstant(static_cast<Bool_t>(item.is_constant));
96 }
97 }
98 break;
99 }
101 LikelihoodWrapper::enableOffsetting(get_manager()->messenger().receive_from_master_on_worker<bool>());
102 break;
103 }
104 }
105 }
106}
107
109{
110 if (get_manager()->process_manager().is_master()) {
111 bool valChanged = false;
112 bool constChanged = false;
113 std::vector<update_state_t> to_update;
114 for (std::size_t ix = 0u; ix < static_cast<std::size_t>(vars_.getSize()); ++ix) {
115 valChanged = !vars_[ix].isIdentical(save_vars_[ix], kTRUE);
116 constChanged = (vars_[ix].isConstant() != save_vars_[ix].isConstant());
117
118 if (valChanged || constChanged) {
119 if (constChanged) {
120 ((RooRealVar *)&save_vars_[ix])->setConstant(vars_[ix].isConstant());
121 }
122 // TODO: Check with Wouter why he uses copyCache in MPFE; makes it very difficult to extend, because
123 // copyCache is protected (so must be friend). Moved setting value to if-block below.
124 // _saveVars[ix].copyCache(&_vars[ix]);
125
126 // send message to queue (which will relay to workers)
127 RooAbsReal *rar_val = dynamic_cast<RooAbsReal *>(&vars_[ix]);
128 if (rar_val) {
129 Double_t val = rar_val->getVal();
130 dynamic_cast<RooRealVar *>(&save_vars_[ix])->setVal(val);
131 Bool_t isC = vars_[ix].isConstant();
132 to_update.push_back(update_state_t{ix, val, isC});
133 }
134 }
135 }
136 if (!to_update.empty()) {
137 ++state_id_;
138 zmq::message_t message(to_update.begin(), to_update.end());
139 // always send Job id first! This is used in worker_loop to route the
140 // update_state call to the correct Job.
142 // have to pass message separately to avoid copies from parameter pack to first parameter
144 }
145 }
146}
147
149{
151}
152
154{
155 if (get_manager()->process_manager().is_master()) {
156 // update parameters that changed since last calculation (or creation if first time)
158
159 // master fills queue with tasks
160 for (std::size_t ix = 0; ix < get_manager()->process_manager().N_workers(); ++ix) {
161 get_manager()->queue().add({id_, state_id_, ix});
162 }
164
165 // wait for task results back from workers to master
167
168 for (auto const &item : results_) {
169 result_ += item;
170 }
172 results_.clear();
173 }
174}
175
176// --- RESULT LOGISTICS ---
177
179{
180 task_result_t task_result{id_, result_.Result(), result_.Carry()};
181 zmq::message_t message(sizeof(task_result_t));
182 memcpy(message.data(), &task_result, sizeof(task_result_t));
183 get_manager()->messenger().send_from_worker_to_master(std::move(message));
184}
185
186bool LikelihoodJob::receive_task_result_on_master(const zmq::message_t &message)
187{
188 auto task_result = message.data<task_result_t>();
189 results_.emplace_back(task_result->value, task_result->carry);
190 printf("result received: %f\n", task_result->value);
192 bool job_completed = (N_tasks_at_workers_ == 0);
193 return job_completed;
194}
195
196// --- END OF RESULT LOGISTICS ---
197
198void LikelihoodJob::evaluate_task(std::size_t task)
199{
200 assert(get_manager()->process_manager().is_worker());
201
202 std::size_t N_events = likelihood_->numDataEntries();
203
204 // used to have multiple modes here, but only kept "bulk" mode; dropped interleaved, single_event and all_events from
205 // old MultiProcess::NLLVar
206 std::size_t first = N_events * task / get_manager()->process_manager().N_workers();
207 std::size_t last = N_events * (task + 1) / get_manager()->process_manager().N_workers();
208
209 switch (likelihood_type_) {
212 result_ = likelihood_->evaluatePartition(
213 {static_cast<double>(first) / N_events, static_cast<double>(last) / N_events}, 0, 0);
214 break;
215 }
216 default: {
217 throw std::logic_error(
218 "in LikelihoodJob::evaluate_task: likelihood types other than binned and unbinned not yet implemented!");
219 break;
220 }
221 }
222}
223
225{
228}
229
230#define PROCESS_VAL(p) \
231 case (p): s = #p; break;
232
233std::ostream &operator<<(std::ostream &out, const LikelihoodJob::update_state_mode value)
234{
235 std::string s;
236 switch (value) {
239 default: s = std::to_string(static_cast<int>(value));
240 }
241 return out << s;
242}
243
244#undef PROCESS_VAL
245
246} // namespace TestStatistics
247} // namespace RooFit
#define PROCESS_VAL(p)
double Double_t
Definition RtypesCore.h:59
const Bool_t kTRUE
Definition RtypesCore.h:100
TBuffer & operator<<(TBuffer &buf, const Tmpl *obj)
Definition TBuffer.h:399
T Result() const
Definition Util.h:245
T Carry() const
Definition Util.h:255
Bool_t isConstant() const
Check if the "Constant" attribute is set.
Definition RooAbsArg.h:377
virtual void removeAll()
Remove all arguments from our set, deleting them if we own them.
Int_t getSize() const
virtual RooAbsArg * addClone(const RooAbsArg &var, Bool_t silent=kFALSE)
Add a clone of the specified argument to list.
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
void setConstant(Bool_t value=kTRUE)
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition RooAbsReal.h:64
Double_t getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:94
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:116
void gather_worker_results()
Wait for all tasks to be retrieved for the current Job.
Definition Job.cxx:130
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
void add(JobTask job_task)
Enqueue a task.
Definition Queue.cxx:61
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:26
RooRealVar represents a variable that can be changed from the outside.
Definition RooRealVar.h:39
virtual void setVal(Double_t value)
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 Common.h:18
Definition first.py:1