领域契约
dispatchatlas.core 是内层包边界。它使用不可变、且仅依赖标准库的对象,使基准、求解器、
实验、分析与文档共享同一套调度词汇。
🗂️ 调度模型
问题以 ProblemSpec、TaskSpec、ResourceSpec、Dependency、Objective 与
Constraint 表示。候选调度使用 Assignment、Schedule、ObjectiveValue 与
ScheduleResult。
验证是显式的:
from dispatchatlas.core import (
Duration,
Objective,
ObjectiveSense,
ProblemId,
ProblemSpec,
ResourceAmount,
ResourceId,
ResourceRequirement,
ResourceSpec,
TaskId,
TaskSpec,
validate_problem,
)
cpu = ResourceId("cpu")
problem = ProblemSpec(
id=ProblemId("smoke"),
tasks=(
TaskSpec(
TaskId("task-a"),
Duration(1.0),
demands=(ResourceRequirement(cpu, ResourceAmount(1.0)),),
),
),
resources=(ResourceSpec(cpu, ResourceAmount(1.0)),),
objectives=(Objective("makespan", ObjectiveSense.MINIMIZE),),
)
validated = validate_problem(problem)validate_problem 返回一个带验证戳记与机器可读报告的 ValidatedProblem。
validate_schedule 检查任务覆盖、资源容量、时序边界与依赖关系。
🔗 多资源共分配
一个任务可以同时要求多个资源。TaskSpec.demands 是一个 ResourceRequirement 的元组,
调度构造器将任务跨其要求的每一个资源进行共分配,并在任务的整个持续期内将它们一并
持有。因此候选调度将每次放置记录为 Assignment.resource_ids——一个元组,而非单个
资源——而 validate_schedule 确认两个在时间上重叠的任务绝不共享某个资源。
资源冲突图是调度的杠杆:需求集合相交的两个任务必须串行化,而集合互不相交的两个任务 并发运行。
from dispatchatlas.core import ResourceAmount, ResourceId, ResourceRequirement
# A task that co-allocates a compute node and an accelerator simultaneously.
demands = (
ResourceRequirement(ResourceId("edge-0"), ResourceAmount(1.0)),
ResourceRequirement(ResourceId("gpu-1"), ResourceAmount(1.0)),
)accelerator-coscheduling、distributed-transaction 与 fpga-partitioning 连续体族行使这一杠杆——前者以
固定的计算加加速器的持有,后者以对数据分片的可变基数锁集合。可运行的
examples/inspect_coallocation.py
对两者都进行调度,并展示资源互不相交的任务并行运行、而共享资源的任务串行化。
🧩 可塑执行
一个任务可以在若干模式之一中运行。TaskSpec.modes 是一个 TaskMode 的元组——每个是
一个 (demands, duration) 对,其中更宽的模式(要求更多资源者)运行得更短,即可塑加速。
当设置了 modes 时任务即为可塑的:调度构造器按任务、依据哪些资源空闲,挑选最早完成的
模式,因此调度顺序决定每个任务主张多少并行度。刚性任务保持 modes 未设置(默认值),其
顶层 duration 与 demands 即为其单一模式,精确求解后端将其作为保守参考来调度。
validate_schedule 确认每次放置匹配一个已声明的模式,且可塑执行与不精确
(mandatory_duration)执行互斥——一个任务要么选择其并行度,要么舍弃可选工作,而非
两者兼有。
from dispatchatlas.core import (
Duration,
ResourceAmount,
ResourceId,
ResourceRequirement,
TaskMode,
)
# Two ways to run one job: wide-and-fast on two workers, or narrow-and-slow on one.
modes = (
TaskMode(
demands=(
ResourceRequirement(ResourceId("worker-0"), ResourceAmount(1.0)),
ResourceRequirement(ResourceId("worker-1"), ResourceAmount(1.0)),
),
duration=Duration(1.0),
),
TaskMode(
demands=(ResourceRequirement(ResourceId("worker-0"), ResourceAmount(1.0)),),
duration=Duration(1.8),
),
)elastic-serverless-autoscale 连续体族行使这一杠杆:每次函数调用可以扩展到从一个小型
共享突发池中取用的一个、两个或四个工作者,因此调度顺序决定哪些调用主张稀缺的宽-且-快
模式、哪些以窄模式运行——一种延迟对资源成本的权衡。
🛰️ 团组共调度
共享 TaskSpec.gang_id 的任务构成一个团组,其工作者必须全部在不同资源上同时启动——
一种全有或全无的共启动,正如一个同步分布式训练或 MPI 作业需要其工作者一起运行。串行
构造器在每个工作者的资源都空闲的最早时刻原子地放置整个团组,即便某个工作者本可单独
更早启动;validate_schedule 拒绝其工作者不共启动的团组
(schedule.feasibility.gang_cosched)。团组工作者是刚性的(非可塑),因为团组以固定
宽度共启动;独立任务保持 gang_id 未设置。
from dispatchatlas.core import (
Duration,
ResourceAmount,
ResourceId,
ResourceRequirement,
TaskId,
TaskSpec,
)
# Two workers of one training job that must launch together on distinct accelerators.
gang = "train-job-0"
workers = tuple(
TaskSpec(
id=TaskId(f"worker-{index}"),
duration=Duration(2.0),
demands=(ResourceRequirement(ResourceId(f"acc-{index}"), ResourceAmount(1.0)),),
gang_id=gang,
)
for index in range(2)
)distributed-training-gang 连续体族行使这一杠杆:两到四个工作者的团组复用一个共享
加速器池,且作业随时间到达,因此一个作业在足够的加速器同时空闲之前无法开始,而调度
顺序决定哪个作业首先获取其完整的工作者集合。
⚖️ 多租户公平共享
任务携带一个可选的 TaskSpec.tenant_id,标注其所属租户,用于多租户公平共享核算。
dominant-resource-share 目标(ObjectiveKind.DOMINANT_RESOURCE_SHARE,依据 Ghodsi
等人的支配资源公平性)评分各租户的支配份额平衡得多均匀:每个租户的支配份额是其任务所
占用的某资源总容量-时间在各资源间的最大比例,而该目标是服务最多与最少的租户之间的离散
程度——对于支配份额相等(公平)的调度为 0.0,当某租户垄断其支配资源时更高。该目标为
最小化取向,在无租户实例上返回 DEFERRED。tenant_id 与团组、可塑、不精确执行正交——
一个租户的任务可以是其中任何一种;无租户任务保持 tenant_id 未设置。
杠杆在于放置,而非调度顺序:一个租户的总资源占用由其工作负载固定,因此其任务落在哪些
资源上才是平衡或扭曲支配份额的所在。可运行的
examples/multi_tenant_fairshare_study.py
在一个三节点池上对一个重租户与一个轻租户的公平(分散)放置对垄断放置进行评分,使该杠杆
显式可见。
⏱️ 硬截止与软截止
一个任务可以携带一个完成 TaskSpec.deadline,而 TaskSpec.deadline_kind 分类如何判定
一次错失。默认值 ConstraintKind.HARD 使错失的截止成为可行性违反:validate_schedule
抛出一个阻塞性的 schedule.feasibility.deadline 问题,调度报告为不可行。
ConstraintKind.SOFT 使同一错失仅成为延迟惩罚——调度保持可行,同时超额累计到 lateness
目标(ObjectiveKind.LATENESS),因此一个软实时任务因迟到而受罚,却不致使调度不可行。
当 deadline 未设置时该种类无效。
对截止的两种解读相互独立:硬截止界定可行区域,而软截止塑造目标曲面,任务可以使用任一。
可运行的
examples/infeasibility_study.py
端到端走过硬截止情形——一个过约束实例被报告为不可行,以及当不存在可行调度时的
最小不可行顺序。
💰 成本模型
成本感知调度由 CostModel 描述,这是一个独立的不可变产物,通过其标识符与某个问题
关联。将成本层置于 ProblemSpec 之外,使一个问题及其成本数据能独立地版本化与序列化。
一个成本模型捆绑五个可选契约:
ExecutionTimeMatrix——用于R||Cmax族的非相关机处理时间(p_ij)。该矩阵是 稀疏的:一个缺失的(task, machine)对意味着该任务不能在那里运行,且查询它会抛出 错误,而非默认为零。CompatibilityMask——一个显式的任务-到-机器资格集合,与执行矩阵分开维护,使资格 与制表时间可以分歧。SetupMatrix——序列相关的准备时间,按机器上的任务-到-任务或类型-到-类型转换索引。LoadModel——一条负载相关的执行曲线,通过在严格递增的断点之间进行分段线性或阶梯 插值,将负载水平映射到时长乘数。CommunicationModel——稀疏图上的跨资源通信惩罚;同机通信免费,未列出的跨机对回退 到一个声明的默认惩罚。
from dispatchatlas.core import (
CostModel,
ProblemId,
ResourceId,
TaskId,
execution_matrix_from_iterable,
)
cost_model = CostModel(
problem_id=ProblemId("smoke"),
execution_matrix=execution_matrix_from_iterable(
[(TaskId("task-a"), ResourceId("cpu"), 1.0)]
),
)🎯 目标与归约
目标族在 OBJECTIVE_FAMILY 中命名,它记录每个目标的正典取向与单位:makespan、能量、
成本、碳、延迟、迟到、公平性、支配资源份额(服务最多与最少的租户的支配资源份额之间的
离散程度——多租户公平共享)、可靠性、安全性、鲁棒性、准备,不精确奖励(在部分可执行
任务的强制部分之外完成的可选计算),以及加权复合。测得结果由 VectorObjectiveValue
承载,它持有一个或多个 ObjectiveValue 条目(按名称排序)加上一个显式的
ObjectiveReduction 与一个披露标签。加权和与 Chebyshev 归约将向量标量化;非标量化归约
(NONE、LEXICOGRAPHIC)在 scalarize() 上抛出错误,以便调用方显式处理排序。
✅ 可行性报告
build_feasibility_report 将一份调度验证报告转化为对审阅者可见的 FeasibilityReport:
硬违反成为逐行的 InfeasibleRow 记录,而被违反的具名软约束累计加权的
SoftConstraintPenalty 条目。软违反绝不会把 feasible 翻转为 False。
📐 目标评估、约束与前沿
目标-与-约束层逐一计算每个具名目标,因此无一被折叠进通用捆绑。evaluate_objective
直接从调度导出 makespan、迟到、负载公平性(Jain 指数),以及——对于带租户标注的实例——
支配资源份额公平性,从附带的执行时间矩阵导出成本、从附带的准备矩阵导出序列相关的准备
时间,并将计算出的各成分归约为一个加权复合。需要核心未携带之模型的目标(能量、碳、
延迟、可靠性、安全性、鲁棒性)返回一个状态为 DEFERRED 且带具名理由的
ObjectiveEvaluation,而非捏造的值。MultiObjectiveOutcome 将标量值、向量目标与可行性
报告通过一次确定性的序列化往返进行承载。
约束核算将具名的服务水平(SLA)约束作为一等约束加入,兼具一条硬违反路径(一种不可行性)
与一条软惩罚路径(一种与违反成比例的加权惩罚)。ConstraintViolationSummary 聚合硬
违反、软惩罚、SLA 结果与修复诊断;它在硬规则违反或硬 SLA 违反任一情形下报告不可行。
Pareto 辅助器提取非支配前沿,并报告依据 Riquelme、Von Lücken & Barán (2015) 选定的四个
具名质量指标:超体积(主要指标)、IGD+(一个弱-Pareto-相容的收敛指标)、加性
epsilon-指标,以及散布(多样性指标)。每个指标都可单独计算。frontier_data 构建带
非支配标志的前沿就绪记录,供分析与门户渲染。
鲁棒性被量化为一个可度量的目标,而非一个姿态标签:evaluate_robustness 在一个显式
声明的扰动集合上聚合某一目标的值,或作为最坏情形值,或作为最坏尾部的条件风险价值
(CVaR)。扰动集合与聚合两者都记录于结果之上。
⚠️ 局限
核心内核定义成本、目标与约束的契约,以及评估它们的目标-与-约束层;它不进行优化。
需要核心未携带之模型的目标(能量、碳、延迟、可靠性、安全性与鲁棒性)被报告为延迟并附
具名理由,而非被估算。LoadModel 仅评估其自身声明的曲线,而 ObjectiveDefinition
承载元数据而非一个评估器。
🌱 出处与种子
生成的产物携带 Provenance、ArtifactHash、SourceReference、EnvironmentStamp 与
可选的 SeedLineage 记录。种子流由稳定坐标导出:
from dispatchatlas.core import derive_seed
seed = derive_seed(42, "benchmark.smoke", 0)相同的根种子、命名空间与索引始终产生相同的导出种子。
📦 序列化
核心对象通过正典的 JSON 兼容映射与 ArtifactEnvelope 包装器进行序列化。包装器将载荷
绑定到内容哈希,并将该哈希复制回出处。
🔌 协议
外层包依赖核心定义的协议:
BenchmarkProviderSolverExperimentRunnerResultRepositoryDisclosurePolicyAnalysisExporter
这些协议使包导入保持向内定向,同时允许具体的基准、求解器、实验与分析包在之后进行组合。