Edward J. Schwartz
Add PTX and CUBIN file downloads
47b782d
Raw
History Blame Contribute Delete
5.79 kB
import glob
import os
import shutil
import subprocess
import sys
import tempfile
import gradio as gr
ARCHITECTURES = ["sm_70", "sm_75", "sm_80", "sm_86", "sm_89", "sm_90"]
DEFAULT_MODEL = """\
import torch
class Model(torch.nn.Module):
def forward(self, x, y):
return torch.relu(x + y)
model = Model()
inputs = (torch.randn(4, 4), torch.randn(4, 4))
torch.onnx.export(model, inputs, 'model.onnx', opset_version=17)
"""
def _run(cmd: list[str], label: str, timeout: int) -> tuple[str, bool]:
try:
r = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
if r.returncode != 0:
return f"{label} failed:\n\n{r.stderr.strip()}", False
return r.stdout, True
except subprocess.TimeoutExpired:
return f"{label} timed out ({timeout}s).", False
def compile_pipeline(code: str, arch: str) -> tuple[str, str, str, str, str | None, str | None]:
if not code.strip():
return "Error: no code provided.", "", "", "", None, None
try:
with tempfile.TemporaryDirectory() as tmpdir:
src = os.path.join(tmpdir, "model_def.py")
onnx_path = os.path.join(tmpdir, "model.onnx")
mlir_path = os.path.join(tmpdir, "model.mlir")
vmfb_path = os.path.join(tmpdir, "model.vmfb")
exec_dir = os.path.join(tmpdir, "exec")
cubin_path = os.path.join(tmpdir, "kernel.cubin")
os.makedirs(exec_dir)
with open(src, "w") as f:
f.write(code)
py_cmd = [sys.executable, src]
import_cmd = ["iree-import-onnx", onnx_path, "-o", mlir_path]
compile_cmd = [
"iree-compile", mlir_path,
"--iree-hal-target-backends=cuda",
f"--iree-cuda-target={arch}",
f"--iree-hal-dump-executable-files-to={exec_dir}",
"-o", vmfb_path,
]
cmds = "\n".join(" ".join(c) for c in [py_cmd, import_cmd, compile_cmd])
# PyTorch → ONNX
r = subprocess.run(py_cmd, capture_output=True, text=True, timeout=60, cwd=tmpdir)
if r.returncode != 0:
err = f"PyTorch export failed:\n\n{r.stderr.strip()}"
return cmds, err, err, err, None, None
# ONNX → MLIR
out, ok = _run(import_cmd, "iree-import-onnx", 60)
if not ok:
return cmds, out, out, out, None, None
mlir_text = open(mlir_path).read() if os.path.exists(mlir_path) else "(no MLIR output)"
# MLIR → VMFB, PTX dumped to exec_dir
out, ok = _run(compile_cmd, "iree-compile", 120)
if not ok:
return cmds, mlir_text, out, out, None, None
ptx_files = sorted(glob.glob(os.path.join(exec_dir, "**", "*.ptx"), recursive=True))
if not ptx_files:
return cmds, mlir_text, "No PTX files produced.", "No PTX to disassemble.", None, None
ptx_text = "\n\n".join(open(p).read() for p in ptx_files)
# PTX → CUBIN → SASS (first PTX file)
ptxas_cmd = ["ptxas", f"--gpu-name={arch}", ptx_files[0], "-o", cubin_path]
cuobjdump_cmd = ["cuobjdump", "--dump-sass", cubin_path]
cmds += "\n" + " ".join(ptxas_cmd) + "\n" + " ".join(cuobjdump_cmd)
_, ok = _run(ptxas_cmd, "ptxas", 30)
sass_text = _run(cuobjdump_cmd, "cuobjdump", 30)[0] if ok else "ptxas failed; SASS unavailable."
ptx_tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".ptx")
ptx_tmp.write(ptx_text.encode())
ptx_tmp.close()
cubin_tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".cubin")
cubin_tmp.close()
if ok and os.path.exists(cubin_path):
shutil.copy(cubin_path, cubin_tmp.name)
cubin_out = cubin_tmp.name
else:
cubin_out = None
return cmds, mlir_text, ptx_text, sass_text, ptx_tmp.name, cubin_out
except FileNotFoundError as e:
return "", "", f"Tool not found: {e}\n\nEnsure iree-compiler is installed.", "", None, None
except Exception as e:
return "", "", f"Unexpected error: {e}", "", None, None
with gr.Blocks(title="PyTorch → SASS Explorer") as demo:
gr.Markdown(
"# PyTorch → SASS Explorer\n"
"Write a PyTorch model that exports to `model.onnx`, pick a GPU architecture, "
"and trace the full compilation pipeline: PyTorch → ONNX → IREE MLIR → PTX → SASS."
)
with gr.Row():
with gr.Column(scale=2):
code_input = gr.Code(
label="PyTorch Model", language="python",
value=DEFAULT_MODEL, lines=20,
)
with gr.Column(scale=1):
arch = gr.Dropdown(label="GPU Architecture", choices=ARCHITECTURES, value="sm_80")
btn = gr.Button("Compile", variant="primary")
cmds_out = gr.Code(label="Commands", language="shell", lines=4, interactive=False)
mlir_out = gr.Code(label="MLIR", language=None, lines=10, max_lines=10, interactive=False)
with gr.Row():
ptx_out = gr.Code(label="PTX", language=None, lines=10, max_lines=10, interactive=False)
sass_out = gr.Code(label="SASS", language=None, lines=10, max_lines=10, interactive=False)
with gr.Row():
ptx_file = gr.File(label="Download PTX", interactive=False)
cubin_file = gr.File(label="Download CUBIN", interactive=False)
btn.click(compile_pipeline, [code_input, arch], [cmds_out, mlir_out, ptx_out, sass_out, ptx_file, cubin_file])
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)