Memory 缓存读取系统内存与cpu读取系统内存

Memory 缓存读取系统内存与cpu读取系统内存,memory,arm,cpu-architecture,cpu-cache,Memory,Arm,Cpu Architecture,Cpu Cache,在运行Android/Linux的基于arm的SoC上,我观察到以下几点: 为设备DMA输入分配一个未缓存的内存区。DMA完成后,此内存区域的内容将复制到另一个系统内存区域 为设备DMA输入将内存区域分配为缓存。DMA完成后,使内存范围无效,然后将此内存区域的内容复制到另一个系统内存区域 分配的内存区域大小约为2MB,大于缓存大小(二级缓存大小为256KB) 方法2比方法1快10倍 即:方法2的内存复制操作比方法1快x10 我推测,方法2在复制时使用从系统内存缓存线大小读取的缓存,方法1需要通过

在运行Android/Linux的基于arm的SoC上,我观察到以下几点:

  • 为设备DMA输入分配一个未缓存的内存区。DMA完成后,此内存区域的内容将复制到另一个系统内存区域
  • 为设备DMA输入将内存区域分配为缓存。DMA完成后,使内存范围无效,然后将此内存区域的内容复制到另一个系统内存区域
  • 分配的内存区域大小约为2MB,大于缓存大小(二级缓存大小为256KB)

    方法2比方法1快10倍

    即:方法2的内存复制操作比方法1快x10

    我推测,方法2在复制时使用从系统内存缓存线大小读取的缓存,方法1需要通过绕过缓存硬件从系统内存总线事务大小读取cpu


    但是,我找不到明确的解释。我很感谢能提供详细解释的人。

    涉及的硬件项目太多,很难给出具体说明。SOC在很大程度上决定了这一点。然而,您观察到的是现代ARM系统的典型性能

    主要因素是。所有DRAM都由“行”和“列”构成。在DRAM芯片上,一次可以读取整个“行”。也就是说,有一个晶体管矩阵,有一个物理点/接线,可以读取整行(实际上可能有SRAM将该行存储在芯片上)。当您阅读另一个“列”时,您需要“取消充电/预充电”接线以访问新的“行”。这需要一些时间。主要的一点是,DRAM可以在大数据块中快速读取顺序内存。此外,由于内存随每个时钟边缘流出,因此没有命令开销

    如果将内存标记为未缓存,则CPU/SOC可能会发出单拍读取。通常,在单个读/写过程中,这些设备将“预充电”,消耗额外的周期,并且必须向DRAM设备发送许多额外的命令


    SDRAM也有“银行”。银行有一个单独的“行”缓冲区(静态RAM/多管存储器),允许您从一个银行读取到另一个银行,而无需重新充电/读取。银行之间往往相距甚远。如果您的操作系统已将“未缓存”内存从第二个“缓存”区域物理分配到另一个存储库中,那么这也将增加额外的效率。在操作系统中,单独管理缓存/未缓存内存是很常见的(针对MMU问题)。内存池通常距离足够远,可以放在单独的存储组中。

    如您所述:如果将内存标记为未缓存,则CPU/SOC可能会发出单拍读取。缓存的情况如何?我知道这可能与实现有关,对于如何(通过缓存控制器)读入数据,是否有一种常见的做法?thanksCache要么是命中(缓存中),要么是未命中。如果是未命中,则会将其放入缓存中,但必须清除某些内容。这是通过“方式”机制和随机或LRU(最近使用)更换完成的。但是,对于
    memcpy()
    ,缓存并不重要。您不重用数据,因此缓存对编写良好的
    memcpy()
    没有任何好处。通常的做法是缓存线。它通常是一个或两个SDRAM突发读/写大小(不是行长度)。如果您按顺序读取一行,则不必重新发出命令(预充电)。典型的最大DDR bw约为时钟速率。也就是说,由于命令开销,16位500MHz DDR大约为1GB/s。问题不在于“缓存”版本能够通过缓存访问服务所有后续请求,而非缓存版本必须始终通过内存获取数据。