CANN PyPTO 数据类型字节数查询:pypto.bytes_of 用法、返回值与底层实现解析
2026/9/18 12:35:15 网站建设 项目流程

CANN PyPTO 数据类型字节数查询:pypto.bytes_of 用法、返回值与底层实现解析

【免费下载链接】pyptoPyPTO(发音: pai p-t-o):Parallel Tensor/Tile Operation编程范式。项目地址: https://gitcode.com/cann/pypto

导读

在基于 CANN PyPTO(Parallel Tensor/Tile Operation 编程范式)开发算子时,无论是手工分配 Host 内存、计算 Tensor 总字节数,还是判断向量运算的对齐步长,都绕不开"某个数据类型占几个字节"这一基础问题。pypto.bytes_of正是 PyPTO 提供的专用查询接口:传入一个pypto.DataType,即可获得该类型单个元素的存储字节宽度。本文以 PyPTO 官方 API 文档 pypto.bytes_of 为主线,结合仓库源码与单测用例,完整讲解其函数原型、参数返回值、各数据类型速查表、调用示例,以及从 Python 层到 C++ 层的实现原理,并展示它在框架内存计算、形状推断中的典型用途。

产品支持情况

pypto.bytes_of在以下产品形态上均受支持(与 DataType 枚举保持一致):

产品形态支持情况
Ascend 950PR / Ascend 950DT支持
Atlas A3 训练系列产品 / Atlas A3 推理系列产品支持
Atlas A2 训练系列产品 / Atlas A2 推理系列产品支持

功能说明与函数原型

pypto.bytes_of的功能非常简单明确:返回某个数据类型所占的 Byte(字节)大小。这里的"大小"指的是该数据类型单个元素在内存中占用的字节宽度,返回值类型为 Python 的int

函数原型如下:

bytes_of(dtype: pypto.DataType) -> int

其中形参dtype的类型是pypto.DataType,即 PyPTO 框架中用于表示 Tensor 数据类型的枚举类。关于DataType枚举所涵盖的全部类型(整数、浮点数、布尔值等)及其字节/位宽定义,可参见 DataType 文档。

参数说明

参数名输入/输出说明
dtype输入需要查看 Byte 大小的数据类型,取值为pypto.DataType枚举或其常量别名(如pypto.DT_FP32)。

返回值说明

返回该数据类型所占的 Byte 大小,类型为int

各数据类型字节数速查表

将文档给出的 DataType 常量定义 与仓库源码 framework/include/tilefwk/data_type.h 中的DATA_TYPE_ALL描述表(DTYPE_DESC(name, byte, bit, is_float, type, cann_type),第二列即字节数)对照,可以得到 PyPTO 全部支持数据类型的字节数速查表:

数据类型常量说明bytes_of 返回值
DT_INT44 位有符号整数(按字节单元存储)1
DT_INT88 位有符号整数1
DT_INT1616 位有符号整数2
DT_INT3232 位有符号整数4
DT_INT6464 位有符号整数8
DT_FP88 位浮点数1
DT_FP1616 位半精度浮点数2
DT_FP3232 位单精度浮点数4
DT_BF1616 位 Brain Float 格式2
DT_HF44 位 Half Float 格式(按字节单元存储)1
DT_HF88 位 Half Float 格式1
DT_UINT88 位无符号整数1
DT_UINT1616 位无符号整数2
DT_UINT3232 位无符号整数4
DT_UINT6464 位无符号整数8
DT_BOOL布尔类型1
DT_DOUBLE64 位双精度浮点数8
DT_FP8E4M38 位浮点数(4 位指数,3 位尾数)1
DT_FP8E5M28 位浮点数(5 位指数,2 位尾数)1
DT_FP8E8M08 位浮点数(8 位指数,0 位尾数)1
DT_FP4_E2M1X2MXFP4 格式,双元素打包(2 位指数 1 位尾数)1
DT_FP4_E1M2X2MXFP4 格式,双元素打包(1 位指数 2 位尾数)1
DT_FP4_E2M14 位浮点数(2 位指数,1 位尾数)1
DT_FP4_E1M24 位浮点数(1 位指数,2 位尾数)1

注意:表中有多类 4 位(4-bit)数据格式(如DT_INT4DT_HF4DT_FP4_E2M1DT_FP4_E1M2)。它们虽然位宽只有 4 位,但bytes_of返回的存储单元字节数为 1。这与 C++ 层BytesOf的实现语义一致——该函数返回"表示一个元素所用的字节宽度",用于内存单元、对齐与寻址计算,不能直接用来计算打包后的 Tensor 数据总大小(详见 实现原理 与 使用注意事项)。

调用示例

文档给出的最小调用示例如下:

pypto.bytes_of(pypto.DT_FP32)

结果示例如下:

输出: 4

在实际开发中,更常见的用法是配合其他常量批量查询,或把返回值用于内存分配计算。例如:

import pypto # 单类型查询 print(pypto.bytes_of(pypto.DT_FP32)) # 输出: 4 print(pypto.bytes_of(pypto.DT_INT64)) # 输出: 8 # 批量查询,构造 {类型: 字节数} 映射 dtypes = [pypto.DT_INT8, pypto.DT_FP16, pypto.DT_FP32, pypto.DT_BF16] bytes_map = {dt: pypto.bytes_of(dt) for dt in dtypes} print(bytes_map) # 输出: {DataType.DT_INT8: 1, DataType.DT_FP16: 2, DataType.DT_FP32: 4, DataType.DT_BF16: 2}

单测用例验证

仓库的单测 python/tests/ut/interface/test_enum.py 对pypto.bytes_of的全部常见类型返回值做了断言验证,可直接作为权威参考:

assert pypto.bytes_of(pypto.DT_INT4) == 1 assert pypto.bytes_of(pypto.DT_INT8) == 1 assert pypto.bytes_of(pypto.DT_INT16) == 2 assert pypto.bytes_of(pypto.DT_INT32) == 4 assert pypto.bytes_of(pypto.DT_INT64) == 8 assert pypto.bytes_of(pypto.DT_FP8) == 1 assert pypto.bytes_of(pypto.DT_FP16) == 2 assert pypto.bytes_of(pypto.DT_FP32) == 4 assert pypto.bytes_of(pypto.DT_BF16) == 2 assert pypto.bytes_of(pypto.DT_HF4) == 1 assert pypto.bytes_of(pypto.DT_HF8) == 1 assert pypto.bytes_of(pypto.DT_FP8E4M3) == 1 assert pypto.bytes_of(pypto.DT_FP8E5M2) == 1 assert pypto.bytes_of(pypto.DT_FP8E8M0) == 1 assert pypto.bytes_of(pypto.DT_UINT8) == 1 assert pypto.bytes_of(pypto.DT_UINT16) == 2 assert pypto.bytes_of(pypto.DT_UINT32) == 4 assert pypto.bytes_of(pypto.DT_UINT64) == 8 assert pypto.bytes_of(pypto.DT_BOOL) == 1 assert pypto.bytes_of(pypto.DT_DOUBLE) == 8

实现原理:Python 层到 C++ 层的完整调用链

pypto.bytes_of虽然对外是一个纯 Python 接口,但其实际计算发生在 C++ 侧。从源码结构看,完整调用链分为三层:

1. Python 封装层

接口定义位于 python/pypto/_utils.py,其 docstring 给出了与官方文档一致的用法说明,函数体则直接透传给底层绑定接口:

def bytes_of(dtype: DataType) -> int: """return the number of bytes of the current datatype Parameters ---------- dtype: pypto.DataType datatype to be determined the number of bytes Returns ------- int: the size of bytes the datatype contains """ # implementation return pypto_impl.BytesOf(dtype)

pypto_impl是 C++ 侧通过 pybind11 导出的底层模块,其类型签名声明在 python/pypto/pypto_impl/init.pyi:

def BytesOf(t: DataType) -> int: ...

2. pybind11 绑定层

绑定注册位于 python/src/bindings/controller.cpp:

m.def("BytesOf", [](DataType t) { return BytesOf(t); });

这里把 C++ 命名空间中的BytesOf函数直接暴露给 Python,接收DataType枚举值,返回其字节数。

3. C++ 核心实现

真正的字节数来源是 framework/include/tilefwk/data_type.h 中的内联函数BytesOf。它通过DTYPE_DESC宏展开DATA_TYPE_ALL表,逐一返回每个类型声明的 byte 字段:

// Returns the byte width used to represent one element. Do not use it to calculate packed tensor data size. inline size_t BytesOf(DataType t) { switch (t) { #define DTYPE_DESC(name, byte, bit, is_float, type, cann_type) \ case name: \ return byte; DATA_TYPE_ALL #undef DTYPE_DESC default: throw std::invalid_argument("Unknown DataType"); } }

值得留意的是注释中的关键约束:"Returns the byte width used to represent one element. Do not use it to calculate packed tensor data size."(返回表示一个元素所用的字节宽度,不要用它计算打包后的 Tensor 数据大小)。这正是 4-bit 类型返回 1 而非 0.5 的原因——该值代表寻址/存储单元宽度,而非严格的位宽换算结果。

如果确实需要计算"元素个数 × 位宽换算出的数据大小",同头文件还提供了DataSizeOf(numel, t)(framework/include/tilefwk/data_type.h),其定义为numel * BitsOf(t) / 0x8,与BitsOf配合使用:

// The caller must ensure that the total number of bits is byte aligned. inline int64_t DataSizeOf(int64_t numel, DataType t) { return numel * BitsOf(t) / 0x8; }

在框架中的典型应用场景

BytesOf(以及 Python 侧的bytes_of)在 PyPTO 框架内部被大量使用,主要集中在以下几类场景,理解这些用法有助于在自定义算子开发中复用同样的计算模式:

1. 内存大小计算

最直接的用途是"单元素字节数 × 元素个数 = 数据总字节数"。例如 framework/src/interface/interpreter/communication.cpp 中计算通信数据槽大小:

size_t slotSize = BytesOf(dataType) * std::accumulate(shape.begin(), shape.end(), 1, std::multiplies<size_t>());

同理,framework/src/cost_model/simulation/arch/PipeSimulatorFast.cpp 在性能仿真中通过shapeSize * BytesOf(dtype)计算访问总字节数。

2. 对齐与 tile 形状推断

在向量/矩阵运算中,常常需要"每多少个元素能凑满一个固定字节块",此时用BLOCK_SIZE / BytesOf(dtype)即可求出。例如 framework/src/passes/tensor_graph_pass/cube_tile_setting.cpp:

uint64_t elePerRepeat = BYTES_PER_REPEAT / BytesOf(static_cast<DataType>(inputType));

framework/src/interface/operation/vector/binary_scalar.cpp 中同样以BLOCK_SIZE / BytesOf(...)计算对齐后的元素数。

3. 数据类型转换时的形状换算

在 cast、pack 等涉及 dtype 变换的算子中,需要通过字节数换算形状。例如 framework/src/interface/operation/operation_impl.cpp 中计算目标 Tensor 尾部维度扩展倍数:

float factor = (float)BytesOf(originDType) / (float)BytesOf(dstDataType); auto changedDim = validShape[validShape.size() - 1] * BytesOf(originDType) / BytesOf(dstDataType);

4. 内存复用合法性与约束校验

在内存复用 Pass 中,会先比较源/目标缓冲区的元素字节数是否一致,以判断复用是否合法,如 framework/src/passes/block_graph_pass/memory_reuse/merge_src_dst_buffer.cpp。

使用注意事项

  1. 返回的是存储单元字节数,不是严格位宽:对 4-bit 类型(DT_INT4DT_HF4DT_FP4_E2M1DT_FP4_E1M2),bytes_of返回 1(存储/寻址单元),而不是 0.5。若需要按位宽精确换算数据总字节数,应使用 C++ 层的BitsOf+DataSizeOf语义。
  2. 输入必须是合法DataTypedtype参数类型为pypto.DataType。底层 C++ 实现对未知类型会抛出std::invalid_argument,因此请从 python/pypto/enum.py 导出的常量别名(如DT_FP32DT_INT32)或DataType枚举成员中取值。
  3. 产品差异:不同硬件产品支持的DataType集合有差异。根据 DataType 文档,Atlas A2/A3 系列产品不支持DT_FP8E4M3DT_FP8E5M2DT_FP8E8M0,Ascend 950PR/Ascend 950DT 支持全部类型。在目标产品上使用前请先确认类型可用性。
  4. 常用类型可直接记忆:1 字节(DT_INT8/DT_UINT8/DT_BOOL/8 位浮点类)、2 字节(DT_INT16/DT_FP16/DT_BF16)、4 字节(DT_INT32/DT_FP32)、8 字节(DT_INT64/DT_UINT64/DT_DOUBLE),与主流计算框架的 sizeof 语义一致,便于日常心算校验。

相关文档

  • pypto.bytes_of 官方 API 文档
  • DataType 枚举与常量定义
  • Tensor API 数据类型模块索引
  • Tensor API 总索引

【免费下载链接】pyptoPyPTO(发音: pai p-t-o):Parallel Tensor/Tile Operation编程范式。项目地址: https://gitcode.com/cann/pypto

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询