Skip to content

将元素寻址相关元数据和索引迁移到 int64_t #12

Description

@SnifferCaptain

Issue:将元素寻址相关元数据和索引迁移到 int64_t

背景

当前张量的 shape、stride、storage offset、元素坐标及大量算子循环使用 32 位 int。当张量元素数量或物理跨度超过 INT_MAX 时,可能出现:

  • stride 溢出
  • view offset 溢出
  • 构造或算子因 checkedIntSize() 被拒绝
  • broadcast、copy、reduce 等算子将 size_t 截断为 int
  • 大张量无法正确切片、遍历或序列化

需要将所有与“元素数量、元素位置、物理寻址”相关的类型迁移到 std::int64_t,使 64 位平台能够支持超过 INT_MAX 个元素或跨度的大张量。

类型规则

直接使用标准类型,不引入 index_textent_t 等类型别名。

使用 std::int64_t

  • shape extent
  • stride
  • storage offset
  • 元素坐标
  • 逻辑/物理线性索引
  • slice 的 start/end/step
  • repeat、split、unfold 等涉及元素数量的参数
  • element-wise 算子的循环索引和迭代空间
  • batch/view 等计算出的元素偏移

继续使用 int

  • axis
  • ndim/rank
  • axes 列表
  • permutation/order
  • 线程数
  • SIMD/GEMM tile 内部的小范围计数

继续使用 std::size_t

  • size()
  • nbytes()
  • elementSize()
  • 内存分配大小
  • 容器长度
  • memcpy 等字节数量参数

示例接口:

std::vector<std::int64_t> shape() const;
std::int64_t shape(int axis) const;

std::vector<std::int64_t> stride() const;
std::int64_t stride(int axis) const;

std::int64_t offset(const std::vector<std::int64_t>& coordinate) const;

YTensorBase slice(
    int axis,
    std::int64_t start,
    std::int64_t end,
    std::int64_t step = 1,
    bool autoFix = true
) const;

实现范围

1. Layout 元数据

修改 strided layout:

struct YMeta<YLayoutType::Strided> {
    std::int64_t offset = 0;
    std::vector<std::int64_t> shape;
    std::vector<std::int64_t> stride;
};

Nested layout 中涉及 shape、offset、stride 的字段同步迁移。

2. YTensorBaseYTensor

迁移:

  • 构造函数 shape 参数
  • shape()stride()offset()
  • toIndex()toIndex_()toCoord()
  • atData()atData_()
  • autoShape()
  • slice()
  • view()reshape()
  • repeat()
  • split()
  • unfold()
  • 工厂函数中的 shape 参数
  • 内部 stridedShape/Stride/Offset 接口

axis、ndim 和 permutation 保持 int

3. Strided 算子

检查并迁移以下模块中的元素索引传播链:

  • view
  • broadcast
  • copy/concat/split
  • reduction
  • matmul
  • contiguous/clone/cast
  • function 层的迭代坐标

不能只修改成员字段;所有中间表达式也必须以 64 位执行。例如避免:

int coordinate;
int stride;
std::int64_t offset = coordinate * stride; // 乘法已经在int中溢出

4. 并行循环

当前 parallelFor(int, int, ...)checkedIntSize() 会限制大张量。

需要:

  • 让通用 element-wise 迭代空间支持 std::int64_t
  • 或使用 64 位外层分块,再调用现有较小范围循环
  • 移除算子中仅为了调用 parallelFor 而执行的 checkedIntSize(tensor.size())

不能通过无检查的 size_t -> int64_tsize_t -> int 转换绕过限制。

5. Matmul/AVX2

不要求机械地把所有微内核参数改成 64 位。

推荐:

  • batch 数量和矩阵物理 offset 使用 int64_t
  • 外层迭代空间支持 64 位
  • tile 大小和微内核局部计数继续使用 int
  • 现有 GEMM 接口无法处理的超大单维度,应显式检查或分块
  • 禁止静默缩窄 m/n/k/lda/ldb/ldc

6. 溢出检查

保留并补全 checked arithmetic:

  • shape 乘积
  • contiguous stride 计算
  • coordinate * stride
  • base offset 与相对 offset 相加
  • element count 与 element size 相乘
  • 转换为 size_t
  • 转换为 ptrdiff_t
  • 转换到仍使用 int 的微内核参数

有符号 int64_t 溢出属于未定义行为,必须在乘法或加法前检查,而不是计算后判断。

负 stride 和反向 view 必须继续正确工作。

7. .yt 文件格式

当前 shape 按 32 位整数写入,需要升级格式:

  • 新格式使用明确的 int64_t shape 编码
  • 提升文件格式版本
  • 旧版本文件继续按 int32_t shape 读取并无损提升
  • 新格式不得依赖平台原生 int 宽度
  • 校验 shape extent 非负
  • 校验 shape 乘积和 payload 字节数
  • 更新 Python 转换脚本及文件格式文档

非目标

本任务不要求:

  • 将 axis、ndim、rank 改成 int64_t
  • 将所有 std::vector<int> 全局替换
  • 给 dtype、线程数或 tile 大小改类型
  • 引入大量整数类型别名或 strong type
  • 支持 32 位进程中的超大张量
  • 在测试中实际分配数 GB 内存

测试要求

增加不依赖巨大内存分配的边界测试:

  • 包含大于 INT_MAX extent 的零元素 shape
  • stride 大于 INT_MAX 的小 storage view
  • offset 大于 INT_MAX 的元数据计算
  • 负 stride/reversed view
  • shape、stride 和 offset 的 64 位公开 API
  • INT64_MAX 附近的 checked-add/checked-multiply
  • element count 乘 element size 的溢出
  • 64 位并行/分块循环边界
  • 新文件格式的 64 位 shape round-trip
  • 旧 32 位 shape 文件兼容读取
  • 非法或溢出的文件 shape 被拒绝
  • 现有普通张量、空张量、广播、切片、reduction、concat 和 matmul 测试不回归

验收标准

  • shape、stride、offset 和元素坐标不再受 32 位 int 限制。
  • 通用 element-wise、copy、broadcast 和 reduction 路径不再因元素总数超过 INT_MAX 而直接失败。
  • axis、ndim、axes 和 permutation 保持 int
  • size/nbytes 等内存容量接口保持 size_t
  • 不存在未经检查的 64 位到 32 位缩窄。
  • 不存在先以 32 位运算、再转换为 64 位的溢出表达式。
  • .yt 新旧格式兼容策略明确且有测试。
  • 全部现有测试及新增边界测试通过。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions