跳到主要内容
TileLang 系统教程

tilelang-tutorial.huandu.me

第 10 章 布局与存储层级入门

/code/10-layout-and-memory-intro/

02-plot-layout/plot_layout_demo.py3218 字节
#!/usr/bin/env python3
"""Observe TileLang layouts with tilelang.tools.plot_layout (chapter 10, §3.4).

This is the "how to look at a layout" example. It plots four things:

  1. a hand-written T.Layout (4x4 transpose);
  2. a hand-written T.Fragment (2D -> (thread, local index));
  3. the 128B full-bank shared-memory swizzle of an 8x64 fp16 buffer;
  4. the same buffer read/viewed from the output side.

It needs TileLang (v0.1.15) and Matplotlib installed; it does NOT need a GPU:
layouts are pure index maps, and plot_layout enumerates them in Python.

Usage:
    pip install "tilelang[vis]"      # [vis] pulls in Matplotlib
    python3 plot_layout_demo.py
    # write-ups land under ./tmp/

Verified level: statically checked only. The authoring machine has no TileLang
installed and no GPU, so this file was NOT run; every API call was checked by
reading the v0.1.15 sources listed in the README. Do not treat its output as
observed until you run it.
"""

from __future__ import annotations

import tilelang.language as T
from tilelang.tools import plot_layout

OUT = "./tmp"


def demo_transpose_layout() -> None:
    """A layout is just a forward function: logical (i, j) -> physical (j, i)."""
    transpose = T.Layout([4, 4], lambda i, j: (j, i))
    print("transpose 4x4:", transpose)
    plot_layout(transpose, save_directory=OUT, name="transpose_4x4", formats="png")
    # view="output" draws the output space and labels cells with their source.
    plot_layout(
        transpose,
        save_directory=OUT,
        name="transpose_4x4_output_view",
        formats="png",
        view="output",
    )


def demo_fragment() -> None:
    """A fragment adds a thread mapping and a per-thread local index.

    Here every element (i, j) goes to thread (4*i + j//2) as that thread's
    register slot (j % 2). plot_layout labels each cell with T<thread> and
    L<local>; the picture is exactly figure 4 of the chapter.
    """
    fragment = T.Fragment([8, 8], forward_fn=lambda i, j: (4 * i + j // 2, j % 2))
    print("fragment 8x8:", fragment)
    plot_layout(fragment, save_directory=OUT, name="fragment_8x8", formats="png")


def demo_shared_swizzle() -> None:
    """Shared-memory bank swizzles are plain Layouts too.

    make_full_bank_swizzled_layout takes a *buffer*, not a shape: the swizzle
    depends on the buffer's dtype (to compute the 16B unit) and its strides.
    """
    from tvm import tirx
    from tilelang.layout import make_full_bank_swizzled_layout

    # 8x64 fp16: 128B swizzle needs continuous % (16B-unit * 8) == 0 -> 64 % 64 == 0.
    buf = tirx.decl_buffer((8, 64), "float16", name="A_shared", scope="shared")
    swizzled = make_full_bank_swizzled_layout(buf)
    print("full-bank swizzle:", swizzled)
    plot_layout(swizzled, save_directory=OUT, name="swizzle_full_8x64", formats="png")
    plot_layout(
        swizzled,
        save_directory=OUT,
        name="swizzle_full_8x64_output_view",
        formats="png",
        view="output",
    )


def main() -> None:
    demo_transpose_layout()
    demo_fragment()
    demo_shared_swizzle()
    print(f"PNG files written under {OUT}/; open them and read each cell's label.")


if __name__ == "__main__":
    main()

← 浏览本章全部代码