Parser 工具#

下面几项工具在 TVMScript 转换为 TIRx 的 parse time 生效。它们可以将 Python 计算得到的值直接写入 IR、提取可复用的代码片段,以及组织 parser 阶段使用的状态。

T.meta_var:内联 Python 值#

T.meta_var(x) 告诉 parser,x 是由 Python 计算得到的编译期 meta value,应直接内联到 IR,而不是作为 script variable 解析。它既可以省去没有 实际用途的临时变量,也让 Python values 能够参数化生成的 IR。普通 range(n) 仍会生成 serial TIRx loop;需要 lowering pipeline 展开时应使用 T.unroll(n)

n = T.meta_var(4)              # constant 4 is inlined as the extent
for j in T.unroll(n):          # marked for the UnrollLoop lowering pass
    acc[0] = acc[0] + A[tx, j]

@T.inline:内联函数#

@T.inline 定义的函数会在 parse time 内联到每个调用位置,生成的代码中 不会保留函数调用。它遵循 Python 的 lexical(LEGB)scope 和 late binding; 函数参数会覆盖外层的同名变量:

@T.inline
def add_into(acc, x):
    acc[0] = acc[0] + x

add_into(acc, A[tx, j])       # inlined -> acc[0] = acc[0] + A[tx, j]

@T.meta_class:组织 Parser 状态#

@T.meta_class 修饰普通的 Python class,使它的 instances 成为 parser meta values。对象字段可以保存 buffers 和 scalars,因此可以把相关的 allocation 和状态放进同一个对象,再在 kernel body 中使用。

@T.meta_class
class State:
    def __init__(self, smem):
        self.acc = T.alloc_local([1], "float32")
        self.buf = T.decl_buffer([64], "float16", smem, scope="shared.dyn")

s = State(smem.data)
s.acc[0] = T.float32(0.0)     # use its fields like ordinary buffers
# ... s.buf[i] ...

这种写法适合组织 kernel 的 pipeline state,例如 barriers、accumulators 和 临时 views,避免在函数中传递大量分散的局部变量。

T.constexpr#

T.constexpr 声明编译期 kernel parameter,其值由 @T.jit.specialize(...) 固定。具体用法见 TIRx 入门