图是“拓扑 + 类型 + 形状“的世界

概述

图是"拓扑 + 类型 + 形状"的世界

这句话是理解 AI 编译器"图视角"的核心纲领。

它并不是在说图里没有"数值",而是在强调:

  • 在图编译器(Graph Compiler)这个层面,它完全无视具体的数据值(比如像素是 0.5 还是 0.8)
  • 只关心描述数据的"元数据"和描述计算的"骨架"。

通俗比喻

假设图视角是一家 中央厨房的调度 中心,它负责指挥整个烹饪流程。

  • 拓扑 = 菜谱步骤的依赖关系(必须先洗菜,才能切菜;必须先切菜,才能炒菜)。调度中心不看菜切得漂不漂亮,只看"谁依赖谁"。

  • 类型 = 食材的品种分类(这是肉、这是蔬菜、这是调料)。调度中心不关心这块肉是猪肉还是牛肉(具体值),但必须知道是肉(要用肉刀)还是菜(要用菜刀)。

  • 形状 = 食材的分量和容器大小(这是 1 斤肉装在大盆里,那是 2 两葱花装在小碟里)。调度中心根据这个决定用什么锅炒、炒多久。

调度中心绝对不关心 "这块肉上的花纹长什么样"、"这棵白菜重多少克"(具体数值),它只关注数据(食材)的流向、类型和尺寸,以此来决定如何最高效地安排流水线。


例子:图编译器如何"看"代码

假设我们有一个简单的 PyTorch 模型片段:Conv2d -> BatchNorm -> ReLU

1. 图编译器"看到"的抽象表示

图编译器不关心输入图片是猫还是狗,它只构建如下 DAG:

text 复制代码
输入 (placeholder)
  │  形状: [1, 3, 224, 224]  (类型: fp32)
  ▼
Conv2d 节点
  │  权重形状: [64, 3, 7, 7] (类型: fp32)
  │  输出形状: [1, 64, 112, 112] (类型: fp32)  ← 中间张量 A
  ▼
BatchNorm 节点
  │  参数: γ, β (类型: fp32)
  │  输出形状: [1, 64, 112, 112] (类型: fp32)  ← 中间张量 B
  ▼
ReLU 节点
  │  输出形状: [1, 64, 112, 112] (类型: fp32)  ← 最终输出
  ▼

2. 拆解"拓扑 + 类型 + 形状"如何驱动优化

① 拓扑(依赖关系)告诉编译器"能不能融"

图编译器看拓扑:ReLU 只依赖 BatchNorm,BatchNorm 只依赖 Conv,且它们是一对一的线性关系(没有别的节点使用 中间张量 A)。

这三个节点可以融合(Fusion)!因为中间结果只有这一个"消费者",不需要存回内存给别人用。

② 形状(大小维度)告诉编译器"值不值得融"

图编译器看形状:中间张量 A 的大小是 1, 64, 112, 112,即 1 * 64 * 112 * 112 = 802,816 个元素(约 3.2 MB)。

如果不融合,这 3.2 MB 要写回 DRAM(主存),再读出来给 BN,成本极高(访存墙)。由于形状巨大,融合收益极高,必须融。

③ 类型(数据精度)告诉编译器"用什么指令融"

图编译器看类型:三个节点的数据类型都是 fp32(单精度浮点)。

既然类型一致,融合后的 Kernel 内部统一使用 SIMD 浮点向量指令(如 AVX2 的 vmulps)。如果类型是 int8,则会触发生成专用的低精度矩阵乘指令(如 VPMADDUBSW)。

对比:如果"类型"或"形状"变了,图编译器的决策会截然不同

场景 拓扑(依赖) 类型 形状 图编译器(调度中心)的决策变化
原始场景 Conv → BN → ReLU(链式) fp32 1,64,112,112(大) 融合:节省大量 DRAM 流量。
场景 A Conv → BN → ReLU(链式) fp32 1,64,7,7(小) 不融合或不强求:中间张量只有 12 KB,访存成本低,融合带来的指令调度开销可能大于收益。
场景 B Conv → BN → 输出给 ReLU 和 另一个分支) fp32 1,64,112,112(大) 不融合:拓扑显示中间张量有两个消费者,如果融合进 ReLU,另一个分支就拿不到数据了,必须存回内存。
场景 C Conv → BN → ReLU(链式) 中间转为 int8 1,64,112,112(大) 强行融合但改变内核:为了省访存依然融合,但内部循环会插入量化(Quantization)指令,将 fp32 中间结果截断为 int8。

总结

一批具有固定类型(Type)和固定尺寸(Shape)的数据包(Tensor),按照固定的流向(Topology)流经一堆黑盒操作(Ops)

至于数据包里面的具体数值(比如像素 RGB 是 128 还是 255)------那是 Kernel 层(运行时循环)要处理的具体数值,图编译器完全不看,也不需要看。

在编译期完成 80% 的全局优化决策(内存分配、算子融合、布局转换)。

这,就是"图是拓扑 + 类型 + 形状的世界"的真正含义。

相关推荐
小白说大模型1 小时前
去AI味提示词大全:25个实用Prompt帮你降低AI率
大数据·人工智能·pytorch·深度学习·机器学习·prompt
find1star1 小时前
LeetCode 54:螺旋矩阵——用四个边界模拟矩阵收缩
java·算法·leetcode·边缘计算·学习方法
WeiXin_DZbishe1 小时前
基于springboot大学生提问箱系统-计算机毕设【课程设计】72593
javascript·vue.js·spring boot·vscode·python·node.js·php
z_mazin1 小时前
逆向一种私有二进制序列化格式:从零到字节级解析器
网络·python·网络协议·算法·rpc
luj_17681 小时前
罚球线右移破防新策略
c语言·开发语言·网络·经验分享·算法
vivo互联网技术1 小时前
SmartPhotoCrafter: 先思考后修图,统一理解-生成的图像优化新范式
人工智能·算法·计算机视觉
吞下星星的少年·-·2 小时前
LeetCode 热题 100 两数之和(哈希表)
算法·leetcode·哈希算法
Shan12052 小时前
经典算法题示例与详解:飞地的数量(二)
java·数据结构·算法
土司大王2 小时前
LeetCode hot100——全排列
java·算法·leetcode