cute(2)Tensor基础
Ref
2 Tensor 基础
对应代码:
02_tensor_basics.cu纯 host 代码,不需要 GPU。
reed博士:Layout描述了数据的排列和底层存储位置关系,但Layout并没有指定存储。Tensor就是在Layout的基础上包含了存储,即Tensor = Layout + storage,数据存储的具体表现上可以是指针表达的数据或则是栈上数据(GPU上表现为寄存器)。cute中的Tensor并不同于深度学习框架中的Tensor(如Pytorch、Tensorflow),深度学习框架中的Tensor更强调数据的表达实体,通过Tensor实体与实体之间的计算产生新的Tensor实体,即多份数据实体,cute中的Tensor更多的是对Tensor进行分解和组合等操作,而这些操作多是对Layout的变换(只是逻辑层面的数据组织形式),底层的数据实体一般不变更。也就是说深度学习框架中的Tensor是通过Tensor产生新Tensor,cute中是对数据表达形式的变换,底层数据一般不变更,指变更表达的形式,这个表达形式的变更是通过之前文章介绍的Layout上的运算实现的。之所以有这些差别是因为深度学习框架中的Tensor是用来表达数据实体,cute中的Tensor是偏向描述的实体
核心概念
Tensor = 数据指针 + Layout
1 | Tensor = (data_ptr, layout) |
数据和索引方式是分离的。同一段内存可以用不同的 layout 去解读,不搬运任何数据。
代码解析
第 1 节:从数组创建 Tensor
1 | // ============================================================ |

1 | float data[12]; |
- 第一个参数:指针(
&data[0]),不能直接传数组名 - 第二个参数:layout,决定怎么解读这段内存
- 结果:3×4 row-major tensor
访问元素:
1 | tensor(0, 0) // data[0*4 + 0*1] = data[0] = 0 |
常见错误:make_tensor(data, layout) 传数组名会报错,必须传 &data[0] 指针。
打印函数:
print(tensor)— 打印元信息(指针地址 + layout)print_tensor(tensor)— 打印所有元素的值
第 2 节:同一数据,不同 Layout
1 | // ============================================================ |

1 | float data[12]; |
同一段内存 data,两个 tensor 指向同一个地址,只是 layout 不同:
1 | row_major(1, 2) = data[1*4 + 2*1] = data[6] = 6 |
核心理解:Layout 改变的是"怎么看数据",不是"数据本身"。这就是为什么后面的 compose、retile_D 等操作都是零开销——只改 layout 元数据,不搬数据。
第 3 节:Slice —— 用 _ 取整行/整列
1 | // ============================================================ |

1 | auto tensor = make_tensor(&data[0], make_layout(make_shape(3, 4), make_stride(4, 1))); |
_(Underscore)表示"保留这个维度"- 结果是一个降维的 tensor(二维变一维)
1 | tensor(1, _) = [4, 5, 6, 7] ← 第 1 行的 4 个元素 |
Slice 的本质:
- 固定某个维度的 index → 指针偏移到那个位置
- 保留的维度 → 构成新的 layout
- 不拷贝数据,只是换了一个起始指针 + 新 layout
第 4 节:local_tile —— 把大 Tensor 切成小 Tile
1 | // ============================================================ |

1 | // 6×8 row-major 矩阵 |
local_tile 的三个参数:
- 原始 tensor
- tile 的大小
(3, 4) - 取哪个 tile 的坐标,
_表示保留所有
结果 shape (3, 4, 2, 2) 的含义:
1 | 前两维 (3, 4) = tile 内部的坐标(每个 tile 是 3×4) |
取具体某个 tile:
1 | auto tile = local_tile(tensor, make_tile(Int<3>{}, Int<4>{}), make_coord(ti, tj)); |
可视化(6×8 矩阵切成 4 个 3×4 tile):
1 | 原始 6×8 矩阵: |
local_tile 的内部原理:把每个维度拆成 (tile_内部, tile_编号),stride = tile_size × 原始 stride。不拷贝数据。
reef博士:该函数是Tensor中用户可以使用到的重要的函数,可以通过tile方法对tensor进行分块,通过local_tile可以实现从大的tensor中切取tile块,并且通过coord进行块的选取,以下代码展示了将维度为MNK的张量按照2x3x4的小块进行划分,取出其中的第(1, 2, 3)块。

如上图所示,A Tensor表达了4行6列的行优先的数据,分块的tile大小为2x2, local_tile会将A矩阵按照tile的单位进行分块,然后根据坐标选取出(1, 1)位置的分块,如图则取出了(1,1)位置的tensor得到右下角的结果。
1 | Tensor tensor = make_tensor(ptr, make_shape(M, N, K)); |
第 5 节:make_tensor_like
1 | auto tensor = make_tensor(&data[0], make_layout(make_shape(Int<3>{}, Int<4>{}), |
创建一个和 tensor 同 shape/layout 的新 tensor,数据分配在栈上。
要求:shape 必须是静态的(Int<N>{}),因为编译期需要知道大小才能在栈上分配数组。
用途:在 kernel 中创建临时的寄存器 tensor,用于类型转换等。
第 6 节:Tensor的局部数据提取local_partition
local partition和local tile类似,现将大的Tensor按照tile大小进行分块,分块后每一块取出coordinate指定的元素形成新的块,代码形式和具体实例参考下图:

1 | Tensor tensor = make_tensor(ptr, ...); |
API 速查
| 函数 | 作用 |
|---|---|
make_tensor(ptr, layout) |
从指针+layout 创建 tensor |
make_tensor_like(tensor) |
创建同 layout 的新 tensor(栈上分配) |
tensor(i, j) |
二维访问 |
tensor(i, _) |
Slice:取第 i 行 |
tensor(_, j) |
Slice:取第 j 列 |
local_tile(tensor, tile, coord) |
按 tile 大小切分 |
print(tensor) |
打印元信息 |
print_tensor(tensor) |
打印所有值 |
size(tensor) |
总元素数 |
易错点总结
| 问题 | 解决方法 |
|---|---|
make_tensor(data, layout) 报错 |
必须传指针 &data[0],不能传数组名 |
make_tensor_like 报错 |
shape 必须是静态 Int<N>{},不能是动态 int |
local_tile 结果维度太多 |
正常,前半是 tile 内坐标,后半是 tile 编号 |
- 标题: cute(2)Tensor基础
- 作者: 鱿鱼圈
- 创建于 : 2026-06-07 22:13:32
- 更新于 : 2026-06-14 23:33:01
- 链接: https://yuyanqi.com/2026/06/07/cute(2)Tensor基础/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。