Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 23 additions & 23 deletions tools/su2_dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -1052,8 +1052,8 @@ <h1>SU(2) Measurement Dashboard</h1>
title="Amber marks the active spatial direction (sdir) used with the current time direction for loop/flux operators."><span
class="cursor-legend-swatch s"></span>Amber: space dir (s)</span>
<span class="cursor-legend-item"
title="Green markers are the remaining lattice axes (mu) not currently chosen as time or space direction."><span
class="cursor-legend-swatch other"></span>Green: other mu</span>
title="The remaining lattice axes (mu). They carry no marker: the GPU heat bath updates every direction in one kernel, so the driver reports no per-direction position for them (only T along tdir and R along sdir)."><span
class="cursor-legend-swatch other"></span>Rows show the current loop's T and R as text; markers were removed (the cursor is a scan, not a position)</span>
<span class="cursor-legend-item"
title="Magenta track is per-thread overall config progress from meas_cfg_substep_progress (0-100% of current config), independent of which mu row is active."><span
class="cursor-legend-swatch cfg"></span>Magenta track: cfg progress</span>
Expand Down Expand Up @@ -2897,29 +2897,18 @@ <h1>SU(2) Measurement Dashboard</h1>
}

function muProgressVector(coords, dims, cfgProgress, muCount = 4) {
if (Number.isFinite(cfgProgress)) {
// Keep per-mu cursors tightly coupled to true cfg progress.
// This avoids large visual jumps when raw lattice shift telemetry changes axes.
const base = clamp01(cfgProgress);
const center = (muCount - 1) / 2;
const spread = 0.06;
const vals = Array.from({ length: muCount }, (_, mu) => {
const offset = center > 0 ? ((mu - center) / center) : 0;
return clamp01(base + spread * offset);
});
return rebalanceMuMean(vals, base);
}

const raw = Array.from({ length: muCount }, (_, mu) => {
// Only positions the driver actually reports (#58): for a loop cursor
// that is T along tdir and R along sdir; the other rows have no
// position because the GPU heat bath updates every direction in one
// kernel. Rows without data return NaN and draw no marker. Nothing is
// synthesised from the cfg-progress scalar any more.
return Array.from({ length: muCount }, (_, mu) => {
const c = toFiniteNumber(coords?.[mu], NaN);
const l = toFiniteNumber(dims?.[mu], NaN);
if (!Number.isFinite(c)) return NaN;
const denom = Number.isFinite(l) && l > 1 ? (l - 1) : 1;
return clamp01(c / denom);
Comment on lines 2906 to 2910

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ignore GPU skip counts as cursor positions

When a GPU worker is in skip_sweeps, this raw-vector path still treats every finite meas_cursor_shift entry as a lattice position. In gpt/applications/hmc/su2_2q_signal_scan.py, the GPU one_sweep() invokes its callback only after the complete 2 * Nd sweep, while on_skip_substep() expands that completion into equal counters for every direction before emitting the shift vector. As a result, all four μ markers still appear and move together in exactly the GPU scenario where the new legend says no per-direction position exists; GPU skip-count vectors should not populate these position rows.

Useful? React with 👍 / 👎.

});
const fallback = meanFinite(raw);
const base = Number.isFinite(fallback) ? fallback : 0;
return raw.map((v) => (Number.isFinite(v) ? v : base));
}

function rebalanceMuMean(values, targetMean) {
Expand Down Expand Up @@ -2947,10 +2936,10 @@ <h1>SU(2) Measurement Dashboard</h1>
}

function stabilizeThreadMuProgress(key, targetMu, cfgIdx, cfgProgress, tsMs, inProduction, hasFreshData = true) {
const cleanedTarget = (targetMu || []).map((v) => clamp01(toFiniteNumber(v, 0)));
// NaN = no reported position for that row; keep it NaN (#58).
const cleanedTarget = (targetMu || []).map((v) => { const x = toFiniteNumber(v, NaN); return Number.isFinite(x) ? clamp01(x) : NaN; });
const prev = cursorMuStateByThread[key];
const targetMean = Number.isFinite(cfgProgress) ? clamp01(cfgProgress) : meanFinite(cleanedTarget);
const snapped = Number.isFinite(targetMean) ? rebalanceMuMean(cleanedTarget, targetMean) : cleanedTarget;
const snapped = cleanedTarget; // never rebalanced onto the cfg-progress scalar
// Hold last rendered point between telemetry samples; move only on fresh data.
const out = (hasFreshData || !prev || !inProduction)
? snapped
Expand Down Expand Up @@ -3595,7 +3584,18 @@ <h1>SU(2) Measurement Dashboard</h1>
const baseLabel = Number.isFinite(l) ? `mu${mu} (L=${l})` : `mu${mu}`;
ctx.fillText(role ? `${baseLabel} [${role}]` : baseLabel, 8, y + 4);

const frac = muProgress[mu];
// #58: the driver's cursor is a scan over loop geometries (R, T hop
// with every operator), not a position that travels along an axis;
// drawn as a marker it jumps wildly. Show the values as text and
// leave the magenta cfg track as the only moving element.
const frac = NaN;
if (isT && Number.isFinite(tVal)) {
ctx.fillStyle = "#52adff";
ctx.fillText(`T=${Math.round(tVal)}`, padL + 4, y + 4);
} else if (isS && Number.isFinite(rVal)) {
ctx.fillStyle = "#f2c14b";
ctx.fillText(Number.isFinite(rPerp) ? `R=${Math.round(rVal)} r⊥=${Math.round(rPerp)}` : `R=${Math.round(rVal)}`, padL + 4, y + 4);
}
if (Number.isFinite(frac)) {
const x = padL + frac * iw;
const markerColor = isT
Expand Down
Loading