一句话定义:DMA(Direct Memory Access,直接内存访问)是一种让外设(网卡、硬盘、GPU 等)和内存之间直接搬运数据、不需要 CPU 逐字节中转的机制。CPU 只负责“下达搬运指令”,搬完再通知它一声(中断)。
打个比方:没有 DMA 时,CPU 像老板自己一趟趟搬箱子——从硬盘读到寄存器,再从寄存器写到内存,全程盯着,什么别的事都干不了。有了 DMA,老板雇了一支搬运队(DMA 控制器),告诉它“从这儿搬到那儿,搬 4MB”,然后回去开会;搬完了搬运队按一下门铃(中断),老板再确认结果。
原理层面:CPU 在内存里准备一张“任务单”(描述符,descriptor),写明源地址、目的地址、长度、方向,然后把这张单子的地址写进 DMA 控制器的寄存器,启动传输。控制器自己驱动总线完成读写,CPU 全程可以执行别的线程。现代设备普遍支持分散-聚集(scatter-gather),一张单子里可以列很多不连续的小块,一次提交、批量搬完,减少反复下单的开销。另外,IOMMU 这类地址翻译单元负责把设备看到的地址安全地映射到真实物理内存,防止设备乱写。
和相邻概念的区别:
| 概念 | 谁在搬数据 | 典型场景 |
|---|---|---|
| PIO / CPU 拷贝 | CPU 亲自逐字节读写 | 小数据量、简单嵌入式场景 |
| DMA | DMA 控制器/设备本身 | 网卡收包、磁盘读写、GPU 传数据 |
| 零拷贝(zero-copy) | 内核与设备配合,减少拷贝次数 | 文件发送、网络转发 |
| RDMA | 网卡直接读写远端机器内存 | 跨节点通信、分布式训练 |
关键区别:DMA 解决“本机内 CPU 不要当搬运工”,零拷贝解决“同一次数据传输不要来回拷好几遍”,RDMA 解决“跨机器传输不经过对方 CPU”。三者常叠加使用。
对从业者的实际意义:在推理服务里,数据搬运往往是不显眼的瓶颈。比如从磁盘读模型权重、网卡收请求、主机内存和 GPU 显存之间来回拷张量,这些如果都走 CPU 拷贝,延迟和 CPU 占用都会很难看。常见优化包括:用“锁页内存”(pinned / page-locked memory)让 GPU 能直接对该内存做 DMA,避免额外中转;让网卡直接把数据写进应用缓冲区;在同一张卡上尽量让数据一次到位,减少中间拷贝。写推理服务时值得问自己三个问题:这份数据被拷了几次?每次拷贝是谁在搬?搬的时候 CPU 是不是被占住了?
普通职场人也可以借用这个思路:把自己当成 CPU,把重复性的搬运、转发、格式转换交给“搬运队”(脚本、自动化工具、队列),只保留判断和决策。至于具体硬件的 DMA 能力、通道数量和限制,以厂商官方文档为准。
