首页
/ CPython struct 模块完全指南:用格式字符串在 Python 值与二进制字节间互转

CPython struct 模块完全指南:用格式字符串在 Python 值与二进制字节间互转

2026-09-07 20:05:48作者:范垣楠Rhoda

struct 是 CPython 标准库中专门用于"把 Python 值打包成字节、再把字节解包成 Python 值"的模块。它在两个典型场景中不可替代:一是与外部数据源(文件、网络连接)按约定的二进制布局交换数据;二是在 Python 应用与 C 层之间按 C 结构体内存布局传输数据。读完本文你将掌握格式字符串的全部类型码与字节序控制字符、七个模块级函数与 Struct 类的完整用法,并理解其背后的 C 实现机制,能够直接写出跨平台、可复用的二进制序列化代码。

struct 模块的核心设计理念非常简单:用一串紧凑的**格式字符串(format string)**描述"数据长什么样",CPython 据此自动完成 Python 值与字节之间的转换。官方参考文档位于 Doc/library/struct.rst,纯 Python 的公共接口与文档字符串定义在 Lib/struct.py,而真正的实现是一个用 C 写的高性能加速模块 _struct,源码见 Modules/_struct.c

模块定位与两种使用模式

Lib/struct.py 可以看到,struct 本身只是一个"转发层":它把 calcsizepackpack_intounpackunpack_fromiter_unpackStructerror 等名字全部从底层的 _struct 加速模块再导出:

from _struct import *
from _struct import _clearcache  # noqa: F401
from _struct import __doc__  # noqa: F401

_struct 的 C 实现(Modules/_struct.c)把格式字符串的编译、内存读写等热点逻辑全部下沉到 C 层,因此性能远优于纯 Python 逐字段手工拼装字节的做法。

Modules/_struct.c 中可以看到它的核心数据结构:formatdef 结构体以"表驱动"方式为每一种格式字符登记了 size(字节宽)、alignment(对齐要求)以及一对 unpack/pack 函数指针;formatcode 则在编译格式字符串后记录每个字段的偏移量、尺寸和重复次数:

typedef struct _formatdef {
    const char *format;
    Py_ssize_t size;
    Py_ssize_t alignment;
    PyObject* (*unpack)(_structmodulestate *, const char *,
                        const struct _formatdef *);
    int (*pack)(_structmodulestate *, char *, PyObject *,
                const struct _formatdef *);
} formatdef;

typedef struct _formatcode {
    const struct _formatdef *fmtdef;
    Py_ssize_t offset;
    Py_ssize_t size;
    Py_ssize_t repeat;
} formatcode;

正是这样的设计,让"格式字符"与"具体机器的 C 类型大小/对齐"可以在运行时查表绑定,实现后续要讲的 native 与 standard 两种模式。

函数与异常

struct 模块定义了一个异常和六个模块级函数。所有接收 buffer 参数的函数,都要求参数对象实现缓冲区协议,并提供可读或可读写缓冲区;最常见的类型是 bytesbytearray,但任何能被看作字节数组、实现缓冲区协议的对象(如 memoryviewarray.array)都能直接使用,从而避免额外的拷贝

异常 error

在对各种场合(如格式错误、整数越界、缓冲区长度不足)抛出;异常的实参是一段描述错误的字符串。

>>> import struct
>>> struct.pack('>h', 99999)
Traceback (most recent call last):
  ...
struct.error: 'h' format requires -32768 <= number <= 32767

这条错误消息并非随手写死,而是由 C 实现中的 _range_error() 根据该字段的字节宽度动态计算的(见 Modules/_struct.c):对有符号整数,错误范围是 min ~ max;对无符号整数则是 0 <= number <= max

pack(format, v1, v2, ...)

返回一个 bytes 对象,其中依次存放按 format 打包后的 v1v2……参数的数量与取值必须和格式字符串的要求精确匹配,否则抛 struct.error

>>> struct.pack('>bhl', 1, 2, 3)
b'\x01\x00\x02\x00\x00\x00\x03'

pack_into(format, buffer, offset, v1, v2, ...)

把打包结果写入可写缓冲区 bufferoffset 位置,而不是新建 bytes。注意 offset 是必填参数;它可以是负数,此时从缓冲区末尾向前计数。

>>> import array
>>> buf = array.array('b', [0] * 10)      # 一个可写缓冲对象
>>> struct.pack_into('<I', buf, 0, 0x12345678)
>>> struct.unpack_from('<I', buf, 0)
(305419896,)

unpack(format, buffer)

formatbuffer 解包(通常与 pack(format, ...) 配对使用),返回值是元组——即使只包含一个元素也是如此。缓冲区的字节数必须恰好等于格式所需大小(即 calcsize(format) 的值)。

unpack_from(format, /, buffer, offset=0)

bufferoffset 位置开始解包;offset 默认是 0,可为负(从缓冲区末尾计数)。要求缓冲区在 offset 之后的剩余字节数至少为格式所需大小。解包得到的结果同样是元组。

unpack_from 在解析"前置了长度或魔数、后面紧跟多个定长记录"的报文时尤其好用,因为它允许只解包缓冲区中从指定偏移开始的子区,无需先切片。

iter_unpack(format, buffer)

返回一个迭代器,反复从 buffer 中读取等长的块并解包,直到耗尽全部内容。缓冲区的字节数必须是 calcsize(format) 的整数倍。每次迭代产生一个元组。

>>> struct.iter_unpack('>H', b'\x00\x01\x00\x02\x00\x03')
<iterator object at 0x...>
>>> list(struct.iter_unpack('>H', b'\x00\x01\x00\x02\x00\x03'))
[(1,), (2,), (3,)]

在 C 实现中,iter_unpack 由一个专用的迭代器类型 unpackiter_type 支撑(见 Modules/_struct.c),它实现了 __length_hint__ 以便让 list() 等消费方预分配容量,随后每次 __next__ 前进一个"格式大小"的步长。

该函数在 Python 3.4 中加入。

calcsize(format)

返回格式 format 对应的结构大小(也就是 pack(format, ...) 产出的 bytes 的字节数)。

>>> struct.calcsize('>bhl')
7

格式字符串

格式字符串描述了打包/解包时的数据布局,由**可选的前缀字符 + 一个或多个格式字符(类型码)**构成:

  • 前缀字符:控制整条数据的字节序、尺寸与对齐;
  • 格式字符:描述具体每个数据值的类型与宽度(见下文类型码表)。

字节序、尺寸与对齐

默认情况下(不写前缀或前缀为 @),C 类型按机器原生格式原生字节序表示,并按 C 编译器规则插入必要的填充字节以对齐。选择这一默认行为是为了让打包结果与对应 C 结构体的内存布局完全一致。

前缀字符的可选值如下表:

字符 字节序 尺寸 对齐
@ native(原生) native(原生) native(原生)
= native(原生) standard(标准) none(无)
< little-endian(小端) standard(标准) none(无)
> big-endian(大端) standard(标准) none(无)
! network(网络序,即大端) standard(标准) none(无)

若第一个字符不是上述任一前缀,则默认视为 @

关于字节序的直观例子:数字 1023(十六进制 0x3ff)的两种字节表示分别是——大端(>)下为 03 ff,小端(<)下为 ff 03

>>> import struct
>>> struct.pack('>h', 1023)
b'\x03\xff'
>>> struct.pack('<h', 1023)
b'\xff\x03'

原生字节序由宿主机决定:Intel x86、AMD64(x86-64)和 Apple M1 都是小端;IBM z 系列及许多老架构是大端。可以用 sys.byteorder 查看当前系统字节序:

>>> import sys
>>> sys.byteorder
'little'

尺寸与对齐的取值来源不同

  • native 尺寸与对齐由 C 编译器的 sizeof 表达式确定(_struct 的 native 表中直接使用 sizeof(short)_Alignof(int)sizeof(void *) 等编译期常量,见 Modules/_struct.c),并且始终与原生字节序绑定
  • standard 尺寸只取决于类型码本身(见下节类型码表中"Standard size"列)。

@= 的差异要特别注意:两者都使用原生字节序,但 = 的尺寸与对齐是标准化的(即各类型码取标准宽度、不做任何对齐填充)。

! 即网络字节序,按 IETF RFC 1700 的定义恒为大端。

模块没有提供"强制非原生字节序(强制字节交换)"的通用开关——需要非原生字节序时,请根据目标平台明确选用 <>

对齐规则的三条要点

  1. 填充字节只在相邻结构成员之间自动加入;编码后结构的开头与末尾不会自动加填充;
  2. 使用非原生尺寸/对齐的前缀(<>=!)时,不会插入任何填充;
  3. 若希望结构末尾也按某种类型的对齐要求补齐,可以在格式串末尾写上该类型码并附加重复次数 0(例如 'llh0l'),详见下文示例。

类型码全表

类型码描述单个值的 C 类型与 Python 类型映射。"Standard size"列给出的是使用标准尺寸(即格式串以 <>!= 开头)时该值占用的字节数;使用 native 尺寸时,大小取决于平台。

格式 C 类型 Python 类型 标准尺寸 备注
x pad byte(填充字节) 无对应值 (7)
c char 长度 1 的 bytes 1
b signed char int 1 (2)
B unsigned char int 1 (2)
? _Bool bool 1 (1)
h short int 2 (2)
H unsigned short int 2 (2)
i int int 4 (2)
I unsigned int int 4 (2)
l long int 4 (2)
L unsigned long int 4 (2)
q long long int 8 (2)
Q unsigned long long int 8 (2)
n ssize_t int (2)(3)
N size_t int (2)(3)
e _Float16 float 2 (4)(6)
f float float 4 (4)
d double float 8 (4)
Zf float complex complex 8 (10)
Zd double complex complex 16 (10)
s char[] bytes (9)
p char[] bytes (8)
P void * int (2)(5)

版本相关说明:

  • Python 3.3 起支持 nN 格式;
  • Python 3.6 起支持 e 格式;
  • Python 3.14 起曾加入 FD 格式;
  • Python 3.15 起支持 ZfZd 格式;
  • Python 3.16 起 FD 格式被标记为弃用(新代码应改用 Zf/Zd)。从 Modules/_struct.c 的 native 表可见,F/DZf/Zd 指向完全相同的 pack/unpack 函数,仅是兼容别名。

表注逐条详解

  • (1) ?_Bool? 对应 C99 起定义的 _Bool 类型;在标准模式下占 1 字节。
  • (2) 整数格式与 __index__:对任何整数格式码,若传入的不是整数但带有 __index__ 方法,则会先调用该方法把参数转成整数再打包(Python 3.2 起)。在 C 层,这一逻辑位于 get_pylong():先判断 PyLong_Check,失败后再检查 PyIndex_Check 并调用索引协议(见 Modules/_struct.c)。这意味着 numpy 整数、实现了 __index__ 的自定义类型等都可以直接打包。
  • (3) n/N 仅限 nativenssize_t)与 Nsize_t只在 native 尺寸下可用(默认模式或显式 @);标准尺寸下请按需选用其他整数格式。
  • (4) 浮点用 IEEE 754fde 打包出的表示无论平台自身的浮点格式如何,都分别采用 IEEE 754 binary32、binary64、binary16。
  • (5) P 仅限 nativePvoid * 指针宽度)只在 native 字节序下可用(默认或 @)。= 前缀虽然按宿主机选择端序,但 _struct 并不把 = 视为 native 顺序,因此 P 不可与 = 联用。
  • (6) e 半精度浮点:对应 2008 版 IEEE 754 标准引入的 binary16 "half precision"。它含 1 位符号、5 位指数和 11 位有效精度(显式存储 10 位),全精度下可表示约 6.1e-056.5e+04 之间的数。该类型在 C 编译器中支持不普遍(需编译器支持 C23 附录 H 的 _Float16);在典型机器上可用 unsigned short 存储,但不能直接参与数学运算。C 层对它的打包本质上也是按 2 字节宽度读写(见 Modules/_struct.ceh/H 同为 sizeof(short))。
  • (7) x 填充:打包时 x 插入一个 NUL 字节。
  • (8) p Pascal 字符串:在固定字节数(由 count 给出)内编码"短变长字符串":第 1 字节存字符串长度(与 255 取较小者),随后是字符串内容。若传入的字节串超过 count-1 字节,只保留前 count-1 字节;若短于 count-1,则用 NUL 补足到恰好 count 字节。解包时 p 会消费 count 字节,但返回的 bytes 对象永远不会超过 255 字节。打包时接受 bytesbytearray 参数。
  • (9) sc 的区别s 的 count 表示字节串长度而非重复次数。'10s' 表示单个 10 字节字符串 ↔ 单个 Python 字节串;而 '10c' 表示 10 个各自独立的单字节字符 ↔ 10 个独立的 bytes 对象(等价写法 cccccccccc)。count 缺省为 1。打包时字节串会被截断或用 NUL 补齐到指定长度;解包时得到的 bytes 恒为指定字节数。特例:'0s' 表示单个空字节串,而 '0c' 表示 0 个字符。打包时同样接受 bytes/bytearray
  • (10) Zf/Zd 复数:两个分量(实部、虚部)分别用 IEEE 754 binary32/binary64 表示,不受平台浮点格式影响。需要注意:尽管复数在 C 语言中属于可选特性,但这里无条件可用。按 C11 标准,每个 complex 类型由一个二元 C 数组表示,分别存放实部与虚部。F/D 仅作为 Zf/Zd 的兼容别名保留。

重复计数、空白与范围检查

类型码前可以加整数重复次数,例如 '4h''hhhh' 完全等价。

格式字符串之间的空白字符会被忽略,但 count 与其所属格式码之间不能有空白(否则 4 h 会被解析成独立的 4h 两个字段,通常导致错误)。

打包时若用整数格式(b B h H i I l L q Q)传入的值超出该格式的合法范围,会抛 struct.error(Python 3.1 之前部分整数格式是回绕并抛 DeprecationWarning,此后一律改为抛错,因此越界不会再静默产生错误的二进制数据)。

? 类型的返回值恒为 TrueFalse;打包时使用参数的真值;原生或标准 bool 表示中的 0/1 会被正确打包,解包时任何非零字节都视为 True

官方示例精读

下面的示例全部来自官方文档,可直接在交互式环境中运行验证。注意:native 字节序示例(@ 前缀或无前缀)的输出取决于平台与编译器,可能与读者本机的输出不同。

用大端序打包并解包三种不同宽度的整数

>>> from struct import *
>>> pack(">bhl", 1, 2, 3)
b'\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('>bhl', b'\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> calcsize('>bhl')
7

尝试打包超出字段范围的整数

>>> pack(">h", 99999)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
struct.error: 'h' format requires -32768 <= number <= 32767

sc 的区别演示

>>> pack("@ccc", b'1', b'2', b'3')
b'123'
>>> pack("@3s", b'123')
b'123'

解包结果赋名 / 包装成命名元组——实际解析网络二进制记录时的标准手法:

>>> record = b'raymond   \x32\x12\x08\x01\x08'
>>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)

>>> from collections import namedtuple
>>> Student = namedtuple('Student', 'name serialnum school gradelevel')
>>> Student._make(unpack('<10sHHb', record))
Student(name=b'raymond   ', serialnum=4658, school=264, gradelevel=8)

native 模式下类型码顺序影响结构大小(因为隐式填充,编译出的格式可能比字段"内容"更长);而标准模式完全由用户负责填充。下面这个例子在小端机器上运行,注意第一个 pack 在打包 '#' 之后自动补了 3 个 NUL 字节,把后续整数对齐到 4 字节边界:

>>> pack('@ci', b'#', 0x12131415)
b'#\x00\x00\x00\x15\x14\x13\x12'
>>> pack('@ic', 0x12131415, b'#')
b'\x15\x14\x13\x12#'
>>> calcsize('@ci')
8
>>> calcsize('@ic')
5

用末尾零重复计数对齐结构尾:假设平台 long 按 4 字节对齐,格式 'llh0l' 会在末尾补 2 个填充字节:

>>> pack('@llh0l', 1, 2, 3)
b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'

两大应用场景:native 格式与 standard 格式

struct 的两个主要应用领域会构建风格迥异的格式字符串:

  1. Python 与 C 代码(同一编译器构建的应用)之间的数据交换——使用 native 格式
  2. 遵循约定布局的跨应用/跨机器数据交换——使用 standard 格式

native 格式(原生格式)

当格式串要复刻本机 native 布局时,字节序与填充由编译器与机器架构决定。此时应使用 @ 前缀指明原生字节序与数据尺寸;内部填充字节通常由模块自动插入。为了让连续多个 chunk 正确对齐到字节边界,常常需要在格式串末尾使用一个零重复计数类型码来"凑整"。

在 64 位小端机器上:

>>> calcsize('@lhl')
24
>>> calcsize('@llh')
18

第二个格式串 @llh 在结构末尾没有被补齐到 8 字节边界(18 = 8 + 8 + 2,少了尾部对齐)。用零重复格式码解决:

>>> calcsize('@llh0l')
24

x 类型码也可以承担类似职责,但对 native 格式,更推荐零重复格式(如 '0l'),因为它能把末尾对齐与"此处无字段"的语义区分得更干净。模块默认就使用 native 字节序与对齐,但官方建议显式写出 @ 前缀,让意图一目了然。

standard 格式(标准格式)

当数据要越过当前进程边界(网络传输、落盘存储等)时,必须显式指定字节序、尺寸与对齐,绝不能假定对端与本地机器一致。例如:网络字节序是大端,而主流 CPU 多为小端。一旦布局被显式约定,代码就不再依赖运行平台的具体特性。

标准格式串的首字符一般用 <>(或 !);填充完全由程序员负责。此时零重复格式码不再起作用,需要补位时必须在需要处显式书写 x 填充字节。沿用上一节的例子:

>>> calcsize('<qh6xq')
24
>>> pack('<qh6xq', 1, 2, 3) == pack('@lhl', 1, 2, 3)
True
>>> calcsize('@llh')
18
>>> pack('@llh', 1, 2, 3) == pack('<qqh', 1, 2, 3)
True
>>> calcsize('<qqh6x')
24
>>> calcsize('@llh0l')
24
>>> pack('@llh0l', 1, 2, 3) == pack('<qqh6x', 1, 2, 3)
True

同样注意:以上结果在 64 位机器上成立,在不同机器上并不保证一致。例如在 32 位机器上,long 是 4 字节,结果完全不同:

>>> calcsize('<qqh6x')
24
>>> calcsize('@llh0l')
12
>>> pack('@llh0l', 1, 2, 3) == pack('<qqh6x', 1, 2, 3)
False

这组对照实验也直观说明了一条工程原则:跨进程/跨机器传输务必使用 standard 格式并自管填充

Struct 类:编译一次,反复使用

class struct.Struct(format)

返回一个按照格式串 format 读写二进制数据的 Struct 对象。相比每次调用模块级函数,先创建一次 Struct 对象再反复调用其方法更高效,因为格式串只被编译一次。

不过在多数场景下二者差异不大:传给模块级函数的最近使用的若干格式串的编译结果会被缓存,因此程序里格式串种类不多时无需特意复用 Struct 实例。这一缓存正是 _struct 模块状态里的 cache 字典(见 Modules/_struct.c),模块级函数通过 cache_struct_converter 从缓存中取编译对象、未命中才新建,Lib/struct.py 中再导出的 _clearcache() 则用于清空该缓存。

Struct 实例的 API 与模块级函数一一对应,只是使用编译好的格式:

方法 说明
pack(v1, v2, ...) 等价于模块级 pack,且 len(result) 恒等于 self.size
pack_into(buffer, offset, v1, v2, ...) 等价于模块级 pack_into
unpack(buffer) 等价于模块级 unpack;缓冲区字节数必须等于 self.size
unpack_from(buffer, offset=0) 等价于模块级 unpack_from;从 offset 起的剩余字节数必须至少为 self.size
iter_unpack(buffer) 等价于模块级 iter_unpack;缓冲区字节数必须是 self.size 的整数倍(3.4 起)

实例属性:

  • format:构造该对象所用的格式字符串(Python 3.7 起该属性类型是 str 而非 bytes);
  • size:格式串对应的结构大小(即 pack 方法产出 bytes 的长度)。

Python 3.13 起 Structrepr() 显示为构造表达式形式:

>>> struct.Struct('i')
Struct('i')

性能对比示例

>>> from struct import Struct
>>> s = Struct('<10sHHb')          # 编译一次
>>> s.size
15
>>> s.pack(b'raymond   ', 0x1232, 0x0108, 8)
b'raymond   \x32\x12\x08\x01\x08'
>>> s.unpack(b'raymond   \x32\x12\x08\x01\x08')
(b'raymond   ', 4658, 264, 8)
>>> list(s.iter_unpack(b'raymond   \x32\x12\x08\x01\x08' * 2))
[(b'raymond   ', 4658, 264, 8), (b'raymond   ', 4658, 264, 8)]

C 层实现要点补充

把官方文档与 Modules/_struct.c 对照阅读,可以更准确地理解模块行为背后的机制:

  • 表驱动翻译:每种格式字符的 pack/unpack 都是独立的小函数,native 模式用小端机器上会被编译器优化掉的 memcpy 中间变量读取(native 例程注释说明见 Modules/_struct.c),而大端/小端模式则逐字节移位拼装(例如 bu_intx = (x<<8) | *bytes++ 循环,见 Modules/_struct.c),从而保证无论宿主机字节序如何都能产出正确结果。
  • 范围校验:对越界整数,_range_error() 依据字段字节宽度动态构造错误消息并抛 StructError
  • __index__ 协议:非整数输入先经 get_pylong() 尝试通过索引协议转换为整数,这也是文档注 (2) 的行为来源。
  • 迭代器实现iter_unpack 返回的迭代器对象实现了 __length_hint__ 与标准的 tp_iternext,配合预取逻辑让逐块解包接近纯 C 速度。
  • 两套类型表:native 模式使用基于 sizeof/_Alignofnative_table;standard 模式则把 hilqfd 等统一固定为 2/4/4/8/4/8 等标准宽度,这正是 @= 语义差异的根源。

官方测试与验证入口

如果希望在自己的环境里快速验证本文所有行为,可以直接运行 CPython 的 struct 回归测试套件:

./python -m test test_struct

对应的测试源码为 Lib/test/test_struct.py,覆盖了各字节序组合、native/standard 尺寸差异、边界值溢出、pack_into/unpack_from 的偏移语义、iter_unpackStruct 类的缓存与清理等全部行为,是理解格式串细节的最佳第二手资料。

相关标准库与生态对比

官方文档特别提示,以下模块也使用相似但略有不同的类型码(读取二进制数据时可作为 struct 的替代或补充):

  • Doc/library/array.rst:同质数据的紧凑二进制存储,类型码风格与 struct 相近;
  • Doc/library/ctypes.rst:直接在 Python 中声明并操作 C 结构体(Fundamental data types),适合"把 Python 值映射成真正的 C struct"的场景;
  • Doc/library/json.rstDoc/library/pickle.rst:分别提供基于文本的自描述格式与 Python 对象序列化,二者都面向"紧凑的定长二进制协议"。

需要把握的选择原则:当你要对接的是文件格式或网络协议中约定好的定长二进制结构时,struct(配合 </> 前缀自管字节序与 x 填充)几乎是标准答案;当你要精确复刻某台机器上 C 结构体的内存布局时,则用默认或 @ 前缀的 native 模式,并结合 Doc/library/ctypes.rst 中的 ctypes 数据类型做交叉验证。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391