mirror of
https://github.com/tinygrad/tinygrad.git
synced 2026-04-29 03:00:14 -04:00
viz: ui cleanups from the sqtt real time branch (#15195)
* label location for packets * work * OTHER_* packets always get filtered out * less
This commit is contained in:
@@ -268,7 +268,7 @@ function setFocus(key) {
|
||||
const html = d3.select(".info").html("");
|
||||
if (eventType === EventTypes.EXEC) {
|
||||
const [n, _, ...rest] = e.arg.tooltipText.split("\n");
|
||||
html.append(() => tabulate([["Name", colored(e.label)], ["Duration", formatTime(e.width)], ["Start Time", formatTime(e.x)]]));
|
||||
html.append(() => tabulate([["Name", colored(e.arg.label)], ["Duration", formatTime(e.width)], ["Start Time", formatTime(e.x)]]));
|
||||
let group = html.append("div").classed("args", true);
|
||||
for (const r of rest) group.append("p").text(r);
|
||||
group = html.append("div").classed("args", true);
|
||||
@@ -323,10 +323,10 @@ function setFocus(key) {
|
||||
|
||||
const EventTypes = { EXEC:0, BUF:1 };
|
||||
|
||||
async function renderProfiler(path, unit, opts) {
|
||||
async function renderProfiler(path, opts) {
|
||||
displaySelection("#profiler");
|
||||
// support non realtime x axis units
|
||||
formatTime = unit === "realtime" ? formatMicroseconds : formatCycles;
|
||||
formatTime = opts.unit === "ms" ? formatMicroseconds : formatCycles;
|
||||
if (data?.path !== path) { data = {tracks:new Map(), axes:{}, path, first:null, pcToShape:new Map()}; focusedDevice = null; focusedShape = null; }
|
||||
setFocus(focusedShape);
|
||||
// layout once!
|
||||
@@ -378,16 +378,12 @@ async function renderProfiler(path, unit, opts) {
|
||||
for (let j=0; j<eventsLen; j++) {
|
||||
const e = {name:strings[u32()], ref:optional(u32()), key:optional(u32()), st:u32(), dur:f32(), info:strings[u32()] || null};
|
||||
// find a free level to put the event
|
||||
let depth = 0;
|
||||
if (opts.levelKey != null) { depth = opts.levelKey(e); levels[depth] = 0; }
|
||||
else {
|
||||
depth = levels.findIndex(levelEt => e.st >= levelEt);
|
||||
const et = e.st+Math.trunc(e.dur);
|
||||
if (depth === -1) {
|
||||
depth = levels.length;
|
||||
levels.push(et);
|
||||
} else levels[depth] = et;
|
||||
}
|
||||
let depth = levels.findIndex(levelEt => e.st >= levelEt);
|
||||
const et = e.st+Math.trunc(e.dur);
|
||||
if (depth === -1) {
|
||||
depth = levels.length;
|
||||
levels.push(et);
|
||||
} else levels[depth] = et;
|
||||
if (depth === 0 || opts.colorByName) colorKey = e.name.split(" ")[0];
|
||||
if (!colorMap.has(colorKey)) {
|
||||
const color = typeof colors === "function" ? colors(colorKey)
|
||||
@@ -597,7 +593,7 @@ async function renderProfiler(path, unit, opts) {
|
||||
const labelX = x+ctx.lineWidth+2;
|
||||
if (labelX <= lastLabelEnd) continue;
|
||||
|
||||
const label = formatTime(tick, et-st <= 1e3 ? true : false);
|
||||
const label = formatTime(tick, et-st <= 1e3);
|
||||
ctx.textBaseline = "top";
|
||||
ctx.fillText(label, labelX, tickSize);
|
||||
lastLabelEnd = labelX + ctx.measureText(label).width + 4;
|
||||
@@ -880,7 +876,7 @@ async function main() {
|
||||
if (url.pathname+url.search !== ckey) e.close();
|
||||
else if (e.readyState === EventSource.OPEN) activeSrc = e;
|
||||
}
|
||||
if (ctx.name === "Profiler") return renderProfiler("/get_profile", "realtime", { width:"132px" });
|
||||
if (ctx.name === "Profiler") return renderProfiler("/get_profile", {unit:"ms", width:"132px"});
|
||||
if (workerUrl == null) await initWorker();
|
||||
if (ckey in cache) {
|
||||
ret = cache[ckey];
|
||||
@@ -898,8 +894,8 @@ async function main() {
|
||||
}
|
||||
// timeline with cycles on the x axis
|
||||
if (ret instanceof ArrayBuffer) {
|
||||
opts = {heightScale:0.5, hideLabels:true, levelKey:step.name.includes("PKTS") ? (e) => parseInt(e.name.split(" ")[1].split(":")[1]) : null, colorByName:ckey.includes("pkts")};
|
||||
return renderProfiler(ckey, "clk", opts);
|
||||
const pkts = step.name.includes("PKTS");
|
||||
return renderProfiler(ckey, {unit:"clk", heightScale:0.5, hideLabels:true, colorByName:pkts});
|
||||
}
|
||||
metadata.replaceChildren(...((ret.metadata ?? []).map((m) => {
|
||||
return tabulate(m.map((e) => [e.label.trim(), typeof e.value === "string" ? e.value : formatUnit(e.value)]));
|
||||
|
||||
@@ -340,17 +340,17 @@ def sqtt_timeline(data:bytes, lib:bytes, target:str) -> list[ProfileEvent]:
|
||||
ret:list[ProfileEvent] = []
|
||||
rows:dict[str, None] = {}
|
||||
trace:dict[str, set[int]] = {}
|
||||
def add(name:str, p:PacketType, idx=0, width=1, op_name=None, wave=None, info:InstructionInfo|None=None) -> None:
|
||||
def add(name:str, p:PacketType, width=1, op_name=None, wave=None, info:InstructionInfo|None=None) -> None:
|
||||
if hasattr(p, "wave"): wave = p.wave
|
||||
rows.setdefault(r:=(f"WAVE:{wave}" if wave is not None else f"{p.__class__.__name__}:0 {name}"))
|
||||
key = TracingKey(f"{op_name if op_name is not None else name} OP:{idx}", ret=f"PC:{info.pc}" if info is not None else None)
|
||||
key = TracingKey(f"{op_name if op_name is not None else name}", ret=f"PC:{info.pc}" if info is not None else None)
|
||||
ret.append(ProfileRangeEvent(r, key, Decimal(p._time), Decimal(p._time+width)))
|
||||
for p, info in map_insts(data, lib, target):
|
||||
if len(ret) > getenv("MAX_SQTT_PKTS", 50_000): break
|
||||
if isinstance(p, (INST, INST_RDNA4)):
|
||||
op_name = p.op.name if isinstance(p.op, (InstOp, InstOpRDNA4)) else f"0x{p.op:02x}"
|
||||
name, width = (op_name, 10 if "BARRIER" in op_name else 1)
|
||||
add(name, p, width=width, idx=int("OTHER" in name), info=info)
|
||||
add(name, p, width=width, info=info)
|
||||
if isinstance(p, (VALUINST, IMMEDIATE)): add(p.__class__.__name__, p, info=info)
|
||||
if isinstance(p, IMMEDIATE_MASK): add("IMMEDIATE", p, wave=unwrap(info).wave, info=info)
|
||||
if isinstance(p, (VMEMEXEC, ALUEXEC)):
|
||||
|
||||
Reference in New Issue
Block a user