mirror of
https://github.com/tinygrad/tinygrad.git
synced 2026-08-29 15:16:08 +00:00
viz: support collapsing individual CALL nodes (#15006)
* all * contracted all by default * simple call mask * work * minus not hyphen * color / cleanup * detail
This commit is contained in:
@@ -102,6 +102,14 @@
|
||||
fill: #FFD700;
|
||||
stroke: #B8860B;
|
||||
}
|
||||
g.tag.collapsed circle {
|
||||
fill: #5CD68D;
|
||||
stroke: #4a4b57;
|
||||
}
|
||||
g.tag.expanded circle {
|
||||
fill: #9FDDE6;
|
||||
stroke: #4a4b57;
|
||||
}
|
||||
g.port circle {
|
||||
fill: #b3dcc2;
|
||||
}
|
||||
|
||||
@@ -50,18 +50,23 @@ function intersectRect(r1, r2) {
|
||||
return {x:r1.x+dx*scale, y:r1.y+dy*scale};
|
||||
}
|
||||
|
||||
function addTags(root) {
|
||||
function addTags(root, dy) {
|
||||
root.selectAll("circle").data(d => [d]).join("circle").attr("r", 5);
|
||||
root.selectAll("text").data(d => [d]).join("text").text(d => d).attr("dy", "0.35em");
|
||||
root.selectAll("text").data(d => [d]).join("text").text(d => d).attr("dy", `${dy ?? 0.35}em`);
|
||||
}
|
||||
|
||||
const drawGraph = (data) => {
|
||||
const g = dagre.graphlib.json.read(data);
|
||||
// draw nodes
|
||||
d3.select("#graph-svg").on("click", () => d3.selectAll(".highlight").classed("highlight", false));
|
||||
const callCount = g.nodes().filter(n => g.node(n).label.startsWith("CALL\n")).length;
|
||||
const nodes = d3.select("#nodes").selectAll("g").data(g.nodes().map(id => g.node(id)), d => d).join("g").attr("class", d => d.className ?? "node")
|
||||
.attr("transform", d => `translate(${d.x},${d.y})`).classed("clickable", d => d.ref != null).on("click", (e,d) => {
|
||||
if (d.ref != null) return switchCtx(d.ref);
|
||||
.attr("transform", d => `translate(${d.x},${d.y})`).on("click", (e,d) => {
|
||||
if (d.label.startsWith("CALL")) {
|
||||
if (state.callSrcMask.has(d.id)) state.callSrcMask.delete(d.id); else state.callSrcMask.add(d.id);
|
||||
if (state.callSrcMask.size >= callCount) { showCallSrc.toggle.checked = !showCallSrc.toggle.checked; state.callSrcMask.clear(); }
|
||||
return setState({});
|
||||
}
|
||||
const parents = g.predecessors(d.id);
|
||||
const children = g.successors(d.id);
|
||||
if (parents == null && children == null) return;
|
||||
@@ -105,6 +110,9 @@ const drawGraph = (data) => {
|
||||
});
|
||||
addTags(nodes.selectAll("g.tag").data(d => d.tag != null ? [d] : []).join("g").attr("class", "tag")
|
||||
.attr("transform", d => `translate(${-d.width/2+8}, ${-d.height/2+8})`).datum(e => e.tag));
|
||||
addTags(nodes.selectAll("g.type").data(d => d.label.startsWith("CALL\n") ? [d] : []).join("g")
|
||||
.attr("class", d => `tag ${d.collapsed ? 'collapsed' : 'expanded'}`)
|
||||
.attr("transform", d => `translate(${-d.width/2}, ${0})`).datum(d => d.collapsed ? "+" : "−"), 0.25);
|
||||
// draw edges
|
||||
const line = d3.line().x(d => d.x).y(d => d.y).curve(d3.curveBasis), edges = g.edges();
|
||||
d3.select("#edges").selectAll("path.edgePath").data(edges).join("path").attr("class", "edgePath").attr("d", (e) => {
|
||||
@@ -707,7 +715,7 @@ const evtSources = [];
|
||||
// rewrite: a single UOp transformation
|
||||
// step: collection of rewrites
|
||||
// context: collection of steps
|
||||
const state = {currentCtx:-1, currentStep:0, currentRewrite:0, expandSteps:false};
|
||||
const state = {currentCtx:-1, currentStep:0, currentRewrite:0, expandSteps:false, callSrcMask:new Set()};
|
||||
function setState(ns) {
|
||||
saveToHistory(state);
|
||||
const { ctx:prevCtx, step:prevStep } = select(state.currentCtx, state.currentStep);
|
||||
@@ -755,7 +763,7 @@ const createToggle = (id, text) => {
|
||||
return { toggle, label };
|
||||
}
|
||||
const showIndexing = createToggle("show-indexing", "Show indexing (r)");
|
||||
const showCallSrc = createToggle("show-call-src", "Show CALL src (c)");
|
||||
const showCallSrc = createToggle("show-call-src", "Show all CALL src (c)"); showCallSrc.toggle.checked = false;
|
||||
const showSink = createToggle("show-sink", "Show SINK (s)");
|
||||
showSink.toggle.checked = false;
|
||||
const showGraph = createToggle("show-graph", "Show graph (g)");
|
||||
@@ -907,10 +915,10 @@ async function main() {
|
||||
// ** center graph
|
||||
const data = ret[currentRewrite];
|
||||
const render = (opts) => renderDag({ data, opts }, { recenter:currentRewrite === 0 });
|
||||
const getOpts = () => ({ showIndexing:showIndexing.toggle.checked, showCallSrc:showCallSrc.toggle.checked, showSink:showSink.toggle.checked });
|
||||
const getOpts = () => ({ showIndexing:showIndexing.toggle.checked, showCallSrc:showCallSrc.toggle.checked, showSink:showSink.toggle.checked, callSrcMask:state.callSrcMask });
|
||||
render(getOpts());
|
||||
showIndexing.toggle.onchange = () => render(getOpts());
|
||||
showCallSrc.toggle.onchange = () => render(getOpts());
|
||||
showCallSrc.toggle.onchange = () => { state.callSrcMask.clear(); render(getOpts()); }
|
||||
showSink.toggle.onchange = () => render(getOpts());
|
||||
// ** right sidebar metadata
|
||||
metadata.innerHTML = "";
|
||||
@@ -942,7 +950,7 @@ async function main() {
|
||||
metadata.appendChild(codeBlock(upat[1], "python", { loc:upat[0], wrap:true }));
|
||||
const diffCode = metadata.appendChild(document.createElement("pre")).appendChild(document.createElement("code"));
|
||||
for (const line of diff) {
|
||||
diffCode.appendChild(colored([{st:line, color:line.startsWith("+") ? "#3aa56d" : line.startsWith("-") ? "#d14b4b" : "#f0f0f5"}]));
|
||||
diffCode.appendChild(colored([{st:line, color:line.startsWith("+") ? "#3aa56d" : line.startsWith("−") ? "#d14b4b" : "#f0f0f5"}]));
|
||||
diffCode.appendChild(document.createElement("br"));
|
||||
}
|
||||
diffCode.className = "wrap";
|
||||
|
||||
@@ -73,12 +73,13 @@ const layoutUOp = (g, { graph, change }, opts) => {
|
||||
if (node.label.includes("dtypes.index")) g.removeNode(n);
|
||||
}
|
||||
}
|
||||
if (!opts.showCallSrc) {
|
||||
if (!opts.showCallSrc || opts.callSrcMask.size > 0) {
|
||||
// remove edges from src[0] to CALL nodes, track affected nodes
|
||||
const disconnected = new Set();
|
||||
for (const n of g.nodes()) {
|
||||
const node = g.node(n);
|
||||
if (node.label.startsWith("CALL\n")) {
|
||||
if (node.label.startsWith("CALL\n") && (opts.showCallSrc ? opts.callSrcMask.has(n) : !opts.callSrcMask.has(n))) {
|
||||
node.collapsed = true;
|
||||
for (const pred of (g.predecessors(n) || [])) {
|
||||
const edge = g.edge(pred, n);
|
||||
if (edge?.label?.text === 0) {
|
||||
|
||||
Reference in New Issue
Block a user