Scheduling API¶
The scheduling module covers the EDF scheduler, CBS bandwidth servers, multi-cluster support, and task allocators.
For the equivalent C++ types, see Algo Library.
Enumerations¶
AdmissionTest¶
- class AdmissionTest¶
Selects which utilization bound the scheduler uses when deciding whether a new CBS server can be admitted.
- CapacityBound¶
Admit a server if the total utilization does not exceed the number of processors (
U_total ≤ m).
- GFB¶
Admit a server using the Global Feasibility Bound test, which gives a tighter bound for EDF on multiprocessors.
DeadlineMissPolicy¶
- class DeadlineMissPolicy¶
Controls what the scheduler does when a job misses its absolute deadline.
- Continue¶
Ignore the miss and continue executing the job normally.
- AbortJob¶
Discard the current job instance but keep the task active.
- AbortTask¶
Remove the task and all its pending jobs from the scheduler.
- StopSimulation¶
Halt the simulation immediately.
EdfScheduler¶
- class EdfScheduler(engine: Engine, processors: list[Processor])¶
An Earliest Deadline First scheduler managing one or more processors. CBS servers are added after construction; policies are layered on top in order.
- Parameters:
engine – The simulation engine.
processors – The processors this scheduler manages.
Policy ordering
Create the scheduler and add CBS servers with
add_server().Enable a reclamation policy:
enable_grub()orenable_cash().Enable DVFS:
enable_power_aware_dvfs()or a combined policy (FFA/CSF).Enable DPM:
enable_basic_dpm()(only when not using a combined policy).Create the allocator.
Properties
- utilization: float¶
Total CBS utilization across all admitted servers (read-only).
- processor_count: int¶
Number of processors managed by this scheduler (read-only).
- server_count: int¶
Number of CBS servers currently registered (read-only).
- active_utilization: float¶
Utilization of currently active (non-idle) servers (read-only).
- scheduler_utilization: float¶
Current aggregate utilization seen by the scheduler (read-only).
- max_scheduler_utilization: float¶
Maximum scheduler utilization recorded since the simulation started (read-only).
- max_server_utilization: float¶
Maximum utilization of any single CBS server recorded since the simulation started (read-only).
Server Management
- add_server(task: Task) CbsServer¶
Add a CBS server for task, using the task’s own WCET as the budget and the task’s period as the server period. Raises AdmissionError if the admission test fails.
- add_server(task: Task, budget: float, period: float) CbsServer¶
Add a CBS server for task with explicit budget and period (both in seconds). Raises AdmissionError if the admission test fails.
- can_admit(budget: float, period: float) bool¶
Return
Trueif a server with the given budget / period (in seconds) can be admitted without violating the utilization bound.
- set_admission_test(test: AdmissionTest) None¶
Select the admission test used by
add_server()andcan_admit().
- set_deadline_miss_policy(policy: DeadlineMissPolicy) None¶
Set the action taken when a job misses its absolute deadline.
- set_expected_arrivals(task: Task, count: int) None¶
Hint the expected number of job arrivals for task. Used by the M-GRUB reclamation policy to compute per-task reclaim budgets.
Reclamation Policies
- enable_grub() None¶
Enable GRUB (Global Reclamation of Unused Bandwidth) reclamation. Must be enabled before any DVFS or DPM policy.
- enable_cash() None¶
Enable CASH (Capacity Sharing) reclamation. An alternative to GRUB. Must be enabled before any DVFS or DPM policy.
DVFS Policies
- enable_power_aware_dvfs(cooldown: float) None¶
Enable Power-Aware DVFS. Sets the clock domain frequency to
f_max × ((m-1)×u_max + U_total) / mon every scheduling event.- Parameters:
cooldown – Minimum interval between frequency changes in seconds.
DPM Policies
- enable_basic_dpm(target_cstate: int = 1) None¶
Put idle processors into C-state target_cstate when they have no work.
- Parameters:
target_cstate – C-state level to use for idle processors (default
1).
Combined DVFS + DPM Policies
Note
Combined policies (FFA, CSF, and their timer variants) incorporate both DVFS and DPM. Do not additionally call
enable_power_aware_dvfs()orenable_basic_dpm()when using them.- enable_ffa(cooldown: float, sleep_cstate: int = 1) None¶
Enable FFA (Frequency-First Approach): reduces frequency before shutting down cores.
- Parameters:
cooldown – Minimum interval between policy updates in seconds.
sleep_cstate – C-state level for idle processors (default
1).
- enable_csf(cooldown: float, sleep_cstate: int = 1) None¶
Enable CSF (Core-Shutdown First): shuts down cores before reducing frequency.
- Parameters:
cooldown – Minimum interval between policy updates in seconds.
sleep_cstate – C-state level for idle processors (default
1).
- enable_ffa_timer(cooldown: float, sleep_cstate: int = 1) None¶
Timer-based variant of FFA: re-evaluates the policy periodically rather than on every scheduling event.
- Parameters:
cooldown – Timer interval in seconds.
sleep_cstate – C-state level for idle processors (default
1).
- enable_csf_timer(cooldown: float, sleep_cstate: int = 1) None¶
Timer-based variant of CSF.
- Parameters:
cooldown – Timer interval in seconds.
sleep_cstate – C-state level for idle processors (default
1).
Example — EdfScheduler with GRUB reclamation¶
import pyschedsim as sim
engine = sim.Engine()
platform = engine.platform
cpu = platform.add_processor_type("cpu", 1.0)
clock = platform.add_clock_domain(500.0, 2000.0, 0.0001) # 100 µs DVFS delay
power = platform.add_power_domain([
(0, 0, 0.0, 100.0),
(1, 0, 0.001, 10.0),
])
platform.add_processor(cpu, clock, power)
platform.add_processor(cpu, clock, power)
task1 = platform.add_task(0.010, 0.010, 0.003)
task2 = platform.add_task(0.020, 0.020, 0.005)
engine.schedule_job_arrival(task1, 0.0, 0.002)
engine.schedule_job_arrival(task2, 0.0, 0.004)
engine.enable_energy_tracking(True)
platform.finalize()
procs = sim.get_all_processors(engine)
scheduler = sim.EdfScheduler(engine, procs)
scheduler.add_server(task1)
scheduler.add_server(task2)
# Enable reclamation, then DVFS
scheduler.enable_grub()
scheduler.enable_power_aware_dvfs(0.001) # 1 ms cooldown
allocator = sim.SingleSchedulerAllocator(engine, scheduler)
engine.run()
print(f"Total energy: {engine.total_energy():.3f} mJ")
CbsServer¶
- class CbsServer¶
CbsServeris an opaque handle returned byEdfScheduler.add_server(). It represents a Constant Bandwidth Server and is not directly queryable from Python. Store the reference if you need to identify the server later, but no properties or methods are exposed on this object.
SingleSchedulerAllocator¶
- class SingleSchedulerAllocator(engine: Engine, scheduler: EdfScheduler, clock_domain: ClockDomain | None = None)¶
Routes all incoming job-arrival events to a single
EdfScheduler. Use this allocator for single-cluster (homogeneous) platforms.- Parameters:
engine – The simulation engine.
scheduler – The scheduler that will receive all job arrivals.
clock_domain – Optional clock domain hint (default
None).
Note
The allocator installs the job-arrival handler at construction time. It must be created after all CBS servers have been added to the scheduler. Raises HandlerAlreadySetError if a handler is already installed.
Cluster¶
- class Cluster(clock_domain: ClockDomain, scheduler: EdfScheduler, perf_score: float, reference_freq_max: float)¶
Wraps an
EdfSchedulerand aClockDomaininto a logical cluster for use with multi-cluster allocators. A cluster tracks its own utilization and exposes admission queries that account for heterogeneous performance scaling.- Parameters:
clock_domain – The clock domain shared by all processors in this cluster.
scheduler – The
EdfSchedulermanaging the cluster’s processors.perf_score – Relative performance of this cluster (e.g.,
0.5for LITTLE,1.0for big).reference_freq_max – The highest
freq_maxacross all clusters, used to normalise the scale-speed computation.
Properties
- perf: float¶
Performance score of this cluster (read-only).
- scale_speed: float¶
Effective speed factor relative to the reference cluster, derived from
perf_scoreandclock_domain.freq_max / reference_freq_max(read-only).
- u_target: float¶
Utilization cap for this cluster (read-only). Defaults to the number of processors. Use
set_u_target()to override.
- processor_count: int¶
Number of processors in this cluster’s scheduler (read-only).
- utilization: float¶
Total utilization of all CBS servers assigned to this cluster (read-only).
Methods
- clock_domain() ClockDomain¶
Return the clock domain associated with this cluster.
- scheduler() EdfScheduler¶
Return the scheduler associated with this cluster.
- set_u_target(target: float) None¶
Set an explicit utilization cap for this cluster. Tasks will not be assigned here once
utilizationexceeds target.
- scaled_utilization(task_util: float) float¶
Return task_util scaled by
scale_speed, giving the effective utilization a task with utilization task_util (on the reference cluster) would consume on this cluster.
- can_admit(budget: float, period: float) bool¶
Return
Trueif a server with budget / period (in seconds) can be admitted to this cluster without exceedingu_target.
Note
The C++ methods
remaining_capacity(),set_processor_id(), andprocessor_id()are not available in the Python bindings.
FFCapAllocator¶
- class FFCapAllocator(engine: Engine, clusters: list[Cluster])¶
First-Fit Capacity allocator. Assigns each arriving task to the first cluster that has sufficient remaining capacity, querying
can_admit()on each cluster in order.- Parameters:
engine – The simulation engine.
clusters – Ordered list of clusters to consider.
Note
The allocator installs the job-arrival handler at construction time. It must be created after all per-cluster CBS servers have been added. Raises HandlerAlreadySetError if a handler is already installed.
FFCapAdaptiveLinearAllocator¶
- class FFCapAdaptiveLinearAllocator(engine: Engine, clusters: list[Cluster])¶
Capacity-aware allocator with a linearly adaptive admission threshold. Like
FFCapAllocator, it evaluates clusters in order but dynamically tightens the lowest-performance cluster’su_targetbased on the observed workload. Expected total utilization at or below 3.5 keepsu_targetat 1.0; larger workloads use the fitted linear model.- Parameters:
engine – The simulation engine.
clusters – Ordered list of clusters to consider.
- set_expected_total_util(util: float) None¶
Set the expected aggregate task utilization (sum of individual utilisations). This value combines with the observed maximum per-task utilisation to update the adaptive threshold.
CountingAllocator¶
- class CountingAllocator(engine: Engine, clusters: list[Cluster])¶
An allocator that counts how many task assignments have been made. Useful for instrumentation and testing.
- Parameters:
engine – The simulation engine.
clusters – List of clusters managed by this allocator.
- allocation_count() int¶
Return the total number of task allocations performed so far.
Note
The C++ API provides additional allocators (FirstFitAllocator,
WorstFitAllocator, BestFitAllocator, and others) that are not
currently exposed in the Python bindings. See Algo Library for
the full C++ allocator reference.
Example — Multi-cluster setup with FFCapAllocator¶
import pyschedsim as sim
engine = sim.Engine()
platform = engine.platform
# LITTLE cluster: 4 cores, 500--1400 MHz, perf=0.5
little_type = platform.add_processor_type("A7", 0.5)
little_clock = platform.add_clock_domain(500.0, 1400.0, 0.0001)
little_power = platform.add_power_domain([
(0, 0, 0.0, 200.0),
(1, 0, 0.001, 5.0),
])
for _ in range(4):
platform.add_processor(little_type, little_clock, little_power)
# big cluster: 4 cores, 800--2000 MHz, perf=1.0
big_type = platform.add_processor_type("A15", 1.0)
big_clock = platform.add_clock_domain(800.0, 2000.0, 0.0001)
big_power = platform.add_power_domain([
(0, 0, 0.0, 800.0),
(1, 0, 0.001, 10.0),
])
for _ in range(4):
platform.add_processor(big_type, big_clock, big_power)
tasks = [platform.add_task(0.010, 0.010, 0.002) for _ in range(6)]
for t in tasks:
engine.schedule_job_arrival(t, 0.0, t.wcet)
platform.finalize()
# Reference frequency is the highest freq_max across all clusters
ref_freq_max = 2000.0
little_procs = [platform.processor(i) for i in range(4)]
big_procs = [platform.processor(i) for i in range(4, 8)]
little_sched = sim.EdfScheduler(engine, little_procs)
big_sched = sim.EdfScheduler(engine, big_procs)
# Enable per-cluster reclamation
little_sched.enable_grub()
big_sched.enable_grub()
little_cluster = sim.Cluster(little_clock, little_sched, 0.5, ref_freq_max)
big_cluster = sim.Cluster(big_clock, big_sched, 1.0, ref_freq_max)
# Optional utilization cap on LITTLE
little_cluster.set_u_target(3.2) # 80 % of 4 cores
# The FFCapAllocator routes arrivals and creates CBS servers automatically
allocator = sim.FFCapAllocator(engine, [little_cluster, big_cluster])
engine.run()