From 7b39af444bfbd768cb0deadb1505b8247ea0470a Mon Sep 17 00:00:00 2001 From: Pham D Hung Date: Tue, 15 Sep 2026 19:42:15 -0400 Subject: [PATCH 01/15] [REFACTOR] Rename Triton-Viz to TileLens --- .github/workflows/frontend.yml | 4 +- .github/workflows/python-app.yml | 22 ++--- .gitignore | 2 +- AGENTS.md | 4 +- CONTRIBUTING.md | 12 +-- README.md | 70 ++++++------- benchmarks/bench_sanitizer.py | 48 ++++----- docs/index.html | 90 ++++++++--------- examples/multithread.py | 10 +- examples/nki/matmul.py | 10 +- examples/nki/rmsnorm.py | 14 +-- examples/nki/rope.py | 16 ++- examples/nki/softmax.py | 16 ++- examples/nki_beta2/add.py | 12 +-- examples/nki_beta2/matmul.py | 12 +-- examples/nki_beta2/mlp.py | 12 +-- examples/nki_beta2/rmsnorm.py | 12 +-- examples/nki_beta2/rope.py | 12 +-- examples/nki_beta2/softmax.py | 12 +-- examples/nki_beta2/tiled_attention.py | 12 +-- examples/profiler/load_store.py | 6 +- examples/sanitizer/gemm.py | 4 +- examples/sanitizer/gemm_oob.py | 4 +- examples/sanitizer/gluon_tma_oob.py | 6 +- examples/sanitizer/oob_tensor_view.py | 6 +- examples/visualizer/3dims.py | 8 +- examples/visualizer/9dims_copy.py | 8 +- examples/visualizer/indirect_load.py | 6 +- examples/visualizer/matmul.py | 8 +- frontend/GLOSSARY.md | 2 +- frontend/components/op_workspace.ts | 22 ++--- frontend/components/tensor_view.ts | 6 +- frontend/core/api.ts | 2 +- frontend/core/logger.ts | 2 +- frontend/core/visualization.ts | 10 +- frontend/templates/index.html | 2 +- frontend/types/globals.d.ts | 14 +-- frontend/utils/dimension_utils.ts | 4 +- package-lock.json | 4 +- package.json | 4 +- pyproject.toml | 14 +-- setup.py | 10 +- tests/conftest.py | 2 +- .../end_to_end/loop_site_cross_file_kernel.py | 6 +- .../kernel_with_trace_decorator.py.template | 4 +- .../sitecustomize_fake_trace.py.template | 4 +- .../sitecustomize_spy_trace.py.template | 2 +- tests/end_to_end/test_core.py | 56 +++++------ tests/end_to_end/test_gluon.py | 30 +++--- tests/end_to_end/test_profiler.py | 16 +-- tests/end_to_end/test_race_detector.py | 26 ++--- tests/end_to_end/test_sanitizer.py | 98 +++++++++---------- tests/end_to_end/test_tracer.py | 26 ++--- tests/end_to_end/test_triton_kernels.py | 30 +++--- tests/end_to_end/test_wrapper.py | 26 ++--- tests/frontend/api.test.mjs | 2 +- tests/frontend/nki.test.mjs | 4 +- tests/frontend/registry.test.mjs | 2 +- tests/frontend/state.test.mjs | 2 +- tests/frontend/transfer_build.test.mjs | 8 +- tests/nki/test_nki.py | 6 +- tests/nki/test_nki_beta2.py | 32 +++--- tests/nki/test_nki_tracer.py | 42 ++++---- tests/unit/test_adapters.py | 26 ++--- tests/unit/test_client_manager.py | 6 +- tests/unit/test_draw.py | 4 +- tests/unit/test_dtypes.py | 2 +- tests/unit/test_highlight_descriptor.py | 4 +- tests/unit/test_masked_load.py | 2 +- tests/unit/test_multithreading.py | 38 +++---- tests/unit/test_nki_transform.py | 2 +- tests/unit/test_patch_scope.py | 8 +- tests/unit/test_profiler.py | 6 +- tests/unit/test_race_detector.py | 16 +-- tests/unit/test_sanitizer.py | 20 ++-- tests/unit/test_symbolic_client.py | 14 +-- tests/unit/test_trace_io.py | 59 ++++++++--- tests/unit/test_tracer.py | 4 +- tests/unit/test_utils.py | 18 ++-- tests/unit/test_wrapper.py | 24 ++--- {triton_viz => tilelens}/__init__.py | 0 tilelens/clients/__init__.py | 31 ++++++ .../clients/profiler/__init__.py | 0 .../clients/profiler/data.py | 0 .../clients/profiler/profiler.py | 0 .../clients/race_detector/__init__.py | 0 .../clients/race_detector/data.py | 0 .../clients/race_detector/hb_solver.py | 0 .../clients/race_detector/race_detector.py | 0 .../clients/sanitizer/__init__.py | 0 .../clients/sanitizer/data.py | 0 .../clients/sanitizer/range_summary.py | 0 .../clients/sanitizer/report.py | 0 .../clients/sanitizer/sanitizer.py | 0 .../clients/symbolic_engine.py | 0 .../clients/tracer/tracer.py | 2 +- {triton_viz => tilelens}/clients/utils.py | 0 {triton_viz => tilelens}/core/__init__.py | 0 {triton_viz => tilelens}/core/callbacks.py | 0 {triton_viz => tilelens}/core/client.py | 0 {triton_viz => tilelens}/core/config.py | 8 +- {triton_viz => tilelens}/core/data.py | 2 +- .../core/frontend/__init__.py | 0 .../core/frontend/base.py | 10 +- .../core/frontend/gluon.py | 2 +- {triton_viz => tilelens}/core/frontend/nki.py | 6 +- .../core/frontend/nki_beta2.py | 6 +- .../core/frontend/nki_transform.py | 0 .../core/frontend/triton.py | 12 +-- .../core/masked_load_store.py | 0 {triton_viz => tilelens}/core/patch.py | 0 tilelens/core/simulation/__init__.py | 1 + .../core/simulation/gluon.py | 4 +- .../core/simulation/nki.py | 6 +- .../core/simulation/nki_beta2.py | 4 +- .../core/symbolic_metadata.py | 2 +- {triton_viz => tilelens}/core/trace.py | 4 +- {triton_viz => tilelens}/core/trace_io.py | 19 ++-- .../static/components/histogram.js | 0 .../static/components/infoPopup.js | 0 .../static/components/op_workspace.js | 22 ++--- .../static/components/sbuf_panel.js | 0 .../static/components/tensor_view.js | 6 +- {triton_viz => tilelens}/static/core/api.js | 2 +- .../static/core/logger.js | 2 +- {triton_viz => tilelens}/static/core/state.js | 0 .../static/core/visualization.js | 10 +- {triton_viz => tilelens}/static/main.js | 0 .../static/ops/defaults.js | 0 {triton_viz => tilelens}/static/ops/load.js | 0 {triton_viz => tilelens}/static/ops/matmul.js | 0 {triton_viz => tilelens}/static/ops/nki.js | 0 .../static/ops/registry.js | 0 {triton_viz => tilelens}/static/ops/store.js | 0 .../static/ops/transfer.js | 0 .../static/types/types.js | 0 .../static/utils/colormap.js | 0 .../static/utils/dimension_utils.js | 4 +- .../static/utils/dispose.js | 0 .../static/utils/three_utils.js | 0 .../static/utils/ui_helpers.js | 0 .../static/visualizer.css | 0 {triton_viz => tilelens}/templates/index.html | 2 +- {triton_viz => tilelens}/utils/__init__.py | 0 {triton_viz => tilelens}/utils/dtypes.py | 0 .../utils/traceback_utils.py | 10 +- .../visualizer/__init__.py | 0 .../visualizer/analysis.py | 2 +- {triton_viz => tilelens}/visualizer/draw.py | 4 +- .../visualizer/interface.py | 4 +- .../visualizer/tooltip.py | 0 {triton_viz => tilelens}/visualizer_cli.py | 8 +- {triton_viz => tilelens}/wrapper.py | 12 +-- triton_viz/clients/__init__.py | 31 ------ triton_viz/core/simulation/__init__.py | 1 - tsconfig.json | 2 +- 156 files changed, 751 insertions(+), 721 deletions(-) rename {triton_viz => tilelens}/__init__.py (100%) create mode 100644 tilelens/clients/__init__.py rename {triton_viz => tilelens}/clients/profiler/__init__.py (100%) rename {triton_viz => tilelens}/clients/profiler/data.py (100%) rename {triton_viz => tilelens}/clients/profiler/profiler.py (100%) rename {triton_viz => tilelens}/clients/race_detector/__init__.py (100%) rename {triton_viz => tilelens}/clients/race_detector/data.py (100%) rename {triton_viz => tilelens}/clients/race_detector/hb_solver.py (100%) rename {triton_viz => tilelens}/clients/race_detector/race_detector.py (100%) rename {triton_viz => tilelens}/clients/sanitizer/__init__.py (100%) rename {triton_viz => tilelens}/clients/sanitizer/data.py (100%) rename {triton_viz => tilelens}/clients/sanitizer/range_summary.py (100%) rename {triton_viz => tilelens}/clients/sanitizer/report.py (100%) rename {triton_viz => tilelens}/clients/sanitizer/sanitizer.py (100%) rename {triton_viz => tilelens}/clients/symbolic_engine.py (100%) rename {triton_viz => tilelens}/clients/tracer/tracer.py (99%) rename {triton_viz => tilelens}/clients/utils.py (100%) rename {triton_viz => tilelens}/core/__init__.py (100%) rename {triton_viz => tilelens}/core/callbacks.py (100%) rename {triton_viz => tilelens}/core/client.py (100%) rename {triton_viz => tilelens}/core/config.py (92%) rename {triton_viz => tilelens}/core/data.py (98%) rename {triton_viz => tilelens}/core/frontend/__init__.py (100%) rename {triton_viz => tilelens}/core/frontend/base.py (95%) rename {triton_viz => tilelens}/core/frontend/gluon.py (99%) rename {triton_viz => tilelens}/core/frontend/nki.py (93%) rename {triton_viz => tilelens}/core/frontend/nki_beta2.py (90%) rename {triton_viz => tilelens}/core/frontend/nki_transform.py (100%) rename {triton_viz => tilelens}/core/frontend/triton.py (99%) rename {triton_viz => tilelens}/core/masked_load_store.py (100%) rename {triton_viz => tilelens}/core/patch.py (100%) create mode 100644 tilelens/core/simulation/__init__.py rename {triton_viz => tilelens}/core/simulation/gluon.py (99%) rename {triton_viz => tilelens}/core/simulation/nki.py (99%) rename {triton_viz => tilelens}/core/simulation/nki_beta2.py (99%) rename {triton_viz => tilelens}/core/symbolic_metadata.py (99%) rename {triton_viz => tilelens}/core/trace.py (99%) rename {triton_viz => tilelens}/core/trace_io.py (93%) rename {triton_viz => tilelens}/static/components/histogram.js (100%) rename {triton_viz => tilelens}/static/components/infoPopup.js (100%) rename {triton_viz => tilelens}/static/components/op_workspace.js (96%) rename {triton_viz => tilelens}/static/components/sbuf_panel.js (100%) rename {triton_viz => tilelens}/static/components/tensor_view.js (99%) rename {triton_viz => tilelens}/static/core/api.js (97%) rename {triton_viz => tilelens}/static/core/logger.js (84%) rename {triton_viz => tilelens}/static/core/state.js (100%) rename {triton_viz => tilelens}/static/core/visualization.js (98%) rename {triton_viz => tilelens}/static/main.js (100%) rename {triton_viz => tilelens}/static/ops/defaults.js (100%) rename {triton_viz => tilelens}/static/ops/load.js (100%) rename {triton_viz => tilelens}/static/ops/matmul.js (100%) rename {triton_viz => tilelens}/static/ops/nki.js (100%) rename {triton_viz => tilelens}/static/ops/registry.js (100%) rename {triton_viz => tilelens}/static/ops/store.js (100%) rename {triton_viz => tilelens}/static/ops/transfer.js (100%) rename {triton_viz => tilelens}/static/types/types.js (100%) rename {triton_viz => tilelens}/static/utils/colormap.js (100%) rename {triton_viz => tilelens}/static/utils/dimension_utils.js (98%) rename {triton_viz => tilelens}/static/utils/dispose.js (100%) rename {triton_viz => tilelens}/static/utils/three_utils.js (100%) rename {triton_viz => tilelens}/static/utils/ui_helpers.js (100%) rename {triton_viz => tilelens}/static/visualizer.css (100%) rename {triton_viz => tilelens}/templates/index.html (97%) rename {triton_viz => tilelens}/utils/__init__.py (100%) rename {triton_viz => tilelens}/utils/dtypes.py (100%) rename {triton_viz => tilelens}/utils/traceback_utils.py (97%) rename {triton_viz => tilelens}/visualizer/__init__.py (100%) rename {triton_viz => tilelens}/visualizer/analysis.py (96%) rename {triton_viz => tilelens}/visualizer/draw.py (99%) rename {triton_viz => tilelens}/visualizer/interface.py (99%) rename {triton_viz => tilelens}/visualizer/tooltip.py (100%) rename {triton_viz => tilelens}/visualizer_cli.py (85%) rename {triton_viz => tilelens}/wrapper.py (93%) delete mode 100644 triton_viz/clients/__init__.py delete mode 100644 triton_viz/core/simulation/__init__.py diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index 3da8e6242..ae0a1c276 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/checkout@v3 with: - path: 'triton_viz' + path: 'tilelens' - name: Set up Node uses: actions/setup-node@v4 @@ -30,6 +30,6 @@ jobs: - name: Run frontend tests run: | - cd triton_viz + cd tilelens npm ci npm run test:frontend diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 88d8482cd..e337ee744 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -25,7 +25,7 @@ jobs: steps: - uses: actions/checkout@v3 with: - path: 'triton_viz' + path: 'tilelens' - name: Set up Python 3.12 uses: actions/setup-python@v3 @@ -39,46 +39,46 @@ jobs: - name: Lint with pre-commit run: | - cd triton_viz + cd tilelens pip install pre-commit pre-commit run --all-files - name: Install Dependencies run: | - cd triton_viz + cd tilelens uv sync --extra test - name: Upgrade Triton to latest from main run: | - cd triton_viz + cd tilelens uv pip install --pre -U triton uv pip install "git+https://github.com/triton-lang/triton.git#subdirectory=python/triton_kernels" - name: Run frontend tests run: | - cd triton_viz + cd tilelens npm install npm run test:frontend - name: Test with pytest run: | - cd triton_viz + cd tilelens uv run pytest tests -n auto --ignore=tests/end_to_end/test_triton_kernels.py - - name: Install Triton-Viz with NKI extras + - name: Install TileLens with NKI extras run: | - cd triton_viz + cd tilelens uv sync --extra test --extra nki - name: Upgrade Triton to latest from main (NKI) run: | - cd triton_viz + cd tilelens uv pip install --pre -U triton uv pip install "git+https://github.com/triton-lang/triton.git#subdirectory=python/triton_kernels" - name: Run full (Triton + NKI) pytest suite run: | - cd triton_viz + cd tilelens uv run pytest tests -m "" -n auto --ignore=tests/end_to_end/test_triton_kernels.py test-pip-install: @@ -96,4 +96,4 @@ jobs: run: pip install -e ".[test]" - name: Verify installation - run: python -c "import triton_viz; print(triton_viz.__version__)" + run: python -c "import tilelens; print(tilelens.__version__)" diff --git a/.gitignore b/.gitignore index 3688aff7c..7400c3382 100644 --- a/.gitignore +++ b/.gitignore @@ -169,6 +169,6 @@ uv.lock benchmarks/*.json # Auto-generated version file -triton_viz/version.py +tilelens/version.py .subagents/ subagent*.txt diff --git a/AGENTS.md b/AGENTS.md index c6af6c4ab..dc61bac8f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ ## Project Structure & Module Organization -Triton-Viz is a Python package with a TypeScript web UI. Core code lives in `triton_viz/`: `core/` handles tracing and client lifecycle, `core/frontend/` owns DSL operation adapters, runtime patching, and frontend-local AST rewrites, `core/simulation/` contains NKI simulation runtimes, `clients/` contains visualizer/profiler/sanitizer logic, and `visualizer/` covers visualizer APIs. Web UI source is in `frontend/`; built assets are copied into `triton_viz/static/` and `triton_viz/templates/`. Tests live in `tests/unit/`, `tests/end_to_end/`, `tests/frontend/`, and `tests/nki/`. Examples are in `examples/`; site docs are in `docs/`. +TileLens is a Python package with a TypeScript web UI. Core code lives in `tilelens/`: `core/` handles tracing and client lifecycle, `core/frontend/` owns DSL operation adapters, runtime patching, and frontend-local AST rewrites, `core/simulation/` contains NKI simulation runtimes, `clients/` contains visualizer/profiler/sanitizer logic, and `visualizer/` covers visualizer APIs. Web UI source is in `frontend/`; built assets are copied into `tilelens/static/` and `tilelens/templates/`. Tests live in `tests/unit/`, `tests/end_to_end/`, `tests/frontend/`, and `tests/nki/`. Examples are in `examples/`; site docs are in `docs/`. ## Build, Test, and Development Commands @@ -28,4 +28,4 @@ Recent commits use concise imperative summaries, often with prefixes such as `[F ## Security & Configuration Tips -Do not commit local traces, credentials, or generated debug artifacts. Runtime behavior is controlled by environment variables such as `TRITON_VIZ_VERBOSE`, `TRITON_VIZ_PORT`, `ENABLE_SANITIZER`, `ENABLE_PROFILER`, and `SANITIZER_ENABLE_FAKE_TENSOR`; document any new variables in `README.md`. +Do not commit local traces, credentials, or generated debug artifacts. Runtime behavior is controlled by environment variables such as `TILELENS_VERBOSE`, `TILELENS_PORT`, `ENABLE_SANITIZER`, `ENABLE_PROFILER`, and `SANITIZER_ENABLE_FAKE_TENSOR`; document any new variables in `README.md`. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7f1794039..74a6aad5c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,11 +1,11 @@ -# Contributing to Triton-Viz +# Contributing to TileLens ## Quick Start ```bash # Clone repo -git clone https://github.com/Deep-Learning-Profiling-Tools/triton-viz.git -cd triton-viz +git clone https://github.com/Deep-Learning-Profiling-Tools/tilelens.git +cd tilelens # Setup dev environment and install dependencies uv sync --extra test # append "--extra nki" if developing NKI functionality @@ -23,9 +23,9 @@ npm run test:frontend # test the web UI (if working on the visualizer ``` frontend/ # TypeScript web UI source code -examples/ # Entry points for new users to try out triton-viz functionality -docs/ # triton-viz website -triton_viz/ +examples/ # Entry points for new users to try out tilelens functionality +docs/ # tilelens website +tilelens/ core/frontend/ # DSL operation adapters and runtime patching core/simulation/ # NKI simulation runtimes clients/ # Visualizer, profiler, and sanitizer clients diff --git a/README.md b/README.md index 1cbb7ed0d..4cabe978b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# Triton-Viz: A Visualization Toolkit for programming with Triton +# TileLens: A Visualization Toolkit for programming with Triton
@@ -7,9 +7,9 @@

-Welcome to Triton-Viz, a visualization and profiling toolkit designed for deep learning applications. Built with the intention of making kernel programming in tile-based DSLs like Triton more intuitive. +Welcome to TileLens, a visualization and profiling toolkit designed for deep learning applications. Built with the intention of making kernel programming in tile-based DSLs like Triton more intuitive. -Visit our [site](https://deep-learning-profiling-tools.github.io/triton-viz/) to see our tool in action! +Visit our [site](https://deep-learning-profiling-tools.github.io/tilelens/) to see our tool in action!
@@ -20,7 +20,7 @@ Visit our [site](https://deep-learning-profiling-tools.github.io/triton-viz/) to Getting Started
  • @@ -34,7 +34,7 @@ Visit our [site](https://deep-learning-profiling-tools.github.io/triton-viz/) to ## About -Triton-Viz helps developers inspect Triton kernels with visualization, profiling, and memory-safety analysis tools. It can run many examples through Triton's interpreter, so GPU access is not required for basic debugging workflows. +TileLens helps developers inspect Triton kernels with visualization, profiling, and memory-safety analysis tools. It can run many examples through Triton's interpreter, so GPU access is not required for basic debugging workflows. ## Getting Started @@ -43,11 +43,11 @@ Triton-Viz helps developers inspect Triton kernels with visualization, profiling - Python >= 3.10 -### Installation of Triton-Viz +### Installation of TileLens -> **Windows Note:** Triton-viz depends on Triton, which can only be installed on Windows Subsystem for Linux (WSL). Once installed, follow below instructions in WSL. +> **Windows Note:** TileLens depends on Triton, which can only be installed on Windows Subsystem for Linux (WSL). Once installed, follow below instructions in WSL. -Most users can install directly from PyPI: +TileLens is distributed on PyPI under the existing name `triton-viz`: ```sh pip install triton-viz @@ -56,14 +56,14 @@ pip install triton-viz If you want to run examples from this repo, contribute, or build the web UI, install from source instead: ```sh -git clone https://github.com/Deep-Learning-Profiling-Tools/triton-viz.git -cd triton-viz +git clone https://github.com/Deep-Learning-Profiling-Tools/tilelens.git +cd tilelens uv sync # or "uv sync --extra test" if you're running tests ``` ### Web UI Build -The PyPI package ships with prebuilt web UI assets in `triton_viz/static`, so +The PyPI package ships with prebuilt web UI assets in `tilelens/static`, so you do not need npm to run the visualizer. If you want to modify the web UI, rebuild the TS sources: @@ -77,7 +77,7 @@ npm run build:frontend For PyPI installs, install with the `nki` extra and AWS Neuron repository: ```sh -pip install triton-viz[nki] --extra-index-url https://pip.repos.neuron.amazonaws.com +pip install "triton-viz[nki]" --extra-index-url https://pip.repos.neuron.amazonaws.com ``` For source installs: @@ -93,7 +93,7 @@ uv sync --extra test # tests but no NKI support ``` ### Testing -* To run core Triton-viz tests, run `pytest tests/`. +* To run core TileLens tests, run `pytest tests/`. * (if NKI installed) To run NKI-specific tests, run `pytest tests/ -m nki`. * To run all tests (Triton + NKI), run `pytest tests/ -m ""`. * To run visualizer web UI tests, run `npm run test:frontend`. @@ -111,10 +111,10 @@ Use the decorator API when writing or modifying a Triton kernel: ```py import triton import triton.language as tl -import triton_viz +import tilelens -@triton_viz.trace("sanitizer") # also supports "tracer" and "profiler" +@tilelens.trace("sanitizer") # also supports "tracer" and "profiler" @triton.jit def kernel(x_ptr, out_ptr, BLOCK: tl.constexpr): offsets = tl.arange(0, BLOCK) @@ -124,7 +124,7 @@ def kernel(x_ptr, out_ptr, BLOCK: tl.constexpr): Use the CLI wrappers to run an existing Python script without editing it. These wrappers patch plain `@triton.jit` kernels, so use them with scripts that do not -already apply `@triton_viz.trace(...)`. +already apply `@tilelens.trace(...)`. ```sh triton-sanitizer examples/sanitizer/oob_cli.py @@ -135,10 +135,10 @@ triton-visualizer trace.tvz For visualizer workflows, save a trace and launch the UI from Python: ```py -import triton_viz +import tilelens -triton_viz.save("trace.tvz") -triton_viz.launch() +tilelens.save("trace.tvz") +tilelens.launch() ``` ## DSL Frontends @@ -147,13 +147,13 @@ Triton is the default DSL frontend. NKI support is optional and selected with the `frontend` argument: ```py -triton_viz.trace("tracer") # Triton -triton_viz.trace("tracer", frontend="nki") # NKI -triton_viz.trace("tracer", frontend="nki_beta2") # NKI Beta 2 +tilelens.trace("tracer") # Triton +tilelens.trace("tracer", frontend="nki") # NKI +tilelens.trace("tracer", frontend="nki_beta2") # NKI Beta 2 ``` -The runtime integration code lives under `triton_viz/core/frontend/`. NKI -simulation runtimes live under `triton_viz/core/simulation/`. +The runtime integration code lives under `tilelens/core/frontend/`. NKI +simulation runtimes live under `tilelens/core/simulation/`. ## Analysis Clients @@ -166,24 +166,26 @@ Analyze kernels across visualization, profiling, and sanitization with a single ### Save and load traces ```py -import triton_viz +import tilelens -triton_viz.save("trace.tvz") -triton_viz.load( +tilelens.save("trace.tvz") +tilelens.load( "trace.tvz" ) # automatically clears out existing records, use kwarg "append=True" to prevent this -triton_viz.launch() +tilelens.launch() ``` -CLI: `triton-visualizer trace.tvz`. The archive is a zip file containing `manifest.json` plus `tensors.npz`, and `triton_viz.load(...)` restores the normal trace state for existing consumers. +CLI: `triton-visualizer trace.tvz`. The archive is a zip file containing `manifest.json` plus `tensors.npz`, and `tilelens.load(...)` restores the normal trace state for existing consumers. + +Existing `.tvz` traces can still be loaded with `tilelens.load(...)`. ### Environment variables -Triton-Viz uses a small set of environment variables to configure runtime behavior. Unless noted, boolean flags are enabled only when set to `1`. +TileLens uses a small set of environment variables to configure runtime behavior. Unless noted, boolean flags are enabled only when set to `1`. -- `TRITON_VIZ_VERBOSE` (default: `0`): enable verbose logging and extra debug output. -- `TRITON_VIZ_NUM_SMS` (default: `1`): number of concurrent SMs to emulate for the CPU interpreter (min 1). -- `TRITON_VIZ_PORT` (default: `8000` with `share=True`, `5001` with `share=False`): port for the Flask server. +- `TILELENS_VERBOSE` (default: `0`): enable verbose logging and extra debug output. +- `TILELENS_NUM_SMS` (default: `1`): number of concurrent SMs to emulate for the CPU interpreter (min 1). +- `TILELENS_PORT` (default: `8000` with `share=True`, `5001` with `share=False`): port for the Flask server. - `ENABLE_SANITIZER` (default: `1`): enable the sanitizer pipeline that checks memory accesses. - `ENABLE_PROFILER` (default: `1`): enable the profiler pipeline that collects performance data. - `ENABLE_TIMING` (default: `0`): collect timing data during execution. @@ -199,7 +201,7 @@ If you're interested in fun puzzles to work with in Triton, do check out: [Trito ## License -Triton-Viz is licensed under the MIT License. See the [LICENSE](LICENSE) for details. +TileLens is licensed under the MIT License. See the [LICENSE](LICENSE) for details. ## Publication If you find this repo useful for your research, please cite our paper: diff --git a/benchmarks/bench_sanitizer.py b/benchmarks/bench_sanitizer.py index 874a32e92..056bc6bb6 100644 --- a/benchmarks/bench_sanitizer.py +++ b/benchmarks/bench_sanitizer.py @@ -35,8 +35,8 @@ import triton import triton.language as tl -import triton_viz -from triton_viz.clients.sanitizer.sanitizer import ( +import tilelens +from tilelens.clients.sanitizer.sanitizer import ( SymbolicSanitizer, _fn_symbolic_cache_set, ) @@ -77,7 +77,7 @@ def _timeout_handler(signum, frame): # --------------------------------------------------------------------------- -@triton_viz.trace(client=gemm_sanitizer) +@tilelens.trace(client=gemm_sanitizer) @triton.jit def gemm_kernel( A, @@ -107,7 +107,7 @@ def gemm_kernel( tl.store(C + C_off, accum) -@triton_viz.trace(client=gemm_oob_sanitizer) +@tilelens.trace(client=gemm_oob_sanitizer) @triton.jit def gemm_oob_kernel( A, @@ -137,7 +137,7 @@ def gemm_oob_kernel( tl.store(C + C_off, accum) -@triton_viz.trace(client=indirect_sanitizer) +@tilelens.trace(client=indirect_sanitizer) @triton.jit def indirect_load_kernel(idx_ptr, src_ptr, dst_ptr, BLOCK: tl.constexpr): pid = tl.program_id(0) @@ -147,7 +147,7 @@ def indirect_load_kernel(idx_ptr, src_ptr, dst_ptr, BLOCK: tl.constexpr): tl.store(dst_ptr + offs, vals) -@triton_viz.trace(client=nested_sanitizer) +@tilelens.trace(client=nested_sanitizer) @triton.jit def nested_loop_kernel(out_ptr, OUTER: tl.constexpr, INNER: tl.constexpr): for i in range(0, OUTER): @@ -156,7 +156,7 @@ def nested_loop_kernel(out_ptr, OUTER: tl.constexpr, INNER: tl.constexpr): tl.store(out_ptr + idx, idx) -@triton_viz.trace(client=block_ptr_sanitizer) +@tilelens.trace(client=block_ptr_sanitizer) @triton.jit def block_pointer_loop_advance_kernel(ptr, N: tl.constexpr, BLOCK: tl.constexpr): block_ptr = tl.make_block_ptr( @@ -182,7 +182,7 @@ def silu(x): return x * tl.sigmoid(x) -@triton_viz.trace(client=swiglu_fwd_sanitizer) +@tilelens.trace(client=swiglu_fwd_sanitizer) @triton.jit def swiglu_forward_kernel( a_ptr, b_ptr, c_ptr, stride, n_cols: tl.constexpr, BLOCK_SIZE: tl.constexpr @@ -203,7 +203,7 @@ def swiglu_forward_kernel( tl.store(c_ptr + col_offsets, c_row, mask=mask) -@triton_viz.trace(client=swiglu_bwd_sanitizer) +@tilelens.trace(client=swiglu_bwd_sanitizer) @triton.jit def swiglu_backward_kernel( dc_ptr, a_ptr, b_ptr, stride, n_cols: tl.constexpr, BLOCK_SIZE: tl.constexpr @@ -237,7 +237,7 @@ def swiglu_backward_kernel( # --------------------------------------------------------------------------- -@triton_viz.trace(client=cross_entropy_sanitizer) +@tilelens.trace(client=cross_entropy_sanitizer) @triton.jit def liger_cross_entropy_kernel( X_ptr, @@ -329,7 +329,7 @@ def liger_cross_entropy_kernel( tl.store(X_ptr + y, X_y) -@triton_viz.trace(client=jsd_sanitizer) +@tilelens.trace(client=jsd_sanitizer) @triton.jit def jsd_kernel( X_ptr, # input in logspace, X = log Q @@ -382,7 +382,7 @@ def jsd_kernel( tl.store(dX_ptr + offsets, dX, mask=mask) -@triton_viz.trace(client=element_mul_sanitizer) +@tilelens.trace(client=element_mul_sanitizer) @triton.jit def element_mul_kernel( X_ptr, @@ -408,7 +408,7 @@ def element_mul_kernel( # --------------------------------------------------------------------------- -@triton_viz.trace(client=flaggems_sanitizer) +@tilelens.trace(client=flaggems_sanitizer) @triton.jit def flaggems_ln_persistent_kernel( in_ptr, @@ -449,7 +449,7 @@ def flaggems_ln_persistent_kernel( tl.store(out_ptr + pid * N + n_offsets, out, mask=mask) -@triton_viz.trace(client=flaggems_sanitizer) +@tilelens.trace(client=flaggems_sanitizer) @triton.jit def flaggems_ln_multiline_kernel( in_ptr, @@ -497,7 +497,7 @@ def flaggems_ln_multiline_kernel( tl.store(out_ptr + m_offsets[:, None] * N + n_offsets, out, mask=mask) -@triton_viz.trace(client=flaggems_sanitizer) +@tilelens.trace(client=flaggems_sanitizer) @triton.jit def flaggems_ln_loop_kernel( in_ptr, @@ -580,7 +580,7 @@ def flaggems_ln_loop_kernel( tl.store(out_ptr + pid * N + n_offsets, out) -@triton_viz.trace(client=flaggems_sanitizer) +@tilelens.trace(client=flaggems_sanitizer) @triton.jit def flaggems_ln_backward_kernel( dY, @@ -647,7 +647,7 @@ def flaggems_ln_backward_kernel( tl.store(dX + cols, dx, mask=mask) -@triton_viz.trace(client=flaggems_sanitizer) +@tilelens.trace(client=flaggems_sanitizer) @triton.jit def flaggems_ln_wb_backward_kernel( dY, @@ -1409,33 +1409,33 @@ def _fljsd_run_all(templates): ( "triton_kernels._masked_compaction", "masked-compaction", - "test_triton_viz_sanitizer_masked_compaction", + "test_tilelens_sanitizer_masked_compaction", ), ( "triton_kernels._ragged_tensor_metadata_memset_compute", "ragged-metadata-make", - "test_triton_viz_sanitizer_make_ragged_tensor_metadata", + "test_tilelens_sanitizer_make_ragged_tensor_metadata", ), ( "triton_kernels._remap_ragged_tensor_metadata", "ragged-metadata-remap", - "test_triton_viz_sanitizer_remap_ragged_tensor_metadata", + "test_tilelens_sanitizer_remap_ragged_tensor_metadata", ), ( "triton_kernels._topk_forward", "topk-forward", - "test_triton_viz_sanitizer_topk_forward", + "test_tilelens_sanitizer_topk_forward", ), ( "triton_kernels._topk_backward", "topk-backward", - "test_triton_viz_sanitizer_topk_backward", + "test_tilelens_sanitizer_topk_backward", ), - ("triton_kernels._swiglu", "swiglu", "test_triton_viz_sanitizer_swiglu"), + ("triton_kernels._swiglu", "swiglu", "test_tilelens_sanitizer_swiglu"), ( "triton_kernels.upcast_mxfp4_tile", "mxfp4-tile-upcast", - "test_triton_viz_sanitizer_mxfp4_tile_upcast", + "test_tilelens_sanitizer_mxfp4_tile_upcast", ), ] diff --git a/docs/index.html b/docs/index.html index 2b7d4a3e9..102ca4a1f 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3,7 +3,7 @@ - Triton-Viz | Visualization Toolkit for Triton GPU Programming + TileLens | Visualization Toolkit for Triton GPU Programming @@ -559,8 +559,8 @@ @@ -587,8 +587,8 @@

    Analyze and debug your tile-based DSL kernels

    Install (NKI support)
    - pip install triton-viz[nki] --extra-index-url https://pip.repos.neuron.amazonaws.com -
    @@ -596,7 +596,7 @@

    Analyze and debug your tile-based DSL kernels

    Note: A browser with WebGL/OpenGL enabled is required (standard in modern browsers).
    - See README.md for development installs, web UI builds, DSL frontend selection, and full documentation. + See README.md for development installs, web UI builds, DSL frontend selection, and full documentation.

    @@ -637,10 +637,10 @@

    Analysis Clients

    import torch
     import triton
     import triton.language as tl
    -import triton_viz
    +import tilelens
     
     
    -@triton_viz.trace("tracer")
    +@tilelens.trace("tracer")
     @triton.jit
     def add_3d_slices_kernel(
         input_ptr1,
    @@ -689,7 +689,7 @@ 

    Analysis Clients

    BLOCK_SIZE_Y=BLOCK_SIZE_Y, BLOCK_SIZE_Z=BLOCK_SIZE_Z, ) - triton_viz.launch(share=False, port=5001) + tilelens.launch(share=False, port=5001)
    @@ -713,14 +713,14 @@

    Analysis Clients

    import torch
     import triton
     import triton.language as tl
    -import triton_viz
    +import tilelens
     
     
     BLOCK = 1024
     SHAPE = (2, 3, 4, 3, 4, 2, 4, 2, 3)
     
     
    -@triton_viz.trace("tracer")
    +@tilelens.trace("tracer")
     @triton.jit
     def copy_9d_kernel(x_ptr, y_ptr, n_elements, BLOCK: tl.constexpr):
         pid = tl.program_id(0)
    @@ -736,7 +736,7 @@ 

    Analysis Clients

    n_elements = x.numel() grid = (triton.cdiv(n_elements, BLOCK),) copy_9d_kernel[grid](x, y, n_elements, BLOCK=BLOCK) - triton_viz.launch(share=False, port=5001) + tilelens.launch(share=False, port=5001)
    @@ -760,10 +760,10 @@

    Analysis Clients

    import torch
     import triton
     import triton.language as tl
    -import triton_viz
    +import tilelens
     
     
    -@triton_viz.trace("tracer")
    +@tilelens.trace("tracer")
     @triton.jit
     def add_3d_slices_kernel(
         input_ptr1,
    @@ -812,7 +812,7 @@ 

    Analysis Clients

    BLOCK_SIZE_Y=BLOCK_SIZE_Y, BLOCK_SIZE_Z=BLOCK_SIZE_Z, ) - triton_viz.launch(share=False, port=5001) + tilelens.launch(share=False, port=5001)
    @@ -836,10 +836,10 @@

    Analysis Clients

    import torch
     import triton
     import triton.language as tl
    -import triton_viz
    +import tilelens
     
     
    -@triton_viz.trace("tracer")
    +@tilelens.trace("tracer")
     @triton.jit
     def matmul_kernel(
         a_ptr,
    @@ -888,7 +888,7 @@ 

    Analysis Clients

    BLOCK_N=BLOCK_N, BLOCK_K=BLOCK_K, ) - triton_viz.launch(share=False, port=5001) + tilelens.launch(share=False, port=5001)
    @@ -912,10 +912,10 @@

    Analysis Clients

    import torch
     import triton
     import triton.language as tl
    -import triton_viz
    +import tilelens
     
     
    -@triton_viz.trace("tracer")
    +@tilelens.trace("tracer")
     @triton.jit
     def matmul_kernel(
         a_ptr,
    @@ -964,7 +964,7 @@ 

    Analysis Clients

    BLOCK_N=BLOCK_N, BLOCK_K=BLOCK_K, ) - triton_viz.launch(share=False, port=5001) + tilelens.launch(share=False, port=5001)
    @@ -988,10 +988,10 @@

    Analysis Clients

    import torch
     import triton
     import triton.language as tl
    -import triton_viz
    +import tilelens
     
     
    -@triton_viz.trace("tracer")
    +@tilelens.trace("tracer")
     @triton.jit
     def matmul_kernel(
         a_ptr,
    @@ -1040,7 +1040,7 @@ 

    Analysis Clients

    BLOCK_N=BLOCK_N, BLOCK_K=BLOCK_K, ) - triton_viz.launch(share=False, port=5001) + tilelens.launch(share=False, port=5001)
    @@ -1066,10 +1066,10 @@

    Analysis Clients

    import torch
     import triton
     import triton.language as tl
    -import triton_viz
    +import tilelens
     
     
    -@triton_viz.trace("profiler")
    +@tilelens.trace("profiler")
     @triton.jit
     def simple_kernel(
         x_ptr,
    @@ -1164,10 +1164,10 @@ 

    Analysis Clients

    import torch
     import triton
     import triton.language as tl
    -import triton_viz
    +import tilelens
     
     
    -@triton_viz.trace("sanitizer")
    +@tilelens.trace("sanitizer")
     @triton.jit
     def gemm_kernel(
         A, B, C, M: tl.constexpr, N: tl.constexpr, K: tl.constexpr, TILE_SIZE: tl.constexpr
    @@ -1225,10 +1225,10 @@ 

    Analysis Clients

    import torch
     import triton
     import triton.language as tl
    -import triton_viz
    +import tilelens
     
     
    -@triton_viz.trace("sanitizer")
    +@tilelens.trace("sanitizer")
     @triton.jit
     def gemm_kernel(
         A, B, C, M: tl.constexpr, N: tl.constexpr, K: tl.constexpr, TILE_SIZE: tl.constexpr
    @@ -1274,7 +1274,7 @@ 

    Analysis Clients

    TERMINAL OUTPUT
    🚨 ILLEGAL MEMORY ACCESS DETECTED 🚨
     ━━━ Code Context ━━━
    -File: triton-viz/examples/sanitizer/gemm_oob.py
    +File: tilelens/examples/sanitizer/gemm_oob.py
     Function: gemm_kernel
     Line 25:
       22 │     for k_block in range(K // TILE_SIZE):
    @@ -1385,27 +1385,27 @@ 

    Analysis Clients

    Sponsored by

    -

    Special thanks to AMD for supporting Triton-Viz.

    +

    Special thanks to AMD for supporting TileLens.

    Ready to visualize your kernels?

    -

    Get started with Triton-Viz in minutes. No GPU required for development.

    +

    Get started with TileLens in minutes. No GPU required for development.

    @@ -1456,12 +1456,12 @@

    Ready to visualize your kernels?

    } return highlighted; } - function highlightTritonVizLines() { + function highlightTileLensLines() { const patterns = [ - 'import triton_viz', - 'from triton_viz', - '@triton_viz.trace', - 'triton_viz.launch', + 'import tilelens', + 'from tilelens', + '@tilelens.trace', + 'tilelens.launch', ]; document.querySelectorAll('pre code.language-python').forEach(code => { const lines = code.textContent.split('\n'); @@ -1478,7 +1478,7 @@

    Ready to visualize your kernels?

    code.innerHTML = updated.join('\n'); }); } - highlightTritonVizLines(); + highlightTileLensLines(); diff --git a/examples/multithread.py b/examples/multithread.py index 39c3223c3..d7349aaee 100644 --- a/examples/multithread.py +++ b/examples/multithread.py @@ -60,7 +60,7 @@ def main(): parser.add_argument( "--viz", action="store_true", - help="Enable triton-viz tracing (uses tracer client).", + help="Enable tilelens tracing (uses tracer client).", ) parser.add_argument( "--num-sms", @@ -73,16 +73,16 @@ def main(): trace_decorator = None if args.viz: - import triton_viz + import tilelens - triton_viz.config.num_sms = max(1, args.num_sms) - trace_decorator = triton_viz.trace("tracer") + tilelens.config.num_sms = max(1, args.num_sms) + trace_decorator = tilelens.trace("tracer") producer_consumer, racing_threads = make_kernels(trace_decorator) device = ( "cpu" if args.viz else "cuda" - ) # triton-viz only supports CPU, triton only supports CUDA (TRITON_INTERPRET=1 runs on CPU but hangs) + ) # tilelens only supports CPU, triton only supports CUDA (TRITON_INTERPRET=1 runs on CPU but hangs) # Use smaller workloads on CPU to keep interpreter runs snappy. pc_N = 16384 * 16 if device == "cuda" else 2048 diff --git a/examples/nki/matmul.py b/examples/nki/matmul.py index e0a7c94be..d3f702033 100644 --- a/examples/nki/matmul.py +++ b/examples/nki/matmul.py @@ -1,11 +1,11 @@ from neuronxcc import nki import neuronxcc.nki.language as nl -import triton_viz +import tilelens import numpy as np import math -TRITON_VIZ_ENABLED = True # True = enable visualizer, False = run compiler +TILELENS_ENABLED = True # True = enable visualizer, False = run compiler TRANSPOSED = False # True = run matmul_kernel, False = run matmul_kernel_lhsT @@ -137,12 +137,12 @@ def _run_demo(): result = np.empty((M, N), dtype=lhs_small.dtype) kernel_args = (lhs_small, rhs_small, result) - if TRITON_VIZ_ENABLED: + if TILELENS_ENABLED: print("Executing matmul_kernel with NKI interpreter...") - traced_kernel = triton_viz.trace("tracer", frontend="nki")(kernel) + traced_kernel = tilelens.trace("tracer", frontend="nki")(kernel) kernel_instance = traced_kernel[kernel_grid] kernel_instance(*kernel_args) - triton_viz.launch(share=False) + tilelens.launch(share=False) else: print("Executing NKI JIT-ed matmul kernel...") compiled_kernel = nki.jit(kernel, kernel_return=False) diff --git a/examples/nki/rmsnorm.py b/examples/nki/rmsnorm.py index 87c8603ca..d5f2bd87e 100644 --- a/examples/nki/rmsnorm.py +++ b/examples/nki/rmsnorm.py @@ -1,11 +1,11 @@ import neuronxcc.nki as nki import neuronxcc.nki.language as nl -from triton_viz.clients import Tracer -from triton_viz.core.trace import launches +from tilelens.clients import Tracer +from tilelens.core.trace import launches import math import numpy as np import torch -import triton_viz +import tilelens def nki_rmsnorm_kernel(a_tensor, g_tensor, result): @@ -77,7 +77,7 @@ def torch_rmsnorm_kernel(a_tensor, g_tensor): def _run_demo(): - triton_viz_enabled = True + tilelens_enabled = True kernel_grid = (1, 1, 1) b_dim, d_dim = 32, 32 a_tensor = torch.arange(b_dim * d_dim).float().view(b_dim, d_dim) @@ -85,9 +85,9 @@ def _run_demo(): result = torch.empty_like(a_tensor).numpy() kernel_args = (a_tensor.numpy(), g_tensor.numpy(), result) - if triton_viz_enabled: + if tilelens_enabled: print("Executing kernel with NKI interpreter...") - traced_kernel = triton_viz.trace(client=Tracer(), frontend="nki")( + traced_kernel = tilelens.trace(client=Tracer(), frontend="nki")( nki_rmsnorm_kernel ) kernel_instance = traced_kernel[kernel_grid] @@ -107,7 +107,7 @@ def _run_demo(): print(f" masks shape: {record.masks.shape}") try: - triton_viz.launch(share=False) + tilelens.launch(share=False) except Exception as e: print(f"\nError during visualization: {e}") import traceback diff --git a/examples/nki/rope.py b/examples/nki/rope.py index 0b959895c..b84a70411 100644 --- a/examples/nki/rope.py +++ b/examples/nki/rope.py @@ -3,9 +3,9 @@ import neuronxcc.nki.language as nl import torch from neuronxcc import nki -import triton_viz -from triton_viz.clients import Tracer -from triton_viz.core.trace import launches +import tilelens +from tilelens.clients import Tracer +from tilelens.core.trace import launches import numpy as np os.environ["NEURON_FRAMEWORK_DEBUG"] = "1" @@ -209,11 +209,11 @@ def rotate_half(x): def _run_demo(): - triton_viz_enabled = True + tilelens_enabled = True h_dim, s_dim, d_dim = 2, 4, 8 kernel_grid = (h_dim,) - if triton_viz_enabled: + if tilelens_enabled: q = torch.randn(h_dim, s_dim, d_dim) k = torch.randn(h_dim, s_dim, d_dim) position_ids = torch.arange(s_dim) @@ -231,9 +231,7 @@ def _run_demo(): ) print("Executing rotary embedding kernel with NKI interpreter...") - traced_kernel = triton_viz.trace(client=Tracer(), frontend="nki")( - nki_rope_kernel - ) + traced_kernel = tilelens.trace(client=Tracer(), frontend="nki")(nki_rope_kernel) kernel_instance = traced_kernel[kernel_grid] kernel_instance(*kernel_args) @@ -243,7 +241,7 @@ def _run_demo(): print(f"Number of records: {len(launch.records)}") try: - triton_viz.launch(share=False) + tilelens.launch(share=False) except Exception as e: print(f"Visualization error: {e}") else: diff --git a/examples/nki/softmax.py b/examples/nki/softmax.py index fb051b7a8..80e0b1bdb 100644 --- a/examples/nki/softmax.py +++ b/examples/nki/softmax.py @@ -1,9 +1,9 @@ from neuronxcc import nki import neuronxcc.nki.language as nl -import triton_viz -from triton_viz.clients import Tracer -from triton_viz.core.trace import launches +import tilelens +from tilelens.clients import Tracer +from tilelens.core.trace import launches import numpy as np import math @@ -31,17 +31,15 @@ def softmax_kernel(in_tensor, out_tensor): def _run_demo(): - triton_viz_enabled = True + tilelens_enabled = True kernel_grid = (1, 1, 1) x_small = np.random.rand(16, 32).astype(np.float32) y_small = np.empty(x_small.shape, dtype=x_small.dtype) kernel_args = (x_small, y_small) - if triton_viz_enabled: + if tilelens_enabled: print("Executing softmax_kernel with NKI interpreter...") - traced_kernel = triton_viz.trace(client=Tracer(), frontend="nki")( - softmax_kernel - ) + traced_kernel = tilelens.trace(client=Tracer(), frontend="nki")(softmax_kernel) kernel_instance = traced_kernel[kernel_grid] kernel_instance(*kernel_args) @@ -59,7 +57,7 @@ def _run_demo(): print(f" masks shape: {record.masks.shape}") try: - triton_viz.launch(share=False) + tilelens.launch(share=False) except Exception as e: print(f"\nError during visualization: {e}") import traceback diff --git a/examples/nki_beta2/add.py b/examples/nki_beta2/add.py index 8ee7683bc..4ea494922 100644 --- a/examples/nki_beta2/add.py +++ b/examples/nki_beta2/add.py @@ -4,8 +4,8 @@ import numpy as np import torch -TRITON_VIZ_ENABLED = True -PRE_TRACE = True # Run NKI Beta 2 compiler tracing before Triton-Viz simulation for stronger semantic checks. +TILELENS_ENABLED = True +PRE_TRACE = True # Run NKI Beta 2 compiler tracing before TileLens simulation for stronger semantic checks. def nki_tensor_add_kernel(a_input, b_input, result): @@ -63,14 +63,14 @@ def _run_demo(): kernel_args = (a, b, result) expected = a + b - if TRITON_VIZ_ENABLED: - import triton_viz + if TILELENS_ENABLED: + import tilelens - traced_kernel = triton_viz.trace("tracer", frontend="nki_beta2")(kernel) + traced_kernel = tilelens.trace("tracer", frontend="nki_beta2")(kernel) traced_kernel[kernel_grid](*kernel_args, pre_trace=PRE_TRACE) assert np.allclose(expected, result) print("☑️ Actual equals expected!") - triton_viz.launch(share=False) + tilelens.launch(share=False) else: # Note: no official NKI Beta 2 CPU interpreter exists so run on XLA result = _run_with_xla(kernel, kernel_grid, *kernel_args) assert np.allclose(expected, result) diff --git a/examples/nki_beta2/matmul.py b/examples/nki_beta2/matmul.py index dac4c695e..c09575405 100644 --- a/examples/nki_beta2/matmul.py +++ b/examples/nki_beta2/matmul.py @@ -4,8 +4,8 @@ import numpy as np -TRITON_VIZ_ENABLED = True -PRE_TRACE = True # Run NKI Beta 2 compiler tracing before Triton-Viz simulation for stronger semantic checks. +TILELENS_ENABLED = True +PRE_TRACE = True # Run NKI Beta 2 compiler tracing before TileLens simulation for stronger semantic checks. def matmul_kernel(lhsT, rhs, result): @@ -109,14 +109,14 @@ def _run_demo(): kernel_args = (lhs_small, rhs_small, result) expected = lhs_small.T @ rhs_small - if TRITON_VIZ_ENABLED: - import triton_viz + if TILELENS_ENABLED: + import tilelens - traced_kernel = triton_viz.trace("tracer", frontend="nki_beta2")(kernel) + traced_kernel = tilelens.trace("tracer", frontend="nki_beta2")(kernel) traced_kernel[kernel_grid](*kernel_args, pre_trace=PRE_TRACE) assert np.allclose(expected, result) print("☑️ Actual equals expected!") - triton_viz.launch(share=False) + tilelens.launch(share=False) else: result = _run_with_xla(kernel, kernel_grid, *kernel_args) assert np.allclose(expected, result) diff --git a/examples/nki_beta2/mlp.py b/examples/nki_beta2/mlp.py index 59686287a..db8a1809e 100644 --- a/examples/nki_beta2/mlp.py +++ b/examples/nki_beta2/mlp.py @@ -4,8 +4,8 @@ import numpy as np -TRITON_VIZ_ENABLED = True -PRE_TRACE = True # Run NKI Beta 2 compiler tracing before Triton-Viz simulation for stronger semantic checks. +TILELENS_ENABLED = True +PRE_TRACE = True # Run NKI Beta 2 compiler tracing before TileLens simulation for stronger semantic checks. TILE_M = 128 TILE_K = 128 TILE_H = 128 @@ -170,14 +170,14 @@ def _run_demo(): kernel_args = (x_t, w1_padded, w2_padded, out) expected = np.maximum(x @ w1, 0.0) @ w2 - if TRITON_VIZ_ENABLED: - import triton_viz + if TILELENS_ENABLED: + import tilelens - traced_kernel = triton_viz.trace("tracer", frontend="nki_beta2")(mlp_kernel) + traced_kernel = tilelens.trace("tracer", frontend="nki_beta2")(mlp_kernel) traced_kernel[kernel_grid](*kernel_args, pre_trace=PRE_TRACE) assert np.allclose(expected, out[:batch, :out_dim], atol=1e-4, rtol=1e-4) print("☑️ Actual equals expected!") - triton_viz.launch(share=False) + tilelens.launch(share=False) else: out = _run_with_xla(mlp_kernel, kernel_grid, *kernel_args) assert np.allclose(expected, out[:batch, :out_dim], atol=1e-4, rtol=1e-4) diff --git a/examples/nki_beta2/rmsnorm.py b/examples/nki_beta2/rmsnorm.py index 6a497cf18..811a18ff1 100644 --- a/examples/nki_beta2/rmsnorm.py +++ b/examples/nki_beta2/rmsnorm.py @@ -4,8 +4,8 @@ import numpy as np -TRITON_VIZ_ENABLED = True -PRE_TRACE = True # Run NKI Beta 2 compiler tracing before Triton-Viz simulation for stronger semantic checks. +TILELENS_ENABLED = True +PRE_TRACE = True # Run NKI Beta 2 compiler tracing before TileLens simulation for stronger semantic checks. def rmsnorm_kernel(x, gamma, out, eps=1e-6): @@ -94,14 +94,14 @@ def _run_demo(): kernel_args = (x, gamma, out) expected = _numpy_rmsnorm(x, gamma) - if TRITON_VIZ_ENABLED: - import triton_viz + if TILELENS_ENABLED: + import tilelens - traced_kernel = triton_viz.trace("tracer", frontend="nki_beta2")(rmsnorm_kernel) + traced_kernel = tilelens.trace("tracer", frontend="nki_beta2")(rmsnorm_kernel) traced_kernel[kernel_grid](*kernel_args, pre_trace=PRE_TRACE) assert np.allclose(expected, out) print("☑️ Actual equals expected!") - triton_viz.launch(share=False) + tilelens.launch(share=False) else: out = _run_with_xla(rmsnorm_kernel, kernel_grid, *kernel_args) assert np.allclose(expected, out) diff --git a/examples/nki_beta2/rope.py b/examples/nki_beta2/rope.py index f388baa05..ee7917521 100644 --- a/examples/nki_beta2/rope.py +++ b/examples/nki_beta2/rope.py @@ -4,8 +4,8 @@ import numpy as np -TRITON_VIZ_ENABLED = True -PRE_TRACE = True # Run NKI Beta 2 compiler tracing before Triton-Viz simulation for stronger semantic checks. +TILELENS_ENABLED = True +PRE_TRACE = True # Run NKI Beta 2 compiler tracing before TileLens simulation for stronger semantic checks. def _rotate_half(x): @@ -216,15 +216,15 @@ def _run_demo(): head_dim, ) - if TRITON_VIZ_ENABLED: - import triton_viz + if TILELENS_ENABLED: + import tilelens - traced_kernel = triton_viz.trace("tracer", frontend="nki_beta2")(rope_kernel) + traced_kernel = tilelens.trace("tracer", frontend="nki_beta2")(rope_kernel) traced_kernel[kernel_grid](*kernel_args, pre_trace=PRE_TRACE) assert np.allclose(expected_q, out_q4d) assert np.allclose(expected_k, out_k4d) print("☑️ Actual equals expected!") - triton_viz.launch(share=False) + tilelens.launch(share=False) else: out_q4d, out_k4d = _run_with_xla(rope_kernel, kernel_grid, *kernel_args) assert np.allclose(expected_q, out_q4d) diff --git a/examples/nki_beta2/softmax.py b/examples/nki_beta2/softmax.py index 4cc695289..e120da954 100644 --- a/examples/nki_beta2/softmax.py +++ b/examples/nki_beta2/softmax.py @@ -4,8 +4,8 @@ import numpy as np -TRITON_VIZ_ENABLED = True -PRE_TRACE = True # Run NKI Beta 2 compiler tracing before Triton-Viz simulation for stronger semantic checks. +TILELENS_ENABLED = True +PRE_TRACE = True # Run NKI Beta 2 compiler tracing before TileLens simulation for stronger semantic checks. def softmax_kernel(x, out): @@ -83,14 +83,14 @@ def _run_demo(): kernel_args = (x, out) expected = _numpy_softmax(x) - if TRITON_VIZ_ENABLED: - import triton_viz + if TILELENS_ENABLED: + import tilelens - traced_kernel = triton_viz.trace("tracer", frontend="nki_beta2")(softmax_kernel) + traced_kernel = tilelens.trace("tracer", frontend="nki_beta2")(softmax_kernel) traced_kernel[kernel_grid](*kernel_args, pre_trace=PRE_TRACE) assert np.allclose(expected, out) print("☑️ Actual equals expected!") - triton_viz.launch(share=False) + tilelens.launch(share=False) else: out = _run_with_xla(softmax_kernel, kernel_grid, *kernel_args) assert np.allclose(expected, out) diff --git a/examples/nki_beta2/tiled_attention.py b/examples/nki_beta2/tiled_attention.py index 91ee36ce9..b8fddacf6 100644 --- a/examples/nki_beta2/tiled_attention.py +++ b/examples/nki_beta2/tiled_attention.py @@ -4,8 +4,8 @@ import nki.language as nl import numpy as np -TRITON_VIZ_ENABLED = True -PRE_TRACE = True # Run NKI Beta 2 compiler tracing before Triton-Viz simulation for stronger semantic checks. +TILELENS_ENABLED = True +PRE_TRACE = True # Run NKI Beta 2 compiler tracing before TileLens simulation for stronger semantic checks. def tiled_attention_kernel( @@ -372,16 +372,16 @@ def _run_demo(): ) expected4d = _numpy_tiled_attention(q4d, k4d, v4d) - if TRITON_VIZ_ENABLED: - import triton_viz + if TILELENS_ENABLED: + import tilelens - traced_kernel = triton_viz.trace("tracer", frontend="nki_beta2")( + traced_kernel = tilelens.trace("tracer", frontend="nki_beta2")( tiled_attention_kernel ) traced_kernel[kernel_grid](*kernel_args, pre_trace=PRE_TRACE) assert np.allclose(expected4d, out4d) print("☑️ Actual equals expected!") - triton_viz.launch(share=False) + tilelens.launch(share=False) else: out4d = _run_with_xla(tiled_attention_kernel, kernel_grid, *kernel_args) assert np.allclose(expected4d, out4d) diff --git a/examples/profiler/load_store.py b/examples/profiler/load_store.py index e9710de50..1e15e9499 100644 --- a/examples/profiler/load_store.py +++ b/examples/profiler/load_store.py @@ -1,11 +1,11 @@ import torch import triton import triton.language as tl -import triton_viz -from triton_viz.core.config import config as cfg +import tilelens +from tilelens.core.config import config as cfg -@triton_viz.trace("profiler") +@tilelens.trace("profiler") @triton.jit def simple_kernel( x_ptr, diff --git a/examples/sanitizer/gemm.py b/examples/sanitizer/gemm.py index 18126591a..2fb7e7a26 100644 --- a/examples/sanitizer/gemm.py +++ b/examples/sanitizer/gemm.py @@ -3,10 +3,10 @@ import triton import triton.language as tl -import triton_viz +import tilelens -@triton_viz.trace("sanitizer") +@tilelens.trace("sanitizer") @triton.jit def gemm_kernel( A, B, C, M: tl.constexpr, N: tl.constexpr, K: tl.constexpr, TILE_SIZE: tl.constexpr diff --git a/examples/sanitizer/gemm_oob.py b/examples/sanitizer/gemm_oob.py index 6cae95075..d594500d5 100644 --- a/examples/sanitizer/gemm_oob.py +++ b/examples/sanitizer/gemm_oob.py @@ -3,10 +3,10 @@ import triton import triton.language as tl -import triton_viz +import tilelens -@triton_viz.trace("sanitizer") +@tilelens.trace("sanitizer") @triton.jit def gemm_kernel( A, B, C, M: tl.constexpr, N: tl.constexpr, K: tl.constexpr, TILE_SIZE: tl.constexpr diff --git a/examples/sanitizer/gluon_tma_oob.py b/examples/sanitizer/gluon_tma_oob.py index 7f9eb8409..39976a389 100644 --- a/examples/sanitizer/gluon_tma_oob.py +++ b/examples/sanitizer/gluon_tma_oob.py @@ -3,8 +3,8 @@ from triton.experimental.gluon import language as gl from triton.experimental.gluon.language.nvidia.hopper import mbarrier, tma -import triton_viz -from triton_viz.clients.sanitizer.sanitizer import Sanitizer +import tilelens +from tilelens.clients.sanitizer.sanitizer import Sanitizer BLOCK_M = 16 @@ -40,7 +40,7 @@ def gluon_tma_oob_kernel( def run(abort_on_error: bool = True): x = torch.zeros((BLOCK_M, BLOCK_N), dtype=torch.float32) layout = gl.NVMMASharedLayout.get_default_for([BLOCK_M, BLOCK_N], gl.float32) - kernel = triton_viz.trace( + kernel = tilelens.trace( client=Sanitizer(abort_on_error=abort_on_error), frontend="gluon", )(gluon_tma_oob_kernel) diff --git a/examples/sanitizer/oob_tensor_view.py b/examples/sanitizer/oob_tensor_view.py index 6ffdd6373..defeafbb5 100644 --- a/examples/sanitizer/oob_tensor_view.py +++ b/examples/sanitizer/oob_tensor_view.py @@ -2,7 +2,7 @@ When a masked ``tl.load`` uses a logical length larger than the view's element count, the JIT performs a "wild pointer read" past the underlying -storage. This example wraps the kernel with the triton-viz sanitizer so the +storage. This example wraps the kernel with the tilelens sanitizer so the OOB access is caught symbolically instead of silently returning OOB memory. """ @@ -11,10 +11,10 @@ import triton import triton.language as tl -import triton_viz +import tilelens -@triton_viz.trace("sanitizer") +@tilelens.trace("sanitizer") @triton.jit def oob_load_kernel( vals_ptr, diff --git a/examples/visualizer/3dims.py b/examples/visualizer/3dims.py index b58683b77..ada043888 100644 --- a/examples/visualizer/3dims.py +++ b/examples/visualizer/3dims.py @@ -3,15 +3,15 @@ import triton.language as tl -import triton_viz -from triton_viz.clients import Tracer +import tilelens +from tilelens.clients import Tracer BLOCK_SIZE_X = 32 BLOCK_SIZE_Y = 8 BLOCK_SIZE_Z = 4 -@triton_viz.trace(client=Tracer()) +@tilelens.trace(client=Tracer()) @triton.jit def add_3d_slices_kernel( input_ptr1, @@ -109,7 +109,7 @@ def add_3d_slices(input1, input2, output): # Call the kernel add_3d_slices(input1, input2, output) - triton_viz.launch(share=False, port=5001) + tilelens.launch(share=False, port=5001) # Verify the result expected_output = input1 + input2 diff --git a/examples/visualizer/9dims_copy.py b/examples/visualizer/9dims_copy.py index 26a7f173c..210746c3d 100644 --- a/examples/visualizer/9dims_copy.py +++ b/examples/visualizer/9dims_copy.py @@ -1,14 +1,14 @@ import torch import triton import triton.language as tl -import triton_viz +import tilelens BLOCK = 1024 SHAPE = (2, 3, 4, 3, 4, 2, 4, 2, 3) -@triton_viz.trace("tracer") +@tilelens.trace("tracer") @triton.jit def copy_9d_kernel( x_ptr, @@ -26,7 +26,7 @@ def copy_9d_kernel( def run_demo() -> None: - """Run a rank-9 copy example and launch Triton Viz.""" + """Run a rank-9 copy example and launch TileLens.""" torch.manual_seed(0) x = torch.randn(SHAPE, device="cpu") y = torch.empty_like(x) @@ -41,7 +41,7 @@ def run_demo() -> None: ) assert torch.allclose(y, x), "copy kernel output mismatch" - triton_viz.launch(share=False, port=5001) + tilelens.launch(share=False, port=5001) if __name__ == "__main__": diff --git a/examples/visualizer/indirect_load.py b/examples/visualizer/indirect_load.py index d967ced72..11e75837b 100644 --- a/examples/visualizer/indirect_load.py +++ b/examples/visualizer/indirect_load.py @@ -2,13 +2,13 @@ import triton import triton.language as tl -import triton_viz +import tilelens N = 64 BLOCK = 16 -@triton_viz.trace("tracer") +@tilelens.trace("tracer") @triton.jit def indirect_load_kernel(x_ptr, rand_ptr, out_ptr, BLOCK: tl.constexpr): offs = tl.arange(0, BLOCK) @@ -24,7 +24,7 @@ def run(): rand = torch.randperm(N, dtype=torch.int32, device=device) out = torch.zeros_like(x) indirect_load_kernel[(1,)](x, rand, out, BLOCK=BLOCK) - triton_viz.launch(share=False, port=5001) + tilelens.launch(share=False, port=5001) if __name__ == "__main__": diff --git a/examples/visualizer/matmul.py b/examples/visualizer/matmul.py index cd8827d77..095965db3 100644 --- a/examples/visualizer/matmul.py +++ b/examples/visualizer/matmul.py @@ -2,12 +2,12 @@ import triton import triton.language as tl -import triton_viz -from triton_viz.clients import Tracer +import tilelens +from tilelens.clients import Tracer # Simple matmul kernel producing a C = A @ B (fp32, small sizes for demo) -@triton_viz.trace(client=Tracer()) +@tilelens.trace(client=Tracer()) @triton.jit def matmul_kernel( a_ptr, @@ -86,7 +86,7 @@ def run_demo(): assert torch.allclose(c, ref, atol=1e-3), "matmul result mismatch" # Launch viz UI in blocking (share=True) mode - triton_viz.launch(share=False, port=5001) + tilelens.launch(share=False, port=5001) if __name__ == "__main__": diff --git a/frontend/GLOSSARY.md b/frontend/GLOSSARY.md index 04fbb450c..69b54b25b 100644 --- a/frontend/GLOSSARY.md +++ b/frontend/GLOSSARY.md @@ -1,6 +1,6 @@ # Glossary -This glossary defines the canonical UI terms, data types, and events used across the Triton-Viz frontend. +This glossary defines the canonical UI terms, data types, and events used across the TileLens frontend. ## UI Surfaces - Control Panel: left sidebar with program controls, operation controls, and the code peek panel. diff --git a/frontend/components/op_workspace.ts b/frontend/components/op_workspace.ts index 007e7001b..e5ac7f81f 100644 --- a/frontend/components/op_workspace.ts +++ b/frontend/components/op_workspace.ts @@ -79,7 +79,7 @@ export class OpWorkspace { this.ensureGlobalCodeToggle(); try { - window.__tritonVizActiveBlock = this; + window.__tileLensActiveBlock = this; } catch (error) {} } @@ -303,7 +303,7 @@ export class OpWorkspace { const canReuseViz = !!options.preserveViewState && isSameTab && !!this.contentArea.__vizGetState; const preserveCodePanel = options.refreshCodePanel === false; if (preserveCodePanel) { - try { window.__tritonVizPreserveCodePanel = true; } catch (error) {} + try { window.__tileLensPreserveCodePanel = true; } catch (error) {} } const isTensorOp = op.type === 'Dot' || op.type === 'Load' || op.type === 'Store' || op.type === 'Transfer'; const reuseTensorView = canReuseViz && isTensorOp && this.lastOpType === op.type; @@ -314,7 +314,7 @@ export class OpWorkspace { } } finally { if (preserveCodePanel) { - try { window.__tritonVizPreserveCodePanel = false; } catch (error) {} + try { window.__tileLensPreserveCodePanel = false; } catch (error) {} } } if (!reuseTensorView) { @@ -366,7 +366,7 @@ export class OpWorkspace { } ensureGlobalCodeToggle(): void { - if (window.__tritonVizCodeToggle) return; + if (window.__tileLensCodeToggle) return; let panel: HTMLDivElement | null = null; let visible = false; @@ -380,7 +380,7 @@ export class OpWorkspace { }; const getActiveUuid = (): string | null => { - const activeBlock = window.__tritonVizActiveBlock; + const activeBlock = window.__tileLensActiveBlock; const candidate = window.current_op_uuid ?? activeBlock?.blockData?.[0]?.uuid; return candidate ?? null; }; @@ -461,16 +461,16 @@ export class OpWorkspace { return visible; }; - window.__tritonVizCodeToggle = togglePanel; - window.__tritonVizCodeHide = hidePanel; - window.__tritonVizCodeVisible = () => visible; + window.__tileLensCodeToggle = togglePanel; + window.__tileLensCodeHide = hidePanel; + window.__tileLensCodeVisible = () => visible; } syncCodePanel(forceShow = false): void { - if (!window.__tritonVizCodeToggle) return; - const isVisible = window.__tritonVizCodeVisible ? window.__tritonVizCodeVisible() : false; + if (!window.__tileLensCodeToggle) return; + const isVisible = window.__tileLensCodeVisible ? window.__tileLensCodeVisible() : false; if (!forceShow && !isVisible) return; - const result = window.__tritonVizCodeToggle(true); + const result = window.__tileLensCodeToggle(true); const setOpControlState = window.setOpControlState; if (!setOpControlState) return; if (result && typeof (result as any).then === 'function') { diff --git a/frontend/components/tensor_view.ts b/frontend/components/tensor_view.ts index 1b2123069..9f547dd2f 100644 --- a/frontend/components/tensor_view.ts +++ b/frontend/components/tensor_view.ts @@ -1932,8 +1932,8 @@ export function createTensorVisualization( state.rafId = requestAnimationFrame(() => { state.rafId = null; orbitControls.update(); syncClipPlanes(); renderer.render(scene, camera); if (state.renderPending) { state.renderPending = false; ctx.requestRender(); } }); }; const handleTextSync = (): void => { ctx.requestRender(); }; - window.addEventListener('triton-viz-text-sync', handleTextSync); - disposer.add(() => window.removeEventListener('triton-viz-text-sync', handleTextSync)); + window.addEventListener('tilelens-text-sync', handleTextSync); + disposer.add(() => window.removeEventListener('tilelens-text-sync', handleTextSync)); let lastWidth = 0; let lastHeight = 0; const resizeRenderer = (): void => { @@ -2538,7 +2538,7 @@ export function createTensorVisualization( requestRender(); return state.colorizeOn; }, - toggleShowCode: () => window.__tritonVizCodeToggle?.(), + toggleShowCode: () => window.__tileLensCodeToggle?.(), toggleHistogram: (): boolean => { const isVisible = vizCache.histogramUI.overlay.style.display === 'block'; if (isVisible) { diff --git a/frontend/core/api.ts b/frontend/core/api.ts index 0bbca07f3..35ae41ad6 100644 --- a/frontend/core/api.ts +++ b/frontend/core/api.ts @@ -8,7 +8,7 @@ export type RequestOptions = { const getDefaultBase = (): string => { if (typeof globalThis === 'undefined') return ''; - const globalBase = (globalThis as typeof globalThis & { __TRITON_VIZ_API__?: string }).__TRITON_VIZ_API__; + const globalBase = (globalThis as typeof globalThis & { __TILELENS_API__?: string }).__TILELENS_API__; if (globalBase) return globalBase; if (typeof window === 'undefined' || !window.location) return ''; // derive a stable base from the current page location for proxy paths diff --git a/frontend/core/logger.ts b/frontend/core/logger.ts index 9f112b90b..1eb99f1ab 100644 --- a/frontend/core/logger.ts +++ b/frontend/core/logger.ts @@ -1,4 +1,4 @@ -const LOG_PREFIX = '[triton-viz]'; +const LOG_PREFIX = '[tilelens]'; export function logAction(action: string, details: Record = {}): void { console.info(LOG_PREFIX, action, details); diff --git a/frontend/core/visualization.ts b/frontend/core/visualization.ts index 976a18c73..fa32c8314 100644 --- a/frontend/core/visualization.ts +++ b/frontend/core/visualization.ts @@ -30,7 +30,7 @@ let maxZ = 0; const PROGRAM_AXES: Array = ['x', 'y', 'z']; const appDisposer = createDisposer(); let pidDisposer = createDisposer(); -const THEME_STORAGE_KEY = 'triton-viz-theme'; +const THEME_STORAGE_KEY = 'tilelens-theme'; const DEV_OVERLAY_QUERY_KEY = 'dev'; const DEV_OVERLAY_TOGGLE = 'KeyD'; let devOverlayEnabled = false; @@ -69,7 +69,7 @@ function setOpControlState(nextState: Partial> = {}): ...nextState, }; setToggles(toggles); - try { window.__tritonVizOpState = { ...toggles }; } catch (err) {} + try { window.__tileLensOpState = { ...toggles }; } catch (err) {} updateOpControls(toggles); } @@ -82,9 +82,9 @@ function resetOpControls(): void { opControls.handlers = null; closeDownloadModal(); const nextState = resetToggles(); - try { window.__tritonVizOpState = { ...nextState.toggles }; } catch (err) {} - if (window.__tritonVizCodeHide) { - window.__tritonVizCodeHide(); + try { window.__tileLensOpState = { ...nextState.toggles }; } catch (err) {} + if (window.__tileLensCodeHide) { + window.__tileLensCodeHide(); } updateOpControls(nextState.toggles); } diff --git a/frontend/templates/index.html b/frontend/templates/index.html index b120159c4..f2e2144a7 100644 --- a/frontend/templates/index.html +++ b/frontend/templates/index.html @@ -11,7 +11,7 @@