ai 相关知识

ai 相关知识

相关概念

Tensor

张量,表示多维数组

Tensor = 数据 + 元信息 + 自动求导能力

Tensor 是神经网络里所有数据的统一表示:
输入是 tensor
权重是 tensor
中间结果是 tensor
输出还是 tensor

Tensor = GPU 上的一块结构化内存

DAG(有向无环图)

深度学习里的 DAG
在 PyTorch 或 TensorFlow 的计算图中:
节点 = 张量操作(add、conv、relu…)
边 = 张量流向
方向 = 数据流方向(input → output)
无环 = 前向传播是有序的,不会死循环

算子

算子 = 对张量进行特定操作的“函数”或“原子计算单元”

一、从简单数学看算子

算子其实就是数学函数,但作用在 tensor 上:

类型 数学形式 Tensor 例子
加法 (f(a,b) = a + b) elementwise_add(a, b)
乘法 (f(a,b) = a * b) matmul(a, b)
非线性 (f(x) = \max(0,x)) ReLU(x)
卷积 (f(x, w) = x * w) Conv2D(input, kernel)

✅ 核心特点:

  • 输入 → tensor
  • 输出 → tensor
  • 可以组合成更复杂计算图(DAG)

二、深度学习中的算子示意

以卷积神经网络为例:

Input Tensor → Conv2D → ReLU → MaxPool → FC → Output Tensor

每一箭头代表一个算子:

Conv2D:卷积算子
ReLU:激活算子
MaxPool:池化算子
FC:全连接算子

整个网络就是算子 DAG 的组合。

三、为什么工程上要关注算子

性能优化的粒度

推理加速(TensorRT、ONNX、TVM)基本都是 对算子做优化

例:卷积算子用 Winograd 或 FFT 算法

elementwise 算子 fuse(算子融合)减少内存访问

跨平台执行

CPU / GPU / NPU 都需要实现算子

框架(PyTorch / TensorFlow)通过算子抽象保证网络可移植

调度和内存管理

DAG 中算子执行顺序决定 GPU 内存峰值

通过算子融合 / reorder 可以降低 latency

四、算子的分类(深度学习常用)

算术类:add, subtract, multiply, divide
线性代数类:matmul, batch_matmul
卷积类:conv1d/2d/3d, depthwise_conv
池化类:max_pool, avg_pool, global_pool
激活类:ReLU, Sigmoid, Tanh, GELU
归一化类:BatchNorm, LayerNorm
张量操作类:reshape, transpose, concat, slice

五、总结一句话

算子 = 对 tensor 的原子操作,是神经网络的基本构建块,也是推理优化的核心对象。

内存布局

内存布局 = 张量在内存中存储元素的顺序

为什么要关心内存布局

深度学习的 tensor 通常是多维的(NCHW、NHWC…),而算子在做计算时:

  • CPU/GPU 会按内存顺序访问数据
  • 内存访问顺序不连续 → cache miss ↑、带宽利用率 ↓ → latency ↑

所以布局决定算子执行性能。

二、常见的内存布局

假设有一个 4D 张量(batch, channel, height, width):

shape = [N, C, H, W] = [32, 3, 224, 224]
1️⃣ NCHW (Batch, Channel, Height, Width)

  • 按顺序存储:

    • 最快变化的是 W
    • 然后 H → C → N
  • 常用于 PyTorch 和 GPU 卷积优化

  • 内存访问连续性好,卷积性能高

2️⃣ NHWC (Batch, Height, Width, Channel)

  • 最快变化的是 C
  • 常用于 TensorFlow 的某些 CPU / GPU 优化
  • 对某些 SIMD / vectorized CPU 算子性能友好

Embedding

Embedding = 把离散对象映射成连续向量的表示方法

用一个 低维、稠密、可学习的向量 表示对象:
向量距离 = 语义距离

attention

Attention = 模型在读一句话时,决定“该重点看谁”的机制
Attention = 一个动态加权的信息聚合算子,让每个 token 能从其他 token 获取最相关的信息。

或者更直白:

Attention 就是模型的“阅读理解能力”。

MLP

MLP = Multi-Layer Perceptron(多层感知机)

本质上就是:
一堆全连接层 + 非线性激活函数组成的网络

最直观理解

如果说:

Attention = 让 token 互相交流信息
MLP = 对每个 token 自己做“深度思考”

Attention → 信息混合
MLP → 信息加工

Attention 做什么?

👉 在 token 之间传播信息

MLP 做什么?

👉 在 单个 token 内部做非线性变换

换句话说:

Attention:横向交流
MLP:纵向加工

KV cache

KV cache = 把历史 token 的 Key 和 Value 存起来,避免每次生成新 token 时重复计算 attention。

warp

Warp = GPU 中一起执行同一条指令的一组线程(最小调度单位)

在 NVIDIA GPU 上:
1 warp = 32 个线程

为什么会有 warp

GPU 不是像 CPU 那样:
一个核心跑一个线程
GPU 的设计是:
大量线程同时跑同一条指令

这叫:
SIMT = Single Instruction Multiple Threads
warp 就是这个模式下的执行单位。

👉 GPU 并不是给每个线程独立指令流
👉 而是 warp 内共享同一条指令(指令相同,数据不同)

block

cuda 层次结构:

Grid (整个 kernel 的线程空间)
└─ Block (线程块,多个线程组成)
└─ Warp (32 个线程的执行小队)
└─ Thread (最小计算单位)

Thread:最小执行单元,每个线程处理一个数据元素
Warp:32 个线程组成的同步执行单元
Block:warp 的集合,负责线程调度和共享内存
Grid:所有 block 的集合,覆盖整个数据空间

Block 的作用

1️⃣ 线程分组调度

GPU 不会同时调度所有线程,而是以 block 为单位调度
每个 block 内的线程共享资源(如寄存器和共享内存)

2️⃣ 共享内存管理

GPU 给每个 block 分配 shared memory
同一个 block 内的线程可以高速访问 shared memory
不同 block 之间的 shared memory 不共享

3️⃣ 线程索引管理

  • 每个线程有两个索引:
    • threadIdx:block 内的索引
    • blockIdx:block 在 grid 中的索引
  • 合起来可以唯一定位每个线程对应的数据

memory hierarchy

GPU 内存层级结构

从最接近计算单元(最快)到最远(慢)的顺序:

层级 典型名字 访问速度 容量 作用
寄存器(Register) thread-private 极快 很少(几十 KB per SM) 每个线程的私有变量
共享内存 / L1 Cache shared memory / L1 非常快(几 cycles) KB~100KB 同一个 block 内线程共享数据
L2 Cache L2 中速 MB 级 GPU 全局缓存,跨 block 可用
全局内存(Global Memory) DRAM 慢(400~600 cycles) GB 级 所有线程可访问,跨 block 通信
纹理/常量内存 texture/constant 中速 KB~MB 常量数据或图像数据优化访问模式

每种内存的特点

1️⃣ 寄存器(Registers)

每个线程独享

访问速度最快

容量有限 → 线程数太多会溢出到 local memory

2️⃣ 共享内存(Shared Memory)

block 内线程共享

快速,类似 CPU 的 L1 cache

非常适合 warp 内合作计算

用在 warp shuffle、矩阵块计算、attention 计算

3️⃣ 全局内存(Global Memory)

所有线程都能访问

很慢(几百 cycles)

GPU 核心瓶颈之一

对性能敏感,需要 coalesced memory access

4️⃣ 常量/纹理内存

只读内存

可缓存,访问速度快

用在 embedding 权重、固定参数等

为什么要理解 memory hierarchy

GPU 性能瓶颈很多时候不是计算能力,而是 内存访问:

Embedding lookup → 内存带宽瓶颈

Attention kernel → Global memory 访问模式决定速度

MLP / GEMM → 如果 warp 内访问不连续 → coalescing 失效

优化策略:

尽量用 寄存器 + shared memory 存热数据
尽量让 warp 内访问连续内存
减少 global memory 访问次数
考虑 memory alignment 和 vectorized load/store

工程直观理解

可以把 GPU memory hierarchy 想象成:

寄存器 = 手边的小笔记本,随手可写
共享内存 = 办公桌抽屉,团队成员共用
全局内存 = 仓库,需要走很远才能拿
L2 Cache = 仓库前的临时架子,访问比仓库快
常量内存 = 贴在墙上的参考资料
速度越快 → 容量越小 → 使用越灵活

总结一句话

GPU memory hierarchy = GPU 的多层存储体系,每层速度和容量不同,理解它才能写出高效 kernel。

coalescing

Coalescing = warp 内线程连续访问连续内存,使 GPU 一次内存事务就能满足多个线程的请求。

为什么需要 coalescing

GPU 的 全局内存(Global Memory) 非常慢(400~600 个时钟周期)。
如果 warp 内每个线程访问 随机地址,就会:

  • 每个线程单独发一次内存请求
  • 32 个线程 warp → 32 次 DRAM 访问
  • 吞吐量极低

而如果 连续访问内存:

  • warp 内多个线程的数据可以 一次 DRAM 事务完成
  • 内存带宽得到充分利用
  • 性能大幅提升

这就是 coalescing 的价值。

coalescing 的原则

  1. warp 内线程尽量访问连续地址
  2. 访问模式最好按 threadIdx 排序
  3. 访问类型尽量对齐(alignment)
  • 32 位 float 对齐 128 bytes
  • 64 位 double 对齐 256 bytes
  • 避免分支导致 warp divergence
  1. 分支可能让线程访问模式乱掉 → coalescing 失效

shared memory

Shared memory = GPU block 内所有线程共享的高速内存,相当于每个 block 的本地工作台,用于快速数据交换和缓存。

graph optimization

在 AI 推理(inference) 中,graph optimization 指的是对神经网络计算图(computation graph)进行各种优化,使得模型在推理时 更快、更省内存、更高效。

什么是计算图(Computation Graph)

神经网络可以看作一系列操作(op)和数据(tensor)的组合。

这些操作和数据组成一张 有向无环图(DAG):

  • 节点(Node) → 操作(比如 MatMul, Conv2D, ReLU)
  • 边(Edge) → 张量(Tensor)在操作之间流动

为什么需要 Graph Optimization

原始模型是 为了训练而设计,训练时要保存大量中间变量和梯度,计算顺序不一定最优。

  • 推理只关心输出,不需要梯度。
  • 原始图可能存在冗余计算、低效操作顺序、内存占用大。
  • Graph Optimization 就是把这个图 变得更轻量、高效。

常见的 Graph Optimization 技术

技术 作用
常量折叠 (Constant Folding) 把图中常量计算提前算好,例如 3*412,推理时不用再算
算子融合 (Operator Fusion) 把多个操作合成一个 kernel,比如 Conv2D + ReLU → 一个 fused kernel,减少内存读写
不必要节点消除 (Dead Node Elimination) 去掉对输出无影响的节点
精度降低 (Quantization / FP16) 让 float32 换成 float16 或 int8,减少内存和计算量
内存优化 (Memory Optimization / Tensor Reuse) 减少中间张量占用,复用 buffer
布局转换 (Layout Transformation) 改变 tensor 存储格式,比如 NCHW → NHWC,更适合硬件加速器

Graph Optimization 的效果

  • 更快:减少 kernel 数量、内存访问,硬件更友好。
  • 更省内存:中间张量复用、删除无用节点。
  • 可部署:有些优化可以让模型适应 GPU / CPU / NPU / FPGA 等不同硬件。

工具层面的例子

  • ONNX Runtime → 会对 ONNX graph 自动做 fusion、constant folding 等优化
  • TensorRT → 对 graph 做 layer fusion、precision calibration(量化)、tensor memory reuse
  • TVM / XLA → 静态编译优化整个图,生成高性能 kernel

TensorRT

TensorRT 是 NVIDIA 推出的高性能深度学习推理引擎,专门用来把训练好的神经网络模型在 NVIDIA GPU 上 跑得又快又省资源

基本定义

  • 全称:NVIDIA TensorRT (Tensor Runtime)
  • 主要功能:优化和加速神经网络推理
  • 支持的模型来源:PyTorch、TensorFlow、ONNX 等训练好的模型

TensorRT 做了哪些事情

功能 描述
Graph Optimization 对网络计算图进行优化,例如 operator fusion、constant folding、消除冗余节点
精度优化(Quantization) 支持 FP32 → FP16 或 INT8,减少计算量和显存占用
Kernel 自动选择 根据 GPU 架构自动选最优实现,比如卷积算法选择
内存复用 减少中间张量占用,节省显存
动态批次支持 可以处理不同 batch size,提高吞吐量
序列化部署 优化后的 engine 可以直接部署在 GPU 上,无需训练框架

TensorRT 的流程

一般流程分三步:

  1. 导入模型:
  • 支持 ONNX、Caffe、PyTorch(导出 ONNX)等
  1. 优化模型:
  • 做 graph optimization、精度降低、kernel fusion 等
  1. 生成 TensorRT Engine 并推理:
  • Engine 是针对 GPU 编译后的优化执行文件,推理速度很快

TensorRT 优势

  • 极高性能:同样 GPU 上比原框架推理快 2~10 倍
  • 低延迟:非常适合实时推理(如自动驾驶、视频分析)
  • 节省显存:FP16/INT8 精度可以减少 50~75% 显存
  • 可部署性强:Engine 可以直接在 GPU 上跑,无需原训练框架

ONNX Runtime

ONNX Runtime(ORT) 是微软推出的一个 高性能跨平台神经网络推理引擎,可以运行各种训练好的模型,而且不仅限于 NVIDIA GPU,也可以在 CPU、其他 GPU 或加速器上执行。简单说,它的定位和 TensorRT 类似,但更加通用。

基本概念

全称:Open Neural Network Exchange Runtime
作用:把训练好的模型快速、高效地在不同硬件上运行
支持的模型来源:PyTorch、TensorFlow、Scikit-learn、Keras 等,只要导出为 ONNX 格式即可

ONNX 是一种中间格式(类似“通用模型描述语言”),它把模型抽象成计算图(computation graph),ORT 就能理解和执行。

ONNX Runtime 能做的事情

功能 描述
Graph Optimization 自动优化计算图,比如算子融合、常量折叠、删除无用节点
多硬件支持 CPU、GPU(CUDA)、DirectML、OpenVINO、TensorRT 等
加速推理 使用高性能 kernel、多线程、内存优化
量化支持 FP32 → FP16 / INT8 推理,节省显存和计算量
跨平台部署 Windows、Linux、Mac、甚至移动端和嵌入式平台

ONNX Runtime vs TensorRT

特性 ONNX Runtime TensorRT
支持硬件 CPU/GPU/TPU/加速器 NVIDIA GPU
易用性 高,跨框架、跨平台 针对 NVIDIA GPU,需要 CUDA
优化程度 较高,但不如 TensorRT 深度优化 极致 GPU 性能优化,低延迟、高吞吐
精度优化 支持 FP16/INT8 支持 FP16/INT8,更多 kernel fusion

可以理解:ONNX Runtime 更通用,TensorRT 更专精于 NVIDIA GPU

使用场景

  • 快速部署模型:PyTorch/TF 训练的模型 → ONNX → ORT 推理
  • 跨硬件部署:CPU 上部署 AI 服务,或者 GPU/加速卡上推理
  • 混合优化:在 CPU 上跑,GPU 上跑,甚至和 TensorRT 结合做加速

latency

在 AI 推理(inference) 里,latency 是一个非常核心的概念,简单来说就是:
完成一次推理所需要的时间。

  • Latency = 输入数据送入模型 → 模型计算完成 → 输出结果产生 的时间
  • 单位通常是 毫秒(ms) 或 微秒(µs)
  • 有时也叫 inference time / response time

为什么 latency 很重要

  • 对于 实时系统(自动驾驶、语音识别、AR/VR、视频分析):

    • 高 latency = 响应慢,可能导致系统失效
  • 对于 批量处理/离线推理:

    • latency 不那么关键,更关注 吞吐量(throughput) = 单位时间能处理多少样本

Latency 与吞吐量的区别

指标 关注点 适合场景
Latency 一条数据的响应时间 实时系统、低延迟应用
Throughput 单位时间处理的数据量 批量推理、大规模服务

Latency 受哪些因素影响

  1. 模型大小和复杂度:层数越多、参数越大 → 推理慢
  2. 硬件性能:GPU、CPU、加速器性能差异很大
  3. 计算精度:
  • FP32 > FP16 > INT8
  • 精度越低 → 运算量小 → latency 下降
  1. 批量大小(batch size):
  • 大 batch → 吞吐量高,但单条 latency 增加
  1. 内存/数据传输:
  • CPU/GPU 之间数据传输、缓存命中率都会影响 latency
  1. Graph Optimization / Kernel Fusion:
  • TensorRT、ONNX Runtime 优化可以大幅降低 latency

实际场景举例

  • 自动驾驶:摄像头帧每 33ms → 模型 latency ≤ 33ms 才能实时反应
  • 语音助手:用户说一句话 → 模型 latency ≤ 100ms 才算流畅
  • 批量推荐系统:一次请求推荐 100 个结果 → latency 可以稍大,但关注 throughput

memory bandwidth bound

在 AI 推理 / GPU 性能分析里,memory bandwidth bound 是一个非常关键的概念。

memory bandwidth bound = 程序的速度受限于内存读写带宽,而不是算力。

也叫 内存带宽瓶颈。

直观理解

计算程序运行需要两样东西:

  • 算力(compute) → GPU/CPU 做乘法、加法等计算
  • 内存带宽(memory bandwidth) → 从显存/内存读取数据

如果:

  • 算力用不满
  • 但内存读写已经跑满

那么程序就叫 memory bandwidth bound

compute bound

compute bound(计算受限)是和 memory bandwidth bound 相对的概念,在 AI 推理 / GPU 性能分析里非常常见。

compute bound = 程序的速度受限于计算能力,而不是内存读写速度。

也就是说:

  • GPU 的算力已经被用满
  • 但内存带宽还有余量
    👉 瓶颈在“算得不够快”,不是“搬数据太慢”。
posted @ 2026-02-25 16:34  卑以自牧lq  阅读(3)  评论(0)    收藏  举报