CPU scheduling policy:
Of the set of results that are runnable (see below),
which ones to execute?
(On a machine with N CPUs, BOINC will try to execute N results at once).
Work-fetch policy:
When should the core client ask a project for more work,
which project should it ask,
and how much work should it ask for?
The goals of the CPU scheduler and work-fetch policies are
(in descending priority):
- Results should be completed and reported by their deadline
(results reported after their deadline
may not have any value to the project and may not be granted credit).
- Project resource shares should be honored over the long term;
- If a computer is attached to multiple projects,
execution should rotate among projects on a frequent basis.
The policies are designed to accommodate all scenarios,
including those with computers that are slow or are attached
to a large number of projects.
In previous versions of BOINC,
the core client attempted to maintain at least one result
for each attached project,
and would do weighted round-robin CPU scheduling among all projects.
In some scenarios (any combination of slow computer,
lots of projects, and tight deadlines) a computer could
miss the deadlines of all its results.
The new policies solve this problem as follows:
-
Work fetch is limited to ensure that deadlines can be met.
A computer attached to 10 projects might
have work for only a few (perhaps only one) at a given time.
-
If deadlines are threatened,
the CPU scheduling policy switches to a mode
(earliest deadline first) that optimizes the likelihood
of meeting deadlines, at the expense of variety.
Concepts and terms
Wall CPU time
A result's wall CPU time is the amount of wall-clock time
its process has been runnable at the OS level.
The actual CPU time may be much less than this,
e.g. if the process does a lot of paging,
or if other (non-BOINC) processing jobs run at the same time.
BOINC uses wall CPU time as the measure of how much resource
has been given to each project.
Why not use actual CPU time instead?
- Wall CPU time is more fair in the case of paging apps.
- The measurement of actual CPU time depends on apps to
report it correctly.
Sometimes apps have bugs that cause them to always report zero.
This screws up the scheduler.
Result states
A result is runnable if
- Neither it nor its project is suspended, and
- its files have been downloaded, and
- it hasn't finished computing
A result is runnable soon if
- Neither it nor its project is suspended, and
- it hasn't finished computing
Project states
A project is runnable if
- It's not suspended, and
- it has at least one runnable result
A project is downloading if
- It's not suspended, and
- it has at least one result whose files are being downloaded
A project is contactable if
- It's not suspended, and
- its master file has already been fetched, and
- it's not deferred (i.e. its minimum RPC time is in the past), and
- it's no-new-work flag is not set
A project is potentially runnable if
- It's either runnable, downloading, or contactable.
Debt
Intuitively, a project's 'debt' is how much work is owed to it,
relative to other projects.
BOINC uses two types of debt;
each is defined related to a set S of projects.
In each case, the debt is recalculated periodically as follows:
- A = the wall CPU time used by projects in S during this period
- R = sum of resource shares of projects in S
- For each project P in S:
- F = P.resource_share / R (i.e., P's fractional resource share)
- W = A*F (i.e., how much wall CPU time P should have gotten)
- P.debt += W - P.wall_cpu_time (i.e. what P should have gotten
minus what it got).
- P.debt is normalized (e.g. so that the mean or minimum is zero).
Short-term debt is used by the CPU scheduler.
It is adjusted over the set of runnable projects.
It is normalized so that minimum short-term debt is zero,
and maximum short-term debt is no greater than 86400 (i.e. one day).
Long-term debt is used by the work-fetch policy.
It is adjusted over the set of potentially runnable projects.
It is normalized so that average long-term debt is zero.
The CPU scheduling policy
The CPU scheduler has two modes, normal and panic.
In normal mode, the CPU scheduler runs the project(s)
with the greatest short-term debt.
Specifically:
- Set the 'anticipated debt' of each project to its short-term debt
- Find the project P with the greatest anticipated debt,
select one of P's runnable results
(picking one that is already running, if possible)
and schedule that result.
- Decrement P's anticipated debt by the 'expected payoff'
(the total wall CPU in the last period divided by #CPUs).
- Repeat steps 2 and 3 for additional CPUs
Over the long term, this results in a round-robin policy,
weighted by resource shares.
In panic mode, the CPU scheduler
schedules the runnable results with the earliest deadlines.
This allows the client to meet deadlines that would otherwise be missed.
The CPU scheduler runs when a result is completed,
when the end of the user-specified scheduling period is reached,
when new results become runnable,
or when the user performs a UI interaction
(e.g. suspending or resuming a project or result).
The work-fetch policy
X is the estimated wall time by which the number of
runnable results will fall below #CPUs.
min_queue is the user's network-connection period general preference.
work_fetch_OK is a flag set by the mode selection algorithm (see below).
The work-fetch policy maintains an 'overall urgency':
-
NEED_IMMEDIATELY:
there is at least one idle CPU
-
NEED:
X < than min_queue
-
OK:
X > min_queue, work_fetch_OK is true
-
DONT_NEED:
work_fetch_OK is false
In addition, the work-fetch policy maintains a per-project work-fetch mode:
R(P) = fractional resource share of P
X(P) = estimated wall time when number of runnable results for P
will fall below #CPUs*R(P)
-
NEED_IMMEDIATELY:
no results of P are runnable soon.
-
NEED:
X(P) < min_queue * R(P)
-
OK:
X(P) > min_queue * R(P),
and P is not suspended or deferred or no-new-work
-
DONT_NEED:
P is suspended or deferred or no-new-work
Mode selection
Sort the work units by deadline, earliest first.
If at any point in this list, the sum of the remaining
processing time is greater than 0.8 * up_frac * time to deadline,
the CPU queue is overloaded.
This triggers both no work requests and the CPU scheduler
into earliest deadline first.
Sum the fraction that the remaining processing time is of the time
to deadline for each work unit.
If this is greater than 0.8 * up_frac, the CPU queue is fully loaded.
This triggers no work fetch.
";
page_tail();
?>