首页
/ CPython py_compile 模块完全指南:源码到字节码的预编译与缓存失效机制

CPython py_compile 模块完全指南:源码到字节码的预编译与缓存失效机制

2026-09-07 17:37:33作者:郁楠烈Hubert

导读

本文基于 CPython 官方文档 Doc/library/py_compile.rst,系统讲解标准库 py_compile 模块:它负责将 Python 源文件(.py)编译为字节码缓存文件(.pyc),既提供可在程序中调用的 compile() 函数,也支持 python -m py_compile 命令行方式批量预编译。读完本文,你将掌握 py_compile 全部 API 参数语义、PycInvalidationMode 三种缓存失效策略、错误处理与静默输出规则、CLI 的 stdin 输入技巧,并结合 CPython 仓库源码(Lib/py_compile.py)与官方测试(Lib/test/test_py_compile.py)理解其底层实现。本文基于当前 CPython 3.16 开发版源码编写,所列版本演进均以仓库文档与代码为准。


1. py_compile 的定位与适用场景

py_compile 模块为 Python 解释器提供"从源码生成字节码缓存文件"的能力。需要说明的是:Python 在导入模块时本身就会自动做字节码编译,并在权限允许时把字节码写入对应的 .pyc 文件,因此日常开发中通常并不需要手动调用它。

该模块真正的价值体现在共享安装场景:当一份 Python 程序被安装后供多个用户共同使用时,若某些用户对源码目录没有写权限,就无法在首次导入时生成并落盘 .pyc 缓存,结果每次启动都需重新做字节码编译,显著拖慢程序启动速度。因此在安装阶段(如安装器、构建脚本)用 py_compile 或它在目录级工具 compileall 预先生成全部字节码,是一种推荐做法。模块 docstring 中也明确指出:如果 Python 安装被多个用户共享,最好在安装时就对所有模块做字节码预编译(见 Lib/py_compile.py)。

模块导出四个公共名称(见 Lib/py_compile.py__all__):

名称 类型 用途
compile(file, ...) 函数 编译单个源文件并写出字节码缓存文件
main() 函数 命令行入口,被 python -m py_compile 调用
PyCompileError 异常类 编译出错时抛出的自定义异常
PycInvalidationMode 枚举类 字节码缓存失效模式(3.7 新增)

2. 核心 API:compile() 函数

2.1 函数签名与参数总览

py_compile.compile(file, cfile=None, dfile=None, doraise=False,
                   optimize=-1,
                   invalidation_mode=PycInvalidationMode.TIMESTAMP,
                   quiet=0)

其完整语义为:从 file 指定的源文件加载代码、编译为字节码,并写出 .pyc 缓存文件,随后返回实际写入的字节码文件路径(即最终使用的 cfile 值)。各参数详解如下:

参数 默认值 含义
file 待编译的源文件路径
cfile None 字节码输出路径;默认按 PEP 3147/PEP 488 规则生成(见 2.2)
dfile None 显示用文件名:指定后,回溯信息(traceback)中源码行归属的文件名用它替代真实的 file
doraise False 编译出错时是否抛出 PyCompileError(见 2.4)
optimize -1 优化级别,透传给内建 compile() 函数
invalidation_mode TIMESTAMP 缓存失效模式,需为 PycInvalidationMode 枚举成员(见第 4 节)
quiet 0 错误输出控制级别(见 2.4)

2.2 默认输出路径:PEP 3147 / PEP 488 语义

cfileNone,模块会调用 importlib.util.cache_from_source(file) 计算默认路径(见 Lib/py_compile.py)。典型结果遵循 PEP 3147/PEP 488 的 __pycache__ 布局:

/foo/bar/baz.py
    └── 编译后默认写到 /foo/bar/__pycache__/baz.cpython-32.pyc   # 以 Python 3.2 为例

即默认缓存文件放在源文件旁的 __pycache__/ 目录中,文件名形如 模块名.<解释器缓存标签>.pyc,其中 <解释器缓存标签> 对应 sys.implementation.cache_tag(如 cpython-316)。在传递了 optimize >= 0 时,路径会进一步体现优化级别(详见 2.3)。

需要特别留意的是在 PEP 3147 落地之前的历史行为:3.2 版之前默认输出路径是 file + 'c'(启用优化时为 file + 'o'),即直接写在源码同级目录下。3.2 版起才改为 PEP 3147 兼容的 __pycache__ 布局,见 Doc/library/py_compile.rstversionchanged:: 3.2 记录。

2.3 optimize 参数:控制优化级别与缓存路径

optimize 直接传给内建 compile(),有效值为 -1、0、1、2

  • -1(默认):使用当前解释器的优化级别——也就是解释器由 -O / -OO 命令行选项决定的级别;
  • 0:等价于常规解释器(__debug__ 为 True),不做优化;
  • 1:相当于 python -O,移除 assert 语句并丢弃 __debug__ 分支;
  • 2:相当于 python -OO,在级别 1 基础上进一步丢弃文档字符串。

从源码可以看到,当 optimize >= 0 时,缓存路径按优化级别区分生成(见 Lib/py_compile.py):

if optimize >= 0:
    optimization = optimize if optimize >= 1 else ''
    cfile = importlib.util.cache_from_source(file, optimization=optimization)
else:
    cfile = importlib.util.cache_from_source(file)

因此 optimize=2 会产出包含 opt-2 标记的缓存路径。官方测试 Lib/test/test_py_compile.py 专门验证了这一行为:

def test_optimization_path(self):
    # Specifying optimized bytecode should lead to a path reflecting that.
    self.assertIn('opt-2', py_compile.compile(self.source_path, optimize=2))

2.4 错误处理:doraise 与 quiet 的组合矩阵

doraisequiet 共同决定编译出错时的表现。编译失败的来源既可能是语法错误等"编译期异常",也可能来自文件读取(OSError 家族)。源码中的核心逻辑如下(见 Lib/py_compile.py):

try:
    code = loader.source_to_code(source_bytes, dfile or file, _optimize=optimize)
except Exception as err:
    py_exc = PyCompileError(err.__class__, err, dfile or file)
    if quiet < 2:
        if doraise:
            raise py_exc
        else:
            sys.stderr.write(py_exc.msg + '\n')
    return          # 注意:出错时会返回 None 而非路径

错误处理规则可总结为下表:

quiet doraise 出错行为
01 False(默认) sys.stderr 写入一行错误字符串,函数返回 None(不返回路径)
01 True 抛出 PyCompileError 异常
2 任意 完全静默:既不写消息也不抛异常,doraise 被忽略,直接返回 None

注意:quiet 并不区分 0 与 1 的 API 级差异——API 上只有"是否输出到 2 级"之别;quiet=1quiet=0compile() 内的行为一致。quiet=1 的"仅错误输出"语义实际作用于命令行入口(见第 6 节)。

一个务实的组合建议:调试 / CI 阶段用 doraise=True 让问题立刻以异常暴露;生产预编译脚本中用 doraise=False + quiet=2,让个别坏文件不至于中断整个批量流程,同时不污染输出流。

2.5 cfile 为符号链接或非普通文件时抛出 FileExistsError

当最终 cfile(无论显式给定还是计算所得)指向一个符号链接或非普通文件(如 /dev/null)时,compile() 会直接抛出 FileExistsError,即使该路径当前并不"存在"于常规意义上。源码(见 Lib/py_compile.py)与测试用例(见 Lib/test/test_py_compile.py)对两种情形均有明确实现:

if os.path.islink(cfile):
    msg = ('{} is a symlink and will be changed into a regular file if '
           'import writes a byte-compiled file to it')
    raise FileExistsError(msg.format(cfile))
elif os.path.exists(cfile) and not os.path.isfile(cfile):
    msg = ('{} is a non-regular file and will be changed into a regular '
           'one if import writes a byte-compiled file to it')
    raise FileExistsError(msg.format(cfile))

这一限制的根源在于 import 系统采用"先写临时文件再原子重命名"的方式落盘字节码(见 5.3 节)。若允许对符号链接或设备文件执行该流程,重命名会把这些路径原地替换成普通文件,从而悄悄破坏原有链接/设备语义。因此 py_compile 选择提前拒绝,作为对"import 一旦获准写入就会覆盖该路径"的预警。该语义自 Python 3.4 起随 importlib 写入语义一同引入。

2.6 内部编译管线速览

从源码可见 compile() 完整走的是 importlib 的官方管线(见 Lib/py_compile.py):

  1. 构造 SourceFileLoader('<py_compile>', file),用 get_data() 读取源码字节;
  2. 调用 loader.source_to_code(source_bytes, dfile or file, _optimize=optimize) 完成词法/语法解析与字节码生成,这一步等价于 compile() 内建函数路径;
  3. 失败则进入 2.4 节错误处理分支;
  4. 按失效模式计算元数据头:TIMESTAMP 模式读源文件 mtime 与 size,HASH 模式用 importlib.util.source_hash() 计算源码哈希(详见第 5 节);
  5. 为目标目录执行 os.makedirs(dirname)(目录已存在则吞掉 FileExistsError,见 Lib/py_compile.py);
  6. _calc_mode(file) 推算目标文件权限位,通过 _write_atomic() 原子写盘(见 Lib/importlib/_bootstrap_external.py),保证与 import 系统一致的文件创建/权限/写后改名语义(3.4 版变更);
  7. 返回 cfile 路径。

3. PyCompileError 异常类

PyCompileErrorcompile()doraise=True 时抛出的异常类型(文档见 Doc/library/py_compile.rst)。其构造约定为(见 Lib/py_compile.py):

raise PyCompileError(exc_type, exc_value, file[, msg])
  • exc_type:原始异常类型,其类型名可通过属性 exc_type_name 访问;
  • exc_value:原始异常值,可通过属性 exc_value 访问;
  • file:正在编译的文件名,可通过属性 file 访问,会进入错误消息;
  • msg:可选的自定义消息;缺省时自动生成一条与 py_compile 标准输出格式一致的默认消息,可通过属性 msg 访问。

值得注意的是其内部的消息构造对 SyntaxError 做了特殊处理:会拼接 traceback.format_exception_only() 的输出,并将其中的 File "<string>" 替换为 File "%s" % file(见 Lib/py_compile.py),从而让回溯指向真实源码文件而非内部字符串。非语法错误则统一为 "Sorry: <异常类型>: <异常值>" 格式。


4. PycInvalidationMode:字节码缓存的三种失效策略

4.1 背景与枚举定义

PycInvalidationMode 是 Python 3.7 起(对应 PEP 552)提供的 enum.Enum,用来声明"解释器如何判断 .pyc 缓存是否与源码保持一致"。该模式会以标志位的形式写入 .pyc 文件头(见 Lib/py_compile.py):

class PycInvalidationMode(enum.Enum):
    TIMESTAMP = 1
    CHECKED_HASH = 2
    UNCHECKED_HASH = 3

关于解释器在运行期究竟如何根据这些标志执行失效校验的完整说明,见官方文档 Doc/reference/import.rstCached bytecode invalidation 小节。

4.2 三种模式对比

枚举成员 缓存内容 运行期校验行为 适用场景
TIMESTAMP 源文件的修改时间戳 + 文件大小 将缓存中元数据与源文件元数据比对,不一致则重新生成 默认场景,开销最小
CHECKED_HASH 源文件内容的哈希 运行期对源文件重新计算哈希并比对,不一致则重新生成 需要精确校验、文件 mtime 可能被"抹平"的场景
UNCHECKED_HASH 源文件内容的哈希 只要缓存文件存在即假定有效,完全不校验 由 Python 之外的构建系统(如 Makefile)负责保证 .pyc 永远最新

文档与测试都对后两者的语义差异给出了精确定义:CHECKED_HASH 若校验失败会重新生成并写回新的 checked hash 缓存;UNCHECKED_HASH 则"存在即有效";官方还建议用 --check-hash-based-pycs 命令行开关覆盖 hash 类缓存的校验行为(见 Doc/reference/import.rst)。UNCHECKED_HASH 的存在正是为了构建系统场景:既然外部系统总能保证产物最新,运行期再做哈希无异于浪费(详见 Doc/library/py_compile.rst 的 attribute 说明)。

4.3 默认值如何决定:SOURCE_DATE_EPOCH 环境变量

compile()invalidation_mode 默认值并不是硬编码的 TIMESTAMP,而是依赖环境变量动态决定。文档明确的规则是(见 Doc/library/py_compile.rst):

  • 若设置了 SOURCE_DATE_EPOCH 环境变量,默认改为 PycInvalidationMode.CHECKED_HASH
  • 否则默认 PycInvalidationMode.TIMESTAMP

实现位于默认模式选择函数中(见 Lib/py_compile.py):

def _get_default_invalidation_mode():
    if os.environ.get('SOURCE_DATE_EPOCH'):
        return PycInvalidationMode.CHECKED_HASH
    else:
        return PycInvalidationMode.TIMESTAMP

SOURCE_DATE_EPOCH 是"可复现构建"生态的通用约定(值为自 Unix 纪元起的秒数),追求字节级可复现的构建需保证源码 mtime 稳定,而 TIMESTAMP 模式会把 mtime 写进缓存头从而破坏可复现性,因此一旦检测到该变量即切到基于内容哈希的 CHECKED_HASH。这一行为有明确的版本演变史:

  • 3.7 初版:只要设置了 SOURCE_DATE_EPOCH,就强制invalidation_mode 覆盖为 CHECKED_HASH(连显式传入的参数一并覆盖);
  • 3.7.2 起:环境变量不再覆盖显式传入invalidation_mode 参数,而是改为只影响其默认值。

测试侧,Lib/test/test_py_compile.py 通过 test_source_date_epoch 验证了这一点:设置了 SOURCE_DATE_EPOCH 时读回 .pyc 头部分类标志应为 0b11(CHECKED_HASH),未设置则为 0b00(TIMESTAMP)。该测试还通过 SourceDateEpochTestMeta 元类把整个测试基类分别在设/不设该变量的环境下各跑一遍(见 Lib/test/test_py_compile.py)。

4.4 失效模式对 .pyc 文件头的影响

不同模式不仅影响运行期行为,也直接改变写出的字节码文件头内容。参见 Lib/importlib/_bootstrap_external.py 中两个"代码到文件"的序列化函数:

  • _code_to_timestamp_pyc(code, mtime, source_size)(第 511 行起):写入 源文件 mtime 与 size
  • _code_to_hash_pyc(code, source_hash, checked=True)(第 521 行起):写入 8 字节源码哈希checked 布尔位区分 CHECKED 与 UNCHECKED。

compile() 内部分发逻辑为(见 Lib/py_compile.py):

if invalidation_mode == PycInvalidationMode.TIMESTAMP:
    source_stats = loader.path_stats(file)
    bytecode = importlib._bootstrap_external._code_to_timestamp_pyc(
        code, source_stats['mtime'], source_stats['size'])
else:
    source_hash = importlib.util.source_hash(source_bytes)
    bytecode = importlib._bootstrap_external._code_to_hash_pyc(
        code, source_hash,
        (invalidation_mode == PycInvalidationMode.CHECKED_HASH),
    )

运行期对应的哈希校验函数 _validate_hash_pyc()(见 Lib/importlib/_bootstrap_external.py)会将文件头第 8~16 字节与重新计算的源码哈希比对。测试 Lib/test/test_py_compile.py_classify_pyc() 验证了 CHECKED_HASH 产出标志 0b11、UNCHECKED_HASH 产出标志 0b1,与实际写入规则完全对应。


5. 实现细节:与 import 系统对齐的字节码写盘语义

5.1 为什么必须与 import 保持一致

自 Python 3.4 起,compile() 的缓存写盘改为完全复用 importlib 机制(见 Doc/library/py_compile.rst),因此文件创建/权限位/写后改名等语义与解释器导入模块时完全一致——这正是 2.5 节 FileExistsError 限制、以及多进程并发导入安全性的根因。相关原语全部来自 Lib/importlib/_bootstrap_external.py

  • _write_atomic(path, data, mode)(第 200 行起):临时文件 + 原子重命名;
  • _calc_mode(path)(第 370 行起):参照源文件推导目标权限位。

5.2 cache_tag 缺失时的降级路径

py_compile 还兼容了没有字节码缓存标签的实现环境。命令行入口 main() 中(见 Lib/py_compile.py):

cfilename = (None if sys.implementation.cache_tag
             else f"{filename.rpartition('.')[0]}.pyc")

即:sys.implementation.cache_tag 存在时走常规 __pycache__ 默认路径;否则回退到旧的"源码同名 + c 后缀"布局。测试类 Lib/test/test_py_compile.py 也模拟了该降级行为。

5.3 并发安全与权限继承

原子写盘采用"写入临时文件 → 重命名到目标路径"的方式,保证任意时刻读到的是完整文件,避免多进程同时写同一缓存时的半成品问题。权限方面则由 _calc_mode() 依据源文件推算,使生成缓存的属主/权限与 import 产出一致——这对共享安装场景尤其关键:预编译文件应可被所有读取方使用,而非仅属于首个编译它的用户。


6. 命令行接口:python -m py_compile

6.1 基本用法

模块本身可直接作为脚本运行,一次编译多个源码文件(文档见 Doc/library/py_compile.rst):

python -m py_compile file.py file2.py ...

CLI 行为要点:

  • 位置参数 <file> ... <fileN> 为待编译文件,不做目录递归搜索,只编译显式列出的文件——需要整棵目录树批量预编译时应改用 compileall
  • 字节码按常规方式(PEP 3147 __pycache__ 布局)缓存;
  • 只要有一个文件编译失败,退出状态即为非零
  • 3.2 版起支持 - 参数从标准输入读取文件清单(见 6.2);
  • 3.10 版起支持 -q, --quiet(见 6.3)。

6.2 从标准输入读取文件清单

当且仅当位置参数是单个 - 时,待编译文件列表改为从标准输入逐行读取:

find . -name '*.py' | python -m py_compile -
printf '%s\n' a.py b.py c.py | python -m py_compile -

实现上,main() 对输入行做 rstrip('\n') 后组装成文件名列表(见 Lib/py_compile.py)。这为与 findxargs 等外部工具串联提供了便捷管道。测试 Lib/test/test_py_compile.py 验证了 - 模式下返回码为 0 且字节码确实写出。

6.3 静默模式 -q / --quiet

CLI 支持 -q, --quiet 抑制错误输出。退出码语义不变:仍有文件编译失败时返回码为 1,但错误消息不再打印(见 Lib/py_compile.py):

try:
    compile(filename, cfilename, doraise=True)
except PyCompileError as error:
    if args.quiet:
        parser.exit(1)
    else:
        parser.exit(1, error.msg + '\n')
except OSError as error:
    if args.quiet:
        parser.exit(1)
    else:
        parser.exit(1, str(error) + '\n')

注意 CLI 内部始终以 doraise=Truecompile(),从而把错误统一收拢为 PyCompileErrorOSError 两类,再依据是否带 -q 决定是否打印并统一以状态码 1 退出。对应测试覆盖了两条路径:正常模式下 stderr 中应包含 SyntaxError、且消息以换行结尾;加 -q 后 stderr 完全为空、返回码仍为 1(见 Lib/test/test_py_compile.py)。

6.4 CLI 与 compile() 的对照小结

能力 CLI(python -m py_compile API(compile()
编译对象 显式列出的多个文件,或 - 读 stdin 单个文件
错误策略 出错即 stderr 提示并退出码 1(-q 则静默) doraise/quiet 组合决定
优化级别 跟随解释器启动参数(如 -O 通过 optimize 参数精确控制
目标路径控制 不可直接指定,走默认缓存布局 cfile 显式指定任意路径

6.5 与 compileall 的关系

需要编译目录树时,标准库配套提供 compileall 模块(同时可 python -m compileall <dir>),它内部基于 py_compile 递归遍历目录并批量编译(见本模块文档的 seealso 指引,Doc/library/py_compile.rst)。二者分工可概括为:py_compile 是"单文件原语",compileall 是"目录级批量工具"。


7. 完整可运行示例

7.1 基础编译与产物验证

import py_compile

# 编译并返回实际写入的字节码路径
result = py_compile.compile('/tmp/demo/baz.py')
print(result)
# /tmp/demo/__pycache__/baz.cpython-316.pyc

若当前解释器为无优化模式,生成的默认路径约形如 __pycache__/baz.cpython-316.pyc(缓存标签随解释器实现与版本号变化,如 cpython-316)。

7.2 显式控制输出路径与优化级别

# 写到自定义位置,并产出 opt-2 优化产物
py_compile.compile('/tmp/demo/baz.py',
                   cfile='/tmp/out/baz.pyc',
                   optimize=2)

# optimize 默认 -1:跟随当前解释器的 -O/-OO 设置
py_compile.compile('/tmp/demo/baz.py')

7.3 错误处理三种姿势

# ① 默认:写 stderr,返回 None
r = py_compile.compile('/tmp/bad.py')          # r is None

# ② 抛异常以快速定位
try:
    py_compile.compile('/tmp/bad.py', doraise=True)
except py_compile.PyCompileError as e:
    print(e.exc_type_name, e.file, e.msg)

# ③ 完全静默,适合批量预编译忽略坏文件
r = py_compile.compile('/tmp/bad.py', quiet=2) # 不报错、无输出,返回 None

7.4 可复现构建:显式指定失效模式

import py_compile
from py_compile import PycInvalidationMode

# 追求可复现构建:显式采用内容哈希 + 校验
py_compile.compile('/tmp/demo/baz.py',
                   invalidation_mode=PycInvalidationMode.CHECKED_HASH)

# 由外部构建系统保证缓存新鲜度:跳过运行期校验
py_compile.compile('/tmp/demo/baz.py',
                   invalidation_mode=PycInvalidationMode.UNCHECKED_HASH)

7.5 安装脚本中的典型用法

import py_compile
import sys

def precompile(module_files):
    """共享安装前预编译所有模块;个别坏文件只记录不中断。"""
    failed = []
    for path in module_files:
        try:
            py_compile.compile(path, doraise=True, quiet=1)
        except (py_compile.PyCompileError, OSError) as err:
            failed.append((path, err))
    return failed

if __name__ == '__main__':
    errors = precompile(sys.argv[1:])
    sys.exit(1 if errors else 0)   # 存在失败文件则向调用方暴露非零状态

8. 版本演进速查表

将文档 Doc/library/py_compile.rst 中的 versionchanged 记录整理如下:

版本 变更内容
3.2 默认 cfile 改为 PEP 3147 兼容的 __pycache__ 路径(原为 file+'c' / 'o');新增 optimize 参数;CLI 支持 - 从 stdin 读文件清单
3.4 字节码写盘改用 importlib 机制,文件创建/权限/写后改名语义与 import 一致;新增 cfile 为符号链接或非普通文件时抛 FileExistsError 的限制
3.7 新增 invalidation_mode 参数与 PycInvalidationMode(PEP 552);设置 SOURCE_DATE_EPOCH 时强制使用 CHECKED_HASH
3.7.2 SOURCE_DATE_EPOCH 不再覆盖显式传入的 invalidation_mode,改为仅决定其默认值
3.8 新增 quiet 参数
3.10 CLI 新增 -q, --quiet 选项

以上信息均可在仓库对应文档、源码与 Lib/test/test_py_compile.py 中交叉印证,是理解本模块行为边界的可靠依据。

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

项目优选

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