Page 107 - 《软件学报》2025年第7期
P. 107
3028 软件学报 2025 年第 36 卷第 7 期
发生的逻辑缺陷.
● 张量形状错误. 这类缺陷是指与张量形状 (shape) 或布局 (layout) 相关的问题. 张量的形状与布局对模型的
性能起着重要的作用, 其中张量形状代表了每个维度中的元素数量, 而布局则描述了张量在内存中的表示方式 [7] .
而且这类缺陷大部分发生在张量形状匹配、张量形状转换、张量形状推理、数据布局转换等操作过程中.
● API 误用. 这类缺陷主要源于开发者对 API 的理解或使用不当而产生. 具体表现为在编程过程中错误地选
择了 API、运用了不恰当的参数、在 API 使用过程中遗漏或过度进行了条件检查, 以及不必要或缺失的 API 调用
等情况.
● 类型错误. 这类缺陷包含类型转换和类型推理等类型相关问题. DL 编译器以计算图为核心, 其中节点
(node) 代表深度学习运算符 (operator), 而边 (edge) 则代表张量数据 (tensor). 此类别包含 3 个子类. (1) 节点类型错
误: 这个类别是指涉及节点类型定义或使用的问题. 在 DL 编译器中, 每个节点的输入可以是 0 个或多个张量, 输
出为一个或多个张量. (2) 张量类型错误: 这个类别是指涉及张量数据类型的问题. 张量是一个包含单一数据类型
元素的多维数组 (或称为多维矩阵), 用于表示深度学习中的数据和参数. (3) 传统数据类型错误: 这个类别是指涉
及 DL 编译器中除了节点和张量之外, 还使用到的常规数据类型的问题. 这些常规数据类型包括传统软件系统中
广泛使用的整型、浮点型、字符串等, 它们用于描述编译器内部状态、配置参数等.
● 异常处理错误. 此类缺陷是对异常情况的错误管理. 包括在理应触发异常的情形下, 编译器未能正确抛出异
常; 或者在正常情况下错误地抛出了异常. 同时还包括提供不准确或有误导性的异常信息, 使得调试和故障排除变
得困难.
● 配置错误. 该类型的缺陷是由 DL 编译器中的错误的配置选项引起的, 例如 CmakeLists.txt 文件的错误配置
信息.
● 赋值错误. 这类缺陷包括变量的错误初始化或赋值, 包括变量在使用前未进行声明或初始化就直接被引用,
或者变量被赋予了与预期不符的值.
● 并发问题. 此类缺陷涉及面向并发结构 (比如, 线程、临界区、锁) 的错误操作. 如死锁, 线程过多导致内存
溢出等.
● 不兼容. 此类缺陷是由 DL 编译器内部各个组件之间或 DL 编译器与第三方库 (例如, PyTorch 和 cuDNN)
之间的接口、功能或规范不匹配造成的. 不兼容缺陷通常与技术差异、版本不匹配、缺少必要的支持等因素密切
相关.
● 数值计算错误. 这类缺陷包括错误的数值类计算或使用, 例如不正确的使用运算符或操作数、非法除零、
缺少操作符或操作数等.
● 注册问题. 此类缺陷包括头文件的缺失或者错误引入, API 或者类的属性缺少注册时直接调用.
● 拼写错误. 这类缺陷是由于开发人员粗心导致的代码拼写错字, 比如将变量名“annotations”误写为“annotation”.
● 其他. 当缺陷的根因不常见, 并且不属于上述任何一类时, 本文将其归纳为此类别.
注册问题为本文识别出来的 DL 编译器缺陷根因, 此类缺陷主要因为缺少 API 注册而直接调用而导致的. 14
个此类缺陷中有 12 个出现在 TVM 中, 占比 85.71%. 分析发现, 这类缺陷与 TVM 中复杂的双向跨语言 API 调用
密切相关. 具体而言, TVM 使用外部函数接口 (FFI) 实现 Python 和 C++代码双向调用功能, API 跨语言调用需要
先注册再调用. 缺少注册而直接调用跨语言声明的 API 将会导致程序崩溃. 尽管这个根因是新识别的根因, 但在
Shen 等人 [8] 收集的缺陷中已包含了 5 个此类缺陷, 由于数量不够显著, 被归纳为其他. 除了注册问题以外, 其他缺
陷根因类别都已经被已有工作识别出来的, 因此, DL 编译器迭代更新几乎不会引入新的缺陷类别.
发现 1. 尽管 DL 编译器经历了长时间、大幅度迭代更新, 但缺陷根因的类别已近乎被全面识别.
4.1.2 根因分布情况
图 2 描述了 DL 编译器不同根因的缺陷数量分布对比情况. 其中旧数据 (图的左半部分) 是指已有工作 [8] 中研
究的 603 个早期 DL 编译器缺陷, 新数据 (图的右半部分) 是指本文研究的 613 个近期被修复的 DL 编译器缺陷.
从图中可以看出, 逻辑错误是当下 DL 编译器最常见的缺陷根因. 118 个此类缺陷中, 包括 73 个是由错误的优化代

