/ concept-collection / fastandaccurate
Sign in
concept-collection / fastandaccurate
fastandaccurate / src / harness / resultSchema.ts
134 lines · 4.0 KBBlameHistoryRaw
1// The result-file format committed to the fastandaccurate-results repo.
2// One file holds one work-precision sweep: one problem instance, one
3// solver, one environment.
5import {
6 canonicalSpec,
7 canonicalSpecJson,
8 PROBLEM_ID,
9 PROBLEM_VERSION,
10 type Laplace2dInstance,
11} from "../problems/laplace2d/spec";
12import type { RunPoint } from "./runner";
13import type { TimingPolicy } from "./timing";
15export const RESULT_FORMAT = "fastandaccurate-result";
16export const RESULT_FORMAT_VERSION = 1;
18export interface ResultEnvironment {
19 kind: "browser" | "node" | "matlab";
20 /** User agent (browser), node version (node), or MATLAB version. */
21 runtime: string;
22 /** Absent for runs outside numbl (e.g. real MATLAB). */
23 numblVersion?: string;
24 os?: string;
25 cpu?: string;
26 /** The WebGPU adapter, for a solver that ran on one, and how WebGPU was
27 * reached. Absent otherwise. */
28 gpu?: string;
29 /** Free-text label a human recognizes ("office workstation"). */
30 machineLabel?: string;
31 /** Whether a visitor can rerun this result in the browser. */
32 browserReproducible: boolean;
35export interface ResultPoint {
36 n: number;
37 /** The fastest of the timed runs. */
38 solveSeconds: number;
39 solveSecondsAll: number[];
40 coldSeconds: number;
41 relMax: number;
42 relL2: number;
45export interface ResultFile {
46 format: typeof RESULT_FORMAT;
47 formatVersion: typeof RESULT_FORMAT_VERSION;
48 problem: string;
49 problemVersion: number;
50 instance: string;
51 spec: Record<string, unknown>;
52 specHash: string;
53 solver: {
54 id: string;
55 version: string;
56 backend: "cpu" | "gpu";
57 /** "builtin" for solvers in the fastandaccurate repo; otherwise a
58 * URL or free-text pointer to the solver's source. */
59 source: string;
60 };
61 environment: ResultEnvironment;
62 protocol: {
63 warmupRuns: number;
64 /** The adaptive timed-run policy: at least minTimedRuns runs, then as
65 * many more as fit in timeBudgetSeconds, never past maxTimedRuns. How
66 * many a given point actually ran is the length of its
67 * solveSecondsAll. */
68 minTimedRuns: number;
69 timeBudgetSeconds: number;
70 maxTimedRuns: number;
71 /** Which statistic of the timed runs is reported as solveSeconds. */
72 statistic: "min";
73 timer: string;
74 /** Results written before the adaptive policy carry a fixed count
75 * here instead of the three fields above. */
76 timedRuns?: number;
77 };
78 createdUtc: string;
79 points: ResultPoint[];
82/** SHA-256 hex digest, using WebCrypto (browser, worker, node >= 20). */
83export async function sha256Hex(text: string): Promise<string> {
84 const digest = await crypto.subtle.digest(
85 "SHA-256",
86 new TextEncoder().encode(text)
87 );
88 return Array.from(new Uint8Array(digest))
89 .map((b) => b.toString(16).padStart(2, "0"))
90 .join("");
93export function toResultPoint(p: RunPoint): ResultPoint {
94 return {
95 n: p.n,
96 solveSeconds: p.solveSeconds,
97 solveSecondsAll: p.solveSecondsAll,
98 coldSeconds: p.coldSeconds,
99 relMax: p.relMax,
100 relL2: p.relL2,
101 };
104export async function buildResultFile(opts: {
105 instance: Laplace2dInstance;
106 solver: { id: string; version: string; backend: "cpu" | "gpu"; source: string };
107 environment: ResultEnvironment;
108 timing: TimingPolicy;
109 points: ResultPoint[];
110 /** What measured the times (default numbl tic/toc). */
111 timer?: string;
112}): Promise<ResultFile> {
113 return {
114 format: RESULT_FORMAT,
115 formatVersion: RESULT_FORMAT_VERSION,
116 problem: PROBLEM_ID,
117 problemVersion: PROBLEM_VERSION,
118 instance: opts.instance.id,
119 spec: canonicalSpec(opts.instance) as unknown as Record<string, unknown>,
120 specHash: await sha256Hex(canonicalSpecJson(opts.instance)),
121 solver: opts.solver,
122 environment: opts.environment,
123 protocol: {
124 warmupRuns: 2,
125 minTimedRuns: opts.timing.minTimedRuns,
126 timeBudgetSeconds: opts.timing.timeBudgetSeconds,
127 maxTimedRuns: opts.timing.maxTimedRuns,
128 statistic: "min",
129 timer: opts.timer ?? "numbl tic/toc",
130 },
131 createdUtc: new Date().toISOString(),
132 points: opts.points,
133 };
moveopenescclose