多核 DMA 性能损耗

📅 发布时间:2026/7/5 8:57:50 👁️ 浏览次数:
多核 DMA 性能损耗
核心就 3 条根因CPU 缓存一致性CCE/coherency冲突缓存抖动、反复 flush/invalidate 造成 “空跑周期”总线争用、内存带宽瓶颈、跨 NUMA 访问这些在单核基本不明显多核高并发 DMA会被剧烈放大。最核心损耗Cache 一致性 缓存冲刷DMA 是非一致性访问绝大多数设备设备直接读写内存不看 CPU CacheCPU 写的数据还在 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看到大量cacheflush、dsb、isb、bus lock这就是DMA 导致的多核扩展性极差。第二大损耗伪共享 缓存行乒乓很多驱动设计一个 DMA 描述符descriptor被多个核同时访问完成状态、所有权、控制位混在同一缓存行64B后果核 A 改完 → 核 B 的缓存行立即失效核 B 再改 → 核 A 又失效缓存行在核之间来回弹跳ping-pong即使没有 DMA 流量多核并发访问同一个小结构就会吃掉大量性能。第三大损耗NUMA 下的跨节点 DMA设备在 NUMA node 0内存分配在 node 1DMA CPU 访问都要走跨 NUMA 链路表现延迟翻倍带宽上不去多核并发时NUMA 链路拥塞所有核一起变慢第四PCIe / 总线争用与中断风暴多设备 / 多队列同时 DMA → PCIe 带宽打满大量短小包 DMA →往返握手开销 数据传输多核分散处理中断 → 频繁核间迁移、缓存重建典型网卡多队列收小包CPU 利用率很高但 PPS 上不去大量sys、irq、softirqIPC指令 / 周期暴跌内核中 DMA 与缓存一致性的关键机制1. 两类 DMA 映射决定你要不要 flush(1) 非一致性映射最常见、最耗性能dma_map_single(..., DMA_FROM_DEVICE/TO_DEVICE)内核必须 flush /invalidate多核下开销巨大(2) 一致性映射coherentdma_alloc_coherent()内存属性设置为Non-cacheable 或 Write-throughCPU 写直通内存不需要 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 不走跨 NUMACPU 访问本地内存多核扩展性立刻提升6. 尽量使用硬件 IOMMU snoop 支持SMMU/Snoop IO如果平台 / 设备支持IO coherencysnoopable DMA硬件自动保证缓存一致驱动完全不需要 flush dcache多核性能几乎无损耗这是终极解法但依赖PCIe NoSnoop 0设备支持 ACS、snoopIOMMU 开启并配置正确核心结论多核 DMA 性能损耗 90% 来自缓存 flush/invalidate 缓存行伪共享 NUMA 跨节点 中断 / 队列未绑定。最优解队列核绑定、同 NUMA、缓存隔离、批量 DMA、能开硬件 snoop 就全开。