model の設計

設計目標

他のすべてのパッケージは model を通じてデータをやり取りします。このパッケージは、バージョン付きで、失敗について明示的で、結果をそのプロトコル、入力、環境までたどれるほど完全な語彙を定めます。識別情報とアクセサ以外の振る舞いは持たないため、すべての層から循環なしに依存できます。

数学的背景

同値関係としての環境の互換性

環境スナップショットを、semantic 部分 σ\sigma、performance 部分 π\pi、provenance ρ\rho を用いて e=(σ,π,ρ)e = (\sigma, \pi, \rho) と書きます。environment_compatible は次のとおりです

e∼e′  ⟺  (σ,π)=(σ′,π′),e \sim e' \iff (\sigma, \pi) = (\sigma', \pi'),

フィールドごとに比較します。これは射影 p(e)=(σ,π)p(e) = (\sigma, \pi) の核です: e∼e′  ⟺  p(e)=p(e′)e \sim e' \iff p(e) = p(e')。等号は反射的、対称的、推移的なので、任意の写像の核は同値関係です。したがって、一連の実行のスナップショットはクラスに分かれ、比較が意味を持つのはちょうど同じクラス内です。推移性は実際に重要です。実行 A を B と比較でき、B を C と比較できるなら、A を C と比較できるため、一度保存したベースラインを同じクラスの後の任意の実行に使えます。

許容誤差を伴う関係(例えば「CPU 周波数が 5 % 以内」)は推移的でなく、実行をクラスに分けられません。検査が宣言された文字列の完全一致であるのはそのためです。

直和型としての結果

操作は値を生成するか、異なる扱いに値するいくつかの方法のいずれかで失敗します。結果を直和としてモデル化すると、

Outcome(V)=V+V×Flags+Trap×Flags+3⋅Reason+Exit×Stderr+Ms×Reason,\text{Outcome}(V) = V + V \times \text{Flags} + \text{Trap} \times \text{Flags} + 3 \cdot \text{Reason} + \text{Exit} \times \text{Stderr} + \text{Ms} \times \text{Reason},

型、イベント、レポートにおいてケースが区別されたまま保たれます。value_option は最初の 2 つの成分への射影です。他の成分はいずれも値を持たず、それを含む計時バッチは無効です。

設計上の決定

バージョン付きの識別子

問題。 古い JSONL のリーダーが新しいフィールドを黙って誤読してはなりません。選択。 3 つのバージョン enum が識別子 mmkp_1(プロトコルの語彙)、mmka_1(イベントのアーティファクト)、mmks_1(Plot IR)を生成します。すべてのイベントは artifact_version を持ち、リーダーは未知のバージョンを拒否します。理由。 追加的な変更ではバージョンを保ちます。互換性を壊す変更では V2 とライフサイクルの項目を追加し、古いリーダーは推測する代わりに明示的に失敗します。

3 つの部分からなる環境スナップショット

問題。 違いには、正しさを無効にするもの(ターゲット、フラグ、ABI)、計時を無効にするもの(CPU、GC、時計、周波数ポリシー)、単なる記録上のもの(ホスト名、時刻、リビジョン)があります。選択。 SemanticEnvironment、PerformanceEnvironment、ProvenanceEnvironment に分け、互換性は最初の 2 つで判定します。理由。 宣言されたハードウェアが同じなら、異なるホストでの 2 つの実行は比較可能なままです。フラグが異なる実行は比較できません。スナップショットは宣言したものを記録します。mare_mark はマシンを調査しません。

明示的なプロトコル

問題。 「ベンチマークを実行した」だけでは、ウォームアップ、バッチサイズ、順序、サンプル数、判断の閾値が隠れてしまいます。選択。 RunProtocol がそれらすべてに名前を付け、protocol_identity がウォームアップ回数、確認サンプル数、実用的な閾値を短いキーにまとめます。理由。 結果が再現可能なのは、そのプロトコルが再現可能な場合だけです。キーは意図的に短く、すべてのフィールドを含むわけではありません。比較される結果の隣には完全なプロトコルを保存してください。

文字列ではなく失敗の種類

ExecutionOutcome は、ワーカーのクラッシュ(Aborted)を、タイムアウト、デコードの問題、サポートされない入力、受け入れられた差異から区別し、ValidationStatus はオラクル側でそれを反映します。レポートはケイパビリティ行列で各種類を数えるため、「未サポート」が「誤り」と読まれることはなく、タイムアウトが遅い計測と読まれることもありません。

コンストラクタを持つ読み取り専用のレコード

レコードは pub struct です。フィールドはどこからでも読め、値は new を通じて構築されます。ユーザーが構築する必要のある enum は pub(all) です。IntervalMode と CrossoverResult は関数を通じて構築され、構築経路が 1 つの文書化された道に保たれます。

判断とデプロイの型

ScaleBoundary、Region、ParetoPoint、DeploymentPolicy、CrossoverResult は、計測された優位性がどのようにデプロイの規則になるかを記述します。これらが model にあるので、experiment、tune、アプリケーションは互いに依存せずにこれらについて合意できます。

正しさと不変条件

  • environment_compatible は(上で導いたとおり)同値関係です。
  • すべてのバージョン enum について X::identifier() は implementation() + "_" + version() であり、V1 値は Supported です。
  • ExecutionOutcome::value_option(o) は Value と RaisedFlags に対してちょうど Some になります。flags(o) が空でないのは RaisedFlags と Trapped の場合だけです。
  • OperationResult::completed(v, c) は、出力が空で終了コードのない OperationResult::new(Value(v), Some(c)) と等しくなります。
  • コンストラクタは何もコピーせず、何も検証しません。検証は runner.validate_protocol と BenchSpec::compile の役割です。

採用しなかった代替案

  • 環境を調査する。 CPU のモデル、ガバナー、GC の設定を読むにはプラットフォームごとのコードと権限が必要です。宣言された値は明示的でテスト可能です。
  • 許容誤差のある互換性。 推移的ではありません(上記を参照)。
  • 自由形式の結果文字列。 失敗の種類の区別が失われます。
  • 1 つのフラットなプロトコル文字列。 読めず、検証もされません。

境界

  • 値の検証、IO、シリアライズは行いません(JSON は event、report、tune_gemm にあります)。
  • protocol_identity は 3 つのフィールドしか含みません。
  • ExperimentDesign、ValidationCoverage、OutlierPolicy、WorkspaceScope は記録された意図であり、ランナーはこれらを解釈しません。
  • ProtocolVersion、ArtifactVersion、SchemaVersion はそれぞれ 1 つのバージョンしか持たず、移行のためのコードはありません。