news 2026/4/30 16:34:52

多核 DMA 性能损耗

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
多核 DMA 性能损耗

核心就 3 条根因:

  1. CPU 缓存一致性(CCE/coherency)冲突
  2. 缓存抖动、反复 flush/invalidate 造成 “空跑周期”
  3. 总线争用、内存带宽瓶颈、跨 NUMA 访问

这些在单核基本不明显,多核高并发 DMA会被剧烈放大。

最核心损耗:Cache 一致性 & 缓存冲刷

DMA 是非一致性访问(绝大多数设备)

  • 设备直接读写内存,不看 CPU Cache
  • CPU 写的数据还在 L1/L2,内存是旧的 → DMA 读错
  • DMA 写完内存,CPU Cache 还是旧的 → CPU 读错

所以内核 / 驱动必须做:

  • flush_dcache_range()// 写回 + 失效
  • invalidate_dcache_range()

这些操作在多核下极贵

多核下缓存操作的真实代价

  • 单个flush不是 “本地核操作”,会穿透整个缓存层次
  • 会引发:
    • 大量cache line 回写内存
    • 其他核的缓存行无效(snoop /invalidate)
    • 总线(AXI/PCIe)大量事务
    • CPU 空等缓存状态同步

典型表现:

  • 核越多,单 DMA 的 overhead 反而上升
  • 系统软中断 / 系统耗时暴涨,但业务计算不重
  • perf top看到大量cacheflushdsbisbbus lock

这就是DMA 导致的多核扩展性极差

第二大损耗:伪共享 & 缓存行乒乓

很多驱动设计:

  • 一个 DMA 描述符(descriptor)被多个核同时访问
  • 完成状态、所有权、控制位混在同一缓存行(64B)

后果:

  • 核 A 改完 → 核 B 的缓存行立即失效
  • 核 B 再改 → 核 A 又失效
  • 缓存行在核之间来回弹跳(ping-pong)

即使没有 DMA 流量,多核并发访问同一个小结构就会吃掉大量性能。

第三大损耗:NUMA 下的跨节点 DMA

  • 设备在 NUMA node 0
  • 内存分配在 node 1
  • DMA + CPU 访问都要走跨 NUMA 链路

表现:

  • 延迟翻倍
  • 带宽上不去
  • 多核并发时NUMA 链路拥塞,所有核一起变慢

第四:PCIe / 总线争用与中断风暴

  • 多设备 / 多队列同时 DMA → PCIe 带宽打满
  • 大量短小包 DMA →往返握手开销 > 数据传输
  • 多核分散处理中断 → 频繁核间迁移、缓存重建

典型:

  • 网卡多队列收小包,CPU 利用率很高但 PPS 上不去
  • 大量sysirqsoftirq,IPC(指令 / 周期)暴跌

内核中 DMA 与缓存一致性的关键机制

1. 两类 DMA 映射(决定你要不要 flush)

(1) 非一致性映射(最常见、最耗性能)

dma_map_single(..., DMA_FROM_DEVICE/TO_DEVICE)
  • 内核必须 flush /invalidate
  • 多核下开销巨大

(2) 一致性映射(coherent)

dma_alloc_coherent()
  • 内存属性设置为Non-cacheable 或 Write-through
  • CPU 写直通内存,不需要 flush
  • 但 CPU 访问极慢,不适合大数据、频繁访问

结论:coherent 省掉 cache flush,但 CPU 访问慢;非 coherent CPU 快,但多核 flush 爆炸。

2. 多核下最痛的点:dma_unmap是隐形杀手

很多人不知道:

dma_unmap_single(..., DMA_FROM_DEVICE)

内部会做:

  • invalidate_dcache_range()
  • 强制丢弃该范围所有缓存

这意味着:CPU 刚处理完的数据,缓存直接被废掉

下一次访问必须从内存重新读 → 性能雪崩。

多核 DMA 性能优化

1. 优先使用DMA 多队列 + 核绑定

  • 每个核 / 每个组独占一个 DMA 通道 / 队列
  • 数据、描述符、缓冲区不跨核共享
  • 中断绑定(irq affinity),避免核间迁移

目标:局部化、无共享、无乒乓


2. 彻底避免不必要的 flush:使用dma_alloc_coherent做控制面

  • 描述符、状态位、门控:放coherent 内存
  • 真正大数据 payload:用非 coherent + 批量 flush

控制面不频繁、小数据;payload 连续、可批量。


3. 缓存行隔离,杜绝伪共享

  • DMA 描述符、完成标志、所有权:每个核独立缓存行
  • 对齐到____cacheline_aligned
  • 只读数据与可写数据分开
struct dma_chan_ctx { dma_desc_t desc; u8 pad[SMP_CACHE_BYTES - sizeof(dma_desc_t)]; } ____cacheline_aligned;

4. 批量 DMA、批量 flush,减少次数

  • 少次多量 > 多次少量
  • 一次flush128KB 远快于 32 次 flush 4KB
  • 合并 DMA 描述符,减少中断 & 缓存操作次数

5. NUMA 亲和:内存与设备同节点

numa_node_id = dev_to_node(dev); buf = alloc_pages_node(numa_node_id, GFP_KERNEL | __GFP_NOWARN, order);
  • DMA 不走跨 NUMA
  • CPU 访问本地内存
  • 多核扩展性立刻提升

6. 尽量使用硬件 IOMMU + snoop 支持(SMMU/Snoop IO)

如果平台 / 设备支持IO coherency(snoopable DMA)

  • 硬件自动保证缓存一致
  • 驱动完全不需要 flush dcache
  • 多核性能几乎无损耗

这是终极解法,但依赖:

  • PCIe NoSnoop = 0
  • 设备支持 ACS、snoop
  • IOMMU 开启并配置正确

核心结论

多核 DMA 性能损耗 90% 来自:缓存 flush/invalidate + 缓存行伪共享 + NUMA 跨节点 + 中断 / 队列未绑定。

最优解:队列核绑定、同 NUMA、缓存隔离、批量 DMA、能开硬件 snoop 就全开。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/22 14:58:18

漏洞挖掘小白避坑:从基础认知到落地实操,全流程直接套用

对新手来说,挖掘并非遥不可及,核心是掌握正确思路和基础方法,从手工挖掘入手建立认知。本文就带大家走进漏洞挖掘的入门世界,从思路构建到实战操作,全程手把手教学,帮你迈出“找漏洞”的第一步。一、先理清…

作者头像 李华
网站建设 2026/4/22 14:00:20

一文读懂密钥的分层管理机制:根密钥、密钥加密密钥、工作密钥

数字时代,我们的财产和秘密都锁在云端,而密钥就是打开这些锁的钥匙。如果把所有钥匙都串在同一串钥匙圈上,一旦丢失,后果不堪设想…… 你是否曾经把家门钥匙、车钥匙、办公室钥匙全部挂在同一个钥匙圈上?如果丢失&…

作者头像 李华
网站建设 2026/4/22 14:56:11

基于KeyarchOS的OpenClaw部署实战:打造数据中心7x24小时的“AI管家”

近期,开源AI代理与自动化平台OpenClaw凭借“本地优先、主动执行、多渠道交互”的核心能力,迅速成为GitHub热门项目,从个人办公到团队协作,掀起一场AI自动化效率革命。 浪潮信息云峦服务器操作系统KeyarchOS(简称KOS&a…

作者头像 李华
网站建设 2026/4/22 22:15:33

新手如何建立网站?2026年主流建站步骤与工具全指南

在数字时代,拥有一个专业、可靠的网站已成为个人展示、企业运营的基石。然而,对于许多非技术背景的创业者、博主或小型企业主而言,“建站”二字听起来往往伴随着复杂的技术和高昂的成本。事实上,只要理清步骤,选对工具…

作者头像 李华