report のチュートリアル

このチュートリアルでは、ベンチマークの結果を公開します。JSONL イベントストリームを自己完結型の HTML ページとして描画し、失敗した検証がどう表示されるかを確認し、機械可読な mmks_1 JSON をエクスポートし、独自のプロットを描きます。例は完全なテストです。ファイルの書き出しはプログラムまたは mare-mark コマンドに任せます。

クイックスタート

moon add Luna-Flow/mare_mark@0.3.0
import {
  "Luna-Flow/mare_mark/ir_model",
  "Luna-Flow/mare_mark/report",
  "Luna-Flow/mare_mark/model",
  "Luna-Flow/mare_mark/event",
  "Luna-Flow/mare_mark/runner",
  "moonbitlang/async",
}
test "JSONL to HTML" {
  let events =
    #|{"type":"observation","case":"add","implementation":"baseline","dataset_id":0,"elapsed_us":12.5}
    #|{"type":"observation","case":"add","implementation":"candidate","dataset_id":0,"elapsed_us":10.2}
    #|{"type":"summary","run_id":"first-report"}
  let document = @report.document_from_jsonl(events, target="native").unwrap()
  let page = @report.html(document)
  inspect(page.contains("Run first-report"), content="true")
  inspect(page.contains("<svg"), content="true")
}

page を report.html として保存し、ブラウザで開いてください。サーバーもネットワークも不要です。

日常的な作業

ランナーから直接実行をレポートする

JsonlSink は、document_from_jsonl が読むストリームをそのまま生成します:

async test "run and render" {
  let negate = @runner.Implementation::stateless("negate", "1", (x : Int) => {
    @model.OperationResult::completed(-x, ())
  })
  let plan = @runner.single_step("negate", [1, 2, 3])
    .with_immutable_input(context => context.dataset_key.scale, x => x.to_string())
    .compare([negate])
    .against_equal(x => -x, (expected, actual) => expected == actual)
    .compile()
    .unwrap()
  let sink = @event.JsonlSink::new()
  let environment = @model.EnvironmentSnapshot::new(
    @model.SemanticEnvironment::new(@model.ExecutionTarget::Native, "moonc", "", "i32"),
    @model.PerformanceEnvironment::new("native", "cpu", "default", 1, "monotonic"),
    @model.ProvenanceEnvironment::new("os", "host", "now", "HEAD", "report-tutorial"),
  )
  ignore(
    @runner.run(
      plan,
      @runner.RunContext::new(environment, sink.as_sink(), 5UL, @runner.ProtocolPreset::QuickCheck.validated()),
    ),
  )
  let document = @report.document_from_jsonl(sink.to_jsonl(), target="native").unwrap()
  inspect(document.plots[0].points.length(), content="12")
  inspect(document.differential.corpus.passed, content="3")
}

3 つのスケール × 4 つのブロックで 12 個の点になり、観測ごとに 1 点です。

誤った実装がどうなるかを見る

検証が失敗すると、そのデータセットにおけるその実装の点が取り除かれ、不一致の行が追加されます:

test "failures hide series and show mismatches" {
  let events =
    #|{"type":"observation","case":"add","implementation":"good","dataset_id":0,"elapsed_us":12.0}
    #|{"type":"observation","case":"add","implementation":"fast-but-wrong","dataset_id":0,"elapsed_us":1.0}
    #|{"type":"validation","status":"invalid","case":"add","implementation":"fast-but-wrong","dataset_id":0,"operation":"add","operands":["1","2"],"expected":"3","actual":"4","actual_kind":"value"}
    #|{"type":"summary","run_id":"mismatch","passed_count":1,"failed_count":1}
  let document = @report.document_from_jsonl(events).unwrap()
  inspect(document.plots[0].points.length(), content="1")
  inspect(document.plots[0].points[0].series, content="good")
  inspect(document.differential.mismatches[0].actual, content="4")
  inspect(@report.html(document).contains("Mismatches"), content="true")
}

他のツールのために JSON をエクスポートする

plot_json は同じドキュメントを mmks_1 JSON として書き出します。ノートブックやダッシュボードは HTML を解析せずにこれを読めます:

test "machine-readable output" {
  let events =
    #|{"type":"observation","case":"add","implementation":"a","dataset_id":0,"elapsed_us":2.5}
  let json = @report.plot_json(@report.document_from_jsonl(events).unwrap())
  inspect(json.contains("\"kind\":\"scaling\""), content="true")
  inspect(json.contains("\"y\":2.5"), content="true")
}

独自のプロットを描く

Plot IR は単なるデータです。例えばチューニングのスイープからドキュメントを手で構築し、同じ関数で描画します:

test "a hand-made heatmap" {
  let cells = [
    @ir_model.PlotPoint::new("mc=32", 3.1, "kc=32"),
    @ir_model.PlotPoint::new("mc=64", 2.7, "kc=32"),
    @ir_model.PlotPoint::new("mc=32", 2.9, "kc=64"),
    @ir_model.PlotPoint::new("mc=64", 2.4, "kc=64"),
  ]
  let plot = @ir_model.Plot::new(@ir_model.PlotKind::Heatmap, "Blocking sweep", "µs/op", "median", cells)
  let svg = @report.plot_svg(plot)
  inspect(svg.contains("<rect"), content="true")
  let document = @ir_model.PlotDocument::new("sweep", "native", [plot])
  inspect(@report.html(document).contains("Blocking sweep"), content="true")
}

さらに先へ

  • ファイルとパイプ。 mare-mark report events.jsonl report.html や mare-mark report - - が読み書きを代わりに行います。cli のチュートリアルを参照してください。
  • レポート内の統計。 比較は stats で計算し、Interval プロットとして、または HTML の周りのテキストとして追加してください。レンダラはそれらを計算しません。
  • JSONL を保存する。 HTML は再生成できる射影であり、JSONL が記録です。

よくある落とし穴

  • キャリブレーションイベントだけのストリーム。 表示するものがないため、エラーになります。
  • x 軸にスケールがあると期待する。 x の値はデータセットのインデックスです。
  • 1 つのファイルに複数の実行を混在させる。 異なる実行の点が一緒にプロットされ、最後の要約が実行 ID を決めます。
  • artifact_version を変更する。 受け付けられるのは mmka_1 だけです。

次のステップ