
Unified Memory 让 CPU 和 GPU 可以通过统一地址访问数据,减少了手工维护两份指针的负担,但统一地址不等于数据同时存在于所有处理器的本地内存。运行时仍要根据访问位置、页面状态和平台能力放置或迁移数据。当 CPU 刚写完一个大数组,GPU 随后分散读取;或者多个 GPU 轮流修改同一批页面时,迁移与缺页处理可能形成明显抖动。程序表面上没有显式 memcpy,却并不代表数据移动消失了。
症状通常不只表现为带宽下降
页迁移问题可能表现为首轮内核很慢、后续轮次恢复,也可能在每次迭代都出现周期性停顿。若工作集超过设备可用显存,运行时还要驱逐旧页面,形成反复换入换出。只看平均 GPU 利用率容易忽略短时空洞,应将内核时间线、统一内存活动、缺页组、迁移字节和 CPU 访问阶段对齐。测试时需区分初始化、预热、稳定运行与输入切换,避免把首次触页的合理成本误判为持续性故障。
访问局部性决定迁移是否值得
连续、单向、长时间由同一处理器使用的数据,通常更容易通过预取或访问建议建立稳定归属。随机访问、CPU 与 GPU 交替写入、细粒度生产消费则可能使页面在处理器之间来回移动。工程团队应从数据结构和算法阶段标记所有权:哪一阶段创建,哪一侧写,何时只读,何时结束。若某块数据在一个阶段只由 GPU 使用,可以在阶段开始前预取;若只读数据被多 GPU 共享,可根据实际能力评估只读复制或访问建议。不能把所有分配统一加上同一条提示,因为错误提示也可能造成额外流量。
超额占用需要单独设计实验
Unified Memory 支持的超额占用能力容易被理解为“显存不够也能自动运行”,但可运行与可接受的性能是两回事。应逐级扩大工作集,记录可用显存、迁移总量、驱逐、每轮耗时和尾延迟,找出从本地驻留转向频繁换页的拐点。其他进程、显示服务和运行时缓存也会占用显存,因此容量测试必须在与生产相似的并发条件下进行。若业务必须超额使用,应考虑分块、流水处理、压缩或明确的数据淘汰策略,而不是依赖运行时在压力下猜测最优放置。
多 GPU 与互连路径会改变结论
在多 GPU 节点中,页面首次被哪张卡访问、GPU 之间是否具备合适的点对点路径、CPU NUMA 节点以及进程绑定,都会影响移动成本。一个在单卡上稳定的访问模式,扩展后可能出现远端访问或所有权争用。验证时应固定 GPU 可见性和进程映射,记录设备拓扑,并分别测试单卡、同一互连域和跨域情况。若框架或通信库在后台创建额外进程,还要确认它们是否触碰统一内存,避免应用代码之外的访问改变页面状态。
从观察到修正
- 按阶段记录 CPU/GPU 读写方、工作集大小、第一次访问者和预期驻留位置。
- 使用时间线确认缺页与迁移发生在哪个阶段,区分首次触页和循环抖动。
- 先测试预取,再测试访问建议或数据布局调整,每次只改变一种策略。
- 逐级扩大工作集并加入真实并发,找到驱逐开始影响服务目标的容量边界。
- 在目标多 GPU 拓扑上复测,检查 NUMA、点对点能力和进程绑定。
如果数据天然由 CPU 与 GPU 高频交替修改,显式分区或重构流水可能比继续调提示参数更可靠。反之,对阶段边界清晰的数据,统一内存仍能兼顾可维护性和性能。NVIDIA 对数据传输、统一内存和性能测量的建议可参考 CUDA C++ Best Practices Guide。具体可用能力受操作系统、驱动、GPU 和 CUDA 版本影响,应以目标环境为准。
WeChat
Profile