| name | sketch-design |
| description | 算子草图设计语言规范和生成指导,包含 UnifiedSketch DSL 语法和算子草图设计方法论 |
| category | guide |
| version | 1.0.0 |
| metadata | {"role":"designer"} |
UnifiedSketch 设计
目标与原则
目标
用最小DSL表达算子设计意图,便于LLM理解和Coder实现。
原则
- 极简原语:只有少数核心操作(alloc/load/store/compute/...)
- 统一语法:所有操作都是函数调用风格,无语法差异
- 标准控制流:使用Python for/range语法,不发明新语法
- hint分离:复杂优化用hint表达,不影响主逻辑清晰性
核心语法元素
结构声明
sketch <op_name> {
symbols: M, N, K;
tensors: A[M, K]: f16; B[K, N]: f16; C[M, N]: f32;
constexpr: m0, k0, n0
}
@llm_hint 装饰器详解
基本语法
@llm_hint 用于给 LLM 提供优化提示,帮助 coder 选择最优的实现策略。
@llm_hint("optimization_type")
@llm_hint("optimization_type", "context")
@llm_hint("opt1", "opt2", "opt3")
优化类型
"parallel" - 并行化此循环
"pipeline" - 流水线优化
"vectorize" - 向量化
"unroll" - 循环展开
硬件上下文提示
"grididx" - GPU grid 级别并行(对应 blockIdx)
"threadidx" - GPU thread 级别并行(对应 threadIdx)
"coreidx" - NPU core 级别并行
"warp" - GPU warp 级别优化
"simd" - CPU/NPU SIMD 向量化
for循环表达
@llm_hint("parallel", "grididx.x")
for i in range(0, M, 128):
@llm_hint("parallel", "threadidx.x")
for j in range(0, N, 32):
@llm_hint("pipeline")
for k in range(0, K, k_tile):
@llm_hint("parallel", "coreidx")
for core_idx in range(num_cores):
@llm_hint("pipeline")
for k in range(0, K, k_tile):
@llm_hint("parallel")
for i in range(0, M, tile_size):
@llm_hint(, )
j (tile_size):
核心操作
- alloc - 内存分配
- load - 数据加载
- store - 数据存储
- compute函数 - 计算操作
语法概览
sketch matmul {
symbols: M, N, K;
tensors: A[M, K]: f16; B[K, N]: f16; C[M, N]: f32;
m0, k0, n0 = 128, 256, 256
@llm_hint("parallel")
for i_outer in range(0, ceil(M, m0)):
@llm_hint("parallel")
for j_outer in range(0, ceil(N, n0)):
c_tile = alloc([m0, n0], llm_hint=["accumulator", "init_zero"])
a_tile = alloc([m0, k0], llm_hint=["fast", "input_cache"])
b_tile = alloc([k0, n0], llm_hint=["fast", "input_cache"])
@llm_hint("pipeline")
for k_outer in range(0, ceil(K, k0)):
load(A[i_outer:i_outer+m0, k_outer:k_outer+k0] -> a_tile)
load(B[k_outer:k_outer+k0, j_outer:j_outer+n0] -> b_tile)
gemm(a_tile, b_tile, dst=c_tile)
store(c_tile -> C[i_outer:i_outer+m0, j_outer:j_outer+n0])
}
内存管理系统
alloc() 语法
tile = alloc([shape], llm_hint=["存储要求", "用途说明", "性能要求"])
hint设计原则
语义化描述,让LLM根据硬件文档选择具体实现
存储要求(性能层次)
"fastest" - 最快访问速度,容量小(让LLM选择register/L0等)
"fast" - 快速访问,中等容量(让LLM选择shared/L1等)
"medium" - 中等速度,较大容量(让LLM选择L2/cache等)
"slow" - 较慢但容量大(让LLM选择global/DDR等)
用途说明(帮助LLM理解意图)
"accumulator" - 累加器,需要频繁读写
"input_cache" - 输入数据缓存,主要读取
"output_buffer" - 输出缓冲,主要写入
"temp_workspace" - 临时工作空间
"shared_between_threads" - 线程间共享数据
初始化要求
"init_zero" - 初始化为0
"no_init" - 不初始化(默认)
示例
c_acc = alloc([128, 128], llm_hint=["fastest", "accumulator", "init_zero"])
a_cache = alloc([128, 256], llm_hint=["fast", "input_cache"])
temp = alloc([128], llm_hint=["fast", "temp_workspace"])
数据搬移操作
load() 语法
load(tensor[slice] -> tile)
store() 语法
store(tile -> tensor[slice])
切片表达
A[i:i+128, k:k+256]
X[start:end]
A[i_outer:i_outer+m0, k_outer:k_outer+k0]
示例
load(A[0:128, 0:256] -> a_tile)
store(result_tile -> C[i:i+128, j:j+128])
计算操作库
基础运算
add(src1, src2, dst)
mul(src1, src2, dst)
sub(src1, src2, dst)
div(src1, src2, dst)
max(src1, src2, dst)
min(src1, src2, dst)
...
数学函数
exp(src, dst)
log(src, dst)
sqrt(src, dst)
abs(src, dst)
tanh(src, dst)
sigmoid(src, dst)
...
线性代数
gemm(a, b, dst)
dot(a, b, result)
reduce_sum(src, axis, dst)
reduce_max(src, axis, dst)
...
复合函数
relu(src, dst)
gelu(src, dst)
silu(src, dst)
softmax(src, dst)
...
并行与优化提示
多参数 @llm_hint 用法
不同硬件的并行模式
@llm_hint("parallel", "grididx")
@llm_hint("parallel", "threadidx")
@llm_hint("parallel", "coreidx")
@llm_hint("parallel")
@llm_hint("vectorize", "simd")
组合使用策略
@llm_hint("parallel", "grididx")
for block_i in range(M_blocks):
@llm_hint("parallel", "threadidx")
for thread_j in range(threads_per_block):
@llm_hint("pipeline")
for k in range(k_blocks):
@llm_hint("parallel", "coreidx")
for core_idx in range(num_cores):
@llm_hint("pipeline")
for k in range(k_tiles):
@llm_hint("vectorize")
for i in range(vector_size):
常见模式示例
MatMul(如上面语法概览)
Elementwise - ReLU
sketch relu {
symbols: N;
tensors: X[N]: f32; Y[N]: f32;
tile_size = 1024
@llm_hint("parallel")
for i in range(0, ceil(N, tile_size)):
x_tile = alloc([tile_size], llm_hint="l1_buffer")
y_tile = alloc([tile_size], llm_hint="l1_buffer")
load(X[i:i+tile_size] -> x_tile)
relu(x_tile, y_tile)
store(y_tile -> Y[i:i+tile_size])
}
Reduction - Softmax
sketch softmax {
symbols: B, N;
tensors: X[B, N]: f32; Y[B, N]: f32;
@llm_hint("parallel")
for b in range(B):
x_row = alloc([N], llm_hint="l1_buffer")
y_row = alloc([N], llm_hint="l1_buffer")
max_val = alloc([1], llm_hint="l0c")
sum_val = alloc([1], llm_hint="l0c")
load(X[b, 0:N] -> x_row)
reduce_max(x_row, axis=0, max_val)
sub(x_row, max_val, x_row)
exp(x_row, y_row)
reduce_sum(y_row, axis=0, sum_val)
div(y_row, sum_val, y_row)
store(y_row -> Y[b, 0:N])
}
复合算子 - GELU
sketch gelu {
symbols: N;
tensors: X[N]: f32; Y[N]: f32;
tile_size = 512
@llm_hint("parallel")
for i in range(0, ceil(N, tile_size)):
x_tile = alloc([tile_size], llm_hint="l1_buffer")
y_tile = alloc([tile_size], llm_hint="l1_buffer")
load(X[i:i+tile_size] -> x_tile)
gelu(x_tile, y_tile)
store(y_tile -> Y[i:i+tile_size])
}
最佳实践
编写顺序
- 先写基本结构:symbols, tensors, 主循环框架
- 再加内存管理:alloc合适的tile
- 然后加数据流:load -> compute -> store
- 最后加优化hint:@llm_hint装饰器
Tile大小设置
- 考虑硬件内存约束(如NPU UB大小、GPU shared memory限制)
- 优先选择2的幂次(128, 256, 512, 1024)
- 保证数据对齐要求
错误避免
- 不要混用抽象层次:要么用高级函数(gelu),要么用基础运算(add+mul)
- 明确数据流向:每个load都要有对应的compute,每个compute都要有对应的store
- 合理使用hint:不要过度优化,先保证逻辑正确