本文へスキップ
DispatchAtlas
検索

ドメイン契約

dispatchatlas.core は内側のパッケージ境界です。不変かつ標準ライブラリのみのオブジェクトを 用い、ベンチマーク、ソルバー、実験、分析、ドキュメントが単一の共有スケジューリング語彙を 消費できるようにします。

🗂️ スケジューリングモデル

問題は ProblemSpecTaskSpecResourceSpecDependencyObjectiveConstraint で表現されます。候補スケジュールは AssignmentScheduleObjectiveValueScheduleResult を用います。

検証は明示的です:

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.demandsResourceRequirement のタプルであり、スケジュール構築子はタスクが要求するすべてのリソースにわたって タスクを共割り当てし、タスクの全期間それらをまとめて保持します。したがって候補スケジュールは 各配置を Assignment.resource_ids——単一リソースではなくタプル——として記録し、 validate_schedule は時間的に重なる 2 つのタスクが決してリソースを共有しないことを 確認します。

リソース競合グラフがスケジューリングのてこです: 要求集合が交わる 2 つのタスクは直列化 しなければならず、集合が互いに素な 2 つは並行に実行されます。

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-coschedulingdistributed-transactionfpga-partitioning の連続体ファミリーがこのてこを 行使します——前者は計算プラスアクセラレータの固定保持で、後者はデータシャードに対する 可変カーディナリティのロック集合で。実行可能な examples/inspect_coallocation.py は両方をスケジュールし、互いに素なリソースのタスクが並列に実行される一方、リソースを共有する タスクが直列化する様子を示します。

🧩 可塑的実行

タスクは複数のモードのいずれか 1 つで実行できます。TaskSpec.modesTaskMode の タプルであり——各々が (demands, duration) の対で、より広いモード(より多くのリソースを 要求するもの)はより短く実行されます、可塑的スピードアップです。modes が設定されると タスクは可塑的になります: スケジュール構築子は、どのリソースが空いているかに応じて、タスク ごとに最も早く終わるモードを選びます。したがってスケジュール順が各タスクの主張する並列度を 決めます。剛なタスクは modes を未設定のままにし(既定)、その最上位の durationdemands がその単一モードであり、厳密解バックエンドはこれを保守的な基準としてスケジュール します。validate_schedule は各配置が宣言された 1 つのモードに一致することを確認し、 可塑的実行と不精密(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 の連続体ファミリーがこのてこを行使します: 各関数呼び出しは 小さな共有バーストプールから引いた 1、2、または 4 のワーカーにスケールできるため、 スケジュール順がどの呼び出しが希少な広く-速いモードを主張し、どれが狭く実行されるかを 決めます——レイテンシ対リソースコストのトレードオフです。

🛰️ ギャング共スケジューリング

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 の連続体ファミリーがこのてこを行使します: 2〜4 のワーカーの ギャングが共有アクセラレータプールを再利用し、ジョブは時間とともに到着するため、十分な アクセラレータが同時に空くまでジョブは開始できず、スケジュール順がどのジョブが最初に 完全なワーカー集合を獲得するかを決めます。

⚖️ マルチテナント公平分配

タスクは、所有テナントをラベル付けする任意の TaskSpec.tenant_id を持ち、マルチテナント 公平分配の会計に用います。dominant-resource-share 目的(ObjectiveKind.DOMINANT_RESOURCE_SHARE、 Ghodsi et al. の支配的リソース公平性に基づく)は、テナントの支配的シェアがどれだけ均等に 釣り合っているかを採点します: 各テナントの支配的シェアは、リソース横断で、そのタスクが 占有するあるリソースの総容量-時間の最大の割合であり、目的は最も多く-最も少なく供される テナント間の散らばりです——支配的シェアが等しい(公平な)スケジュールで 0.0、1 つの テナントがその支配的リソースを独占すると高くなります。目的は最小化センスで、テナントなしの インスタンスでは DEFERRED を返します。tenant_id はギャング・可塑的・不精密実行に対して 直交します——テナントのタスクはそのいずれでもあり得ます。テナントなしのタスクは tenant_id を未設定のままにします。

てこはスケジュール順ではなく配置です: テナントの総リソース占有はそのワークロードで固定 されるため、そのタスクがどのリソースに着地するかが支配的シェアを釣り合わせるか歪めるかを 決めます。実行可能な examples/multi_tenant_fairshare_study.py は、3 ノードプール上で重いテナントと軽いテナントの公平な(散らした)配置対独占的な配置を 採点し、てこを明示します。

⏱️ ハード期限とソフト期限

タスクは完了 TaskSpec.deadline を持つことができ、TaskSpec.deadline_kind は超過が どう判定されるかを分類します。既定の ConstraintKind.HARD は、超過した期限を実行可能性 違反にします: validate_schedule はブロッキングな schedule.feasibility.deadline 問題を 発生させ、スケジュールは実行不能と報告します。ConstraintKind.SOFT は同じ超過を遅延 ペナルティのみにします——超過分が lateness 目的(ObjectiveKind.LATENESS)に 累積する間スケジュールは実行可能なままであり、ソフトリアルタイムのタスクはスケジュールを 実行不能にせずに遅延で罰せられます。deadline が未設定のときこの種は効果を持ちません。

期限の 2 つの読みは独立です: ハード期限は実行可能領域を制限し、ソフト期限は目的面を 形作り、タスクはどちらも使えます。実行可能な examples/infeasibility_study.py はハード期限のケースを端から端まで辿ります——過剰制約のインスタンスが実行不能と報告され、 実行可能なスケジュールが存在しないときの最小実行不能順を示します。

💰 コストモデル

コスト考慮スケジューリングは CostModel——識別子で問題に紐づく別個の不変成果物——で 記述されます。コスト層を ProblemSpec の外に保つことで、問題とそのコストデータが独立に バージョン管理・シリアライズできます。コストモデルは 5 つの任意契約を束ねます:

  • 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 に名付けられ、各目的の正典的なセンスと単位を記録 します: メイクスパン、エネルギー、コスト、炭素、レイテンシ、遅延、公平性、支配的リソース シェア(最も多く-最も少なく供されるテナントの支配的リソースシェア間の散らばり—— マルチテナント公平分配)、信頼性、セキュリティ、ロバスト性、セットアップ、不精密報酬 (部分実行可能タスクの必須部分を超えて完了した任意計算)、および重み付き複合。測定された 結果は VectorObjectiveValue が運び、1 つ以上の ObjectiveValue エントリ(名前順)に加え 明示的な ObjectiveReduction と開示ラベルを保持します。重み付き和と Chebyshev の還元は ベクトルをスカラー化します。非スカラー化還元(NONELEXICOGRAPHIC)は scalarize() でエラーを発生させ、呼び出し側が順序付けを明示的に扱うようにします。

実行可能性レポート

build_feasibility_report はスケジュール検証レポートを、レビュアーに見える FeasibilityReport に変えます: ハード違反は行ごとの InfeasibleRow 記録になり、 名前付きで違反したソフト制約は重み付き SoftConstraintPenalty エントリを累積します。 ソフト違反は決して feasibleFalse に反転させません。

📐 目的評価、制約、フロンティア

目的-と-制約層は名前付きの各目的を個別に計算するため、いずれも汎用バンドルに畳み込まれ ません。evaluate_objective はメイクスパン、遅延、負荷公平性(Jain の指数)、そして ——テナントラベル付きインスタンスでは——支配的リソースシェア公平性をスケジュールから 直接導き、添付の実行時間行列からコストを、添付のセットアップ行列からシーケンス依存の セットアップ時間を導き、計算された成分を重み付き複合へ還元します。コアが運ばないモデルを 必要とする目的(エネルギー、炭素、レイテンシ、信頼性、セキュリティ、ロバスト性)は、 捏造値ではなく DEFERRED 状態と名前付きの根拠を伴う ObjectiveEvaluation を返します。 MultiObjectiveOutcome はスカラー値、ベクトル目的、実行可能性レポートを決定的な シリアライズ往復を通じて運びます。

制約会計は、名前付きサービスレベル(SLA)制約を、ハード違反パス(実行不能)とソフト ペナルティパス(違反に比例する重み付きペナルティ)の両方を持つ第一級制約として追加します。 ConstraintViolationSummary はハード違反、ソフトペナルティ、SLA 結果、修復診断を集約 します。ハードルール違反またはハード SLA 違反のいずれかで実行不能と報告します。

Pareto ヘルパーは非支配フロントを抽出し、Riquelme, Von Lücken & Barán (2015) に従って 選ばれた 4 つの名前付き品質指標を報告します: ハイパーボリューム(主要指標)、IGD+ (弱 Pareto 整合の収束指標)、加法イプシロン指標、および散らばり(多様性指標)。各指標は 個別に計算可能です。frontier_data は分析とポータルレンダリング向けに、非支配フラグを 伴うフロンティア対応の記録を構築します。

ロバスト性は姿勢ラベルではなく測定可能な目的として定量化されます: evaluate_robustness は、明示的に宣言された摂動集合にわたって 1 つの目的の値を、最悪ケース値として、または 最悪テールの条件付きバリューアットリスク(CVaR)として集約します。摂動集合と集約の両方が 結果に記録されます。

⚠️ 制限事項

コアカーネルはコスト・目的・制約の契約と、それらを評価する目的-と-制約層を定義します。 最適化はしません。コアが運ばないモデルを必要とする目的(エネルギー、炭素、レイテンシ、 信頼性、セキュリティ、ロバスト性)は、推定ではなく名前付きの根拠を伴い延期と報告されます。 LoadModel は自身の宣言された曲線のみを評価し、ObjectiveDefinition は評価器ではなく メタデータを運びます。

🌱 来歴とシード

生成された成果物は ProvenanceArtifactHashSourceReferenceEnvironmentStamp、 任意の SeedLineage 記録を運びます。シードストリームは安定した座標から導かれます:

from dispatchatlas.core import derive_seed
 
seed = derive_seed(42, "benchmark.smoke", 0)

同じルートシード、名前空間、インデックスは常に同じ導出シードを生成します。

📦 シリアライズ

コアオブジェクトは正典的な JSON 互換マッピングと ArtifactEnvelope ラッパーを通じて シリアライズします。エンベロープはペイロードをコンテンツハッシュに束ね、そのハッシュを 来歴へ写し戻します。

🔌 プロトコル

外側のパッケージはコア定義のプロトコルに依存します:

  • BenchmarkProvider
  • Solver
  • ExperimentRunner
  • ResultRepository
  • DisclosurePolicy
  • AnalysisExporter

これらのプロトコルはパッケージのインポートを内向きに保ちつつ、具体的なベンチマーク・ ソルバー・実験・分析パッケージが後で合成できるようにします。