Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
worker.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 * IP, Inti Pelupessy, Netherlands eScience Center, i.pelupessy@esciencecenter.nl
6 *
7 * Copyright (c) 2021, CERN
8 *
9 * Redistribution and use in source and binary forms,
10 * with or without modification, are permitted according to the terms
11 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)
12 */
13
15
23
24#include <string>
25#include <unistd.h> // getpid, pid_t
26#include <cassert>
27#include <cerrno> // EINTR
28#include <csignal> // sigprocmask etc
29
30namespace RooFit {
31namespace MultiProcess {
32
33static bool worker_loop_running = false;
34
39
40/// \brief The worker processes' event loop
41///
42/// Asks the queue process for tasks, polls for incoming messages from other
43/// processes and handles them.
45{
46 assert(JobManager::instance()->process_manager().is_worker());
48 Q2W message_q2w;
49
50 // use a flag to not ask twice
51 bool dequeue_acknowledged = true;
52
53 Poller poller;
54 std::size_t mw_sub_index;
55
56 std::tie(poller, mw_sub_index) = JobManager::instance()->messenger().create_worker_poller();
57
58 // The SIGTERM handler was set in the ProcessManager after forking to the queue and worker
59 // processes; it wakes up any poll through the self-pipe, so no signal blocking is needed here.
61 try { // watch for error from poll (which is called inside receive functions) caused by SIGTERM from master
62
63 // try to dequeue a task
64 if (dequeue_acknowledged) { // don't ask twice
66 dequeue_acknowledged = false;
67 }
68
69 // wait for handshake from queue or update from the master-worker channel
70 auto poll_result = poller.poll(-1);
71 // because the poller may now have a waiting update from master over the master-worker
72 // channel, but the queue channel could be first in the poll_result vector, and during
73 // handling of a new task it is possible we need to already receive the updated state,
74 // we have to then flip this boolean so that in the for loop when we reach the
75 // master-worker channel's result, we can skip it (otherwise we will hang there,
76 // because no more updated state will be coming):
77 bool skip_sub = false;
78 // then process incoming messages from the channels
79 for (auto readable_index : poll_result) {
80 // message comes from the master-worker channel (first element):
81 if (readable_index == mw_sub_index) {
82 if (!skip_sub) {
83 auto job_id = JobManager::instance()->messenger().receive_from_master_on_worker<std::size_t>();
85 }
86 } else { // from queue channel
88 switch (message_q2w) {
90 dequeue_acknowledged = true;
91 break;
92 }
94 dequeue_acknowledged = true;
95 auto job_id = JobManager::instance()->messenger().receive_from_queue_on_worker<std::size_t>();
98
99 // while loop, because multiple jobs may have updated state coming
100 while (state_id != JobManager::get_job_object(job_id)->get_state_id()) {
101 skip_sub = true;
102 auto job_id_for_state =
104 JobManager::get_job_object(job_id_for_state)->update_state();
105 }
106 if (RooFit::MultiProcess::Config::getTimingAnalysis()) ProcessTimer::start_timer("worker:eval_task:" + std::to_string(task_id));
108 if (RooFit::MultiProcess::Config::getTimingAnalysis()) ProcessTimer::end_timer("worker:eval_task:" + std::to_string(task_id));
110
111 break;
112 }
113 }
114 }
115 }
116
117 } catch (ppoll_error_t &) {
118 // SIGTERM received (benign signal interruptions are retried inside
119 // Channel::wait), so exit the loop
120 break;
121 }
122 }
123
126
127 worker_loop_running = false;
128}
129
130} // namespace MultiProcess
131} // namespace RooFit
static bool getTimingAnalysis()
Definition Config.cxx:87
static JobManager * instance()
static Job * get_job_object(std::size_t job_object_id)
std::size_t get_state_id()
Get the current state identifier.
Definition Job.cxx:141
virtual void send_back_task_result_from_worker(std::size_t task)=0
virtual void update_state()
Virtual function to update any necessary state on workers.
Definition Job.cxx:138
virtual void evaluate_task(std::size_t task)=0
value_t receive_from_master_on_worker(bool *more=nullptr)
Definition Messenger.h:175
std::pair< Poller, std::size_t > create_worker_poller()
Helper function that creates a poller for worker_loop()
Waits for input on a set of registered Channels.
Definition Poller.h:34
std::vector< std::size_t > poll(int timeout_ms=-1) const
Wait for input; returns the registration indices of readable channels.
Definition Poller.h:58
static void start_timer(std::string section_name)
static void end_timer(std::string section_name)
Thrown when a blocking wait on a Channel is interrupted, e.g.
Definition Channel.h:31
void worker_loop()
The worker processes' event loop.
Definition worker.cxx:44
bool is_worker_loop_running()
Definition worker.cxx:35
std::size_t Task
Definition types.h:22
static bool worker_loop_running
Definition worker.cxx:33
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 CodegenImpl.h:73