异构计算:CPU、GPU、NPU 如何协同工作 / Heterogeneous Computing with CPUs, GPUs, and NPUs
📅 创建时间:2026-07-20 🏷️ 标签:#异构计算 #CPUGPU #NPU #任务调度 📚 前置知识:[[07-parallel-patterns]] 📚 相关知识:[[/02-systems-and-performance/02-computer-architecture-and-hardware/09-heterogeneous-computing]] [[/02-systems-and-performance/02-computer-architecture-and-hardware/12-npu-landscape]]
1. 为什么需要异构系统
不存在对所有任务都最优的处理器:
- CPU 擅长控制流、串行逻辑和低延迟
- GPU 擅长规则的大规模数据并行
- NPU 擅长特定张量算子和低精度计算
- FPGA 擅长确定性数据流和定制硬件流水线
异构计算的目标,是让每类工作运行在最适合的设备上,同时控制数据迁移成本。
2. 一个典型异构流水线
CPU:读取文件、解析格式
↓
CPU:构建批次、数据预处理
↓ PCIe / 共享内存
GPU:矩阵计算或仿真核心
↓
CPU:业务判断、结果整理
↓
GPU:可视化或后处理如果每一步都频繁来回传输小数据,GPU 的计算收益可能被传输抵消。
3. 任务放置的四个问题
- 任务是否有足够并行度?
- 数据当前位于哪块内存?
- 迁移数据需要多长时间?
- 设备是否支持所需精度、操作和容量?
粗略决策:
收益 = 设备计算节省时间 - 数据迁移 - 启动与同步开销只有收益显著为正时,迁移到加速器才值得。
4. 数据管理模式
显式拷贝
程序明确分配 Host/Device 内存并传输。控制最清楚,优化空间最大,但代码复杂。
统一虚拟地址
CPU 和 GPU 使用统一地址空间,但物理数据仍可能需要迁移。
Unified Memory
运行时按需迁移页面,简化开发。访问模式不佳时会产生频繁 Page Fault,因此便利不等于没有成本。
零拷贝与共享内存
某些集成式架构让 CPU 和 GPU 共享物理内存,减少显式拷贝,但仍要考虑缓存一致性、带宽竞争和同步。
5. 计算与通信重叠
把数据分成多个批次:
时间 →
传输批次 0 | 传输批次 1 | 传输批次 2
计算批次 0 | 计算批次 1 | 计算批次 2
回传批次 0 | 回传批次 1实现重叠需要:
- 异步传输
- 多个 Stream 或队列
- 独立缓冲区
- 足够大的任务粒度
- 避免不必要的全局同步
6. 可移植编程模型
| 模型 | 特点 |
|---|---|
| CUDA | NVIDIA 生态成熟、控制力强 |
| HIP | 面向 AMD,并提供部分 CUDA 迁移能力 |
| SYCL | 基于现代 C++ 的跨设备模型 |
| OpenCL | 开放、设备广泛,开发体验较底层 |
| OpenMP Offload | 用指令扩展把部分循环卸载到设备 |
可移植性通常会牺牲部分特定硬件优化空间。工程上应先明确目标设备、生命周期和性能要求。
7. 调度与资源竞争
实际系统可能同时运行多个模型或求解任务,需要处理:
- 显存分配和碎片
- Stream 优先级
- 多进程共享 GPU
- CPU 数据线程抢占
- PCIe 和内存带宽竞争
- 设备故障与任务回退
异构系统优化不能只看单个 Kernel,还要观察端到端流水线。
历史原文阅读补充
本页保留课程合并前的异构计算正文。 当前权威版本位于并行计算目录。
历史文章用于比较早期术语、示例和学习顺序。 版本敏感 API 与硬件参数需要重新核验。
任务放置的历史模型
异构系统从“哪个设备执行哪段工作”开始。
决策因素:
- 控制流;
- 并行规模;
- 数据位置;
- 搬运量;
- 算术强度;
- 延迟;
- 内存容量;
- 设备支持;
- 回退成本。
total cost
= queue
+ transfer
+ conversion
+ execution
+ synchronization只比较 Kernel 时间会遗漏大部分系统成本。
CPU 适合的工作
- 复杂分支;
- 小任务;
- 串行关键路径;
- 操作系统服务;
- I/O;
- 调度;
- 不规则图;
- 错误恢复。
GPU 适合的工作
- 规则数据并行;
- 大批量;
- 矩阵和向量;
- 网格 Kernel;
- 图像;
- 高算术密度;
- 可隐藏延迟;
- 可长期驻留的数据。
数据驻留
数据应尽量停留在连续使用它的设备。
upload once
-> kernel A
-> kernel B
-> kernel C
-> download final result每阶段往返 CPU/GPU 会让 PCIe 和同步占主导。
显式拷贝
显式拷贝让位置和时间清晰。
需要管理:
- Host Buffer;
- Device Buffer;
- 大小与对齐;
- Stream;
- Event;
- 生命周期;
- 错误;
- 取消。
Unified Memory
统一地址简化指针,不取消物理迁移。
观察:
- Page Fault;
- Migration;
- Prefetch;
- Oversubscription;
- CPU/GPU 交替访问;
- 同步。
Pinned Memory
Pinned Host Memory 支持高效和异步传输。
它不能无限使用。 过多页锁定内存会影响整个系统。
池化、复用并限制总量。
零拷贝
零拷贝避免显式复制,但设备经互连访问 Host Memory。
适合低复用、小数据或集成设备。 高复用 Kernel 更适合设备本地内存。
重叠
copy batch N+1
overlaps
compute batch N
overlaps
CPU prepares batch N+2重叠需要独立资源和正确依赖。 异步 API 返回不代表操作完成。
多 GPU 拓扑
多 GPU 性能取决于:
- PCIe Root;
- P2P;
- NVLink;
- NUMA;
- Host 线程;
- 集合通信;
- 数据分区;
- 显存容量。
负载均衡
设备型号、温度、输入和共享状态可能不同。
均分元素数量不一定均分时间。
记录每设备:
- 队列等待;
- 计算;
- 传输;
- 显存;
- 完成时间;
- 错误和重试。
可移植模型
SYCL、OpenMP Offload、OpenCL、Kokkos 和 RAJA 提供不同抽象。
比较:
- 平台覆盖;
- 编译器;
- 内存模型;
- 工具;
- 调试;
- 性能特化;
- 生态;
- 长期维护。
回退
设备不可用、OOM 或编译失败时,需要明确回退。
回退必须保持:
- 输出语义;
- 精度;
- 错误报告;
- 事务边界;
- 可审计性。
端到端 Profile
先用系统 Timeline 区分:
- CPU 准备;
- H2D;
- Kernel;
- D2H;
- 同步;
- 空闲;
- 队列。
再对主导 Kernel 使用设备级分析。
验证
测试:
- CPU 基线;
- 单 GPU;
- 多 GPU;
- 多规模;
- 冷启动;
- 稳态;
- 容量边界;
- 错误回退;
- 数值容差;
- 资源释放。
当前课程映射
当前文章补充了数据驻留、Pinned Memory、双缓冲、设备队列、故障回退和观测字段。
引用历史内容时,应到当前版本核对术语和工具命令。
核心总结
- 异构计算是任务放置和数据管理问题。
- 最快设备不一定带来最快端到端系统。
- 数据应尽量长期停留在使用它的设备附近。
- 批处理、异步执行和双缓冲可帮助重叠通信与计算。
- 可移植性、性能和开发成本需要共同权衡。
下一篇:[[09-distributed-parallelism]]