std*_*out 3 memory io cpu concurrency dma
我想知道如果 2 个 CPU 内核同时尝试访问内存(通过内存控制器),“一般情况下”如何处理内存访问?实际上,当内核和支持 DMA 的 IO 设备尝试以相同的方式访问时,这同样适用。
我认为,内存控制器足够智能,可以利用地址总线并同时处理这些请求,但是我不确定当它们尝试访问同一位置或 IO 操作垄断地址总线并且没有 CPU 空间时会发生什么继续前进。
谢谢
简短的回答是“它很复杂,但在某些情况下访问肯定可能并行发生”。
我觉得你的问题是有点太黑与白:你可能会寻找像“是的,多台设备可以在访问内存的答案相同的时间”或“不,他们不能”,但现实情况是,首先你” d 需要描述一些具体的硬件配置,包括一些底层的实现细节和优化特性,才能得到准确的答案。最后,您需要准确定义“同一时间”的含义。
一般来说,一个好的一阶近似是硬件会使所有硬件看起来几乎可以同时访问内存,可能会由于争用而导致延迟增加和带宽减少。在非常细粒度的时序级别访问一个设备可能确实推迟另一个设备的访问,也可能不会,这取决于许多因素。您极不可能需要这些信息来正确实施软件,而且您甚至不太可能需要了解细节才能最大限度地提高性能。
也就是说,如果您真的需要了解详细信息,请继续阅读,我可以对某种理想化的 latpop/桌面/服务器级硬件进行一些一般性观察。
正如马蒂亚斯所提到的,您首先必须考虑缓存。缓存意味着任何受缓存影响的读或写操作(包括几乎所有 CPU 请求和许多其他类型的请求)可能根本不接触内存,因此从这个意义上说,许多内核可以“访问”内存(至少缓存它的图像)同时。
如果您随后考虑在所有缓存级别中未命中的请求,您需要了解内存子系统的配置。通常,RAM 芯片一次只能做“一件事”(即,命令1这样的读写适用于整个模块)并且通常扩展到由几个芯片组成的 DRAM 模块以及一系列连接的 DRAM通过总线连接到单个内存控制器。
所以你可以说从电气上来说,一个内存控制器和它所连接的 RAM的组合很可能一次只做一件事情。现在这件事通常类似于从物理连续的字节范围中读取字节,但该操作实际上可以帮助同时处理来自不同设备的多个请求:即使每个设备向控制器发送单独的请求,良好的实现也会将请求合并到相同或附近的2个内存区域。
此外,即使是 CPU 也可能具有这样的能力:当一个新请求发生时,它可以/必须注意到一个现有的请求正在处理重叠区域,并将新请求与旧请求联系起来。
不过,您可以说,对于单个内存控制器,您通常一次只处理一个设备的请求,而没有合并请求的异常机会。现在请求本身通常是纳秒级的,因此可以在一小段时间内处理许多单独的请求,因此这种“排他性”是细粒度的,通常不会引起注意3。
现在上面我小心地将讨论限制在单个内存控制器上——当你有多个内存控制器时4你绝对可以让多个设备同时访问内存,即使是在 RAM 级别。这里每个控制器本质上是独立的,因此如果来自两个设备的请求映射到不同的控制器(不同的 NUMA 区域),它们可以并行处理。
这就是长答案。
1事实上,命令流比“读”或“写”之类的东西更底层、更复杂,它涉及诸如打开内存页、从中流式传输字节等概念。每个程序员都应该了解的有关内存的知识可用作该主题的出色介绍。
2例如,假设有两个对内存中相邻字节的请求:如果它们适合总线宽度,控制器可以将它们合并为一个请求。
3当然,如果你在多台设备上争夺内存,整体影响可能非常明显:每台设备带宽减少,延迟增加,但我的意思是,共享足够细粒度,你可以通常不会区分精细切片的独占访问和一些假设设备之间的区别,这些设备在每个时期对每个请求同时进行。
4现代硬件上最常见的配置是每个插槽一个内存控制器,因此在 2P 系统上,您通常有两个控制器,当然也可以使用其他配给(更高和更低)。