Linux 平板分配器和缓存性能

Posted

技术标签:

【中文标题】Linux 平板分配器和缓存性能【英文标题】:Linux slab allocator and cache performance 【发布时间】:2018-03-25 17:01:06 【问题描述】:

来自指南understanding linux kernel 3rd edition,第 8.2.10 章,Slab coloring-

我们从第 2 章中知道,相同的硬件缓存行映射了许多不同的 RAM 块。在这个 在本章中,我们还看到相同大小的对象最终存储在缓存中的相同偏移量处。 在不同的slab中具有相同偏移量的对象将以相对较高的概率最终被映射 在同一缓存行中。因此,缓存硬件可能会浪费内存周期来传输两个对象 从同一高速缓存行来回到不同的 RAM 位置,而其他高速缓存行未得到充分利用。 板分配器尝试通过称为板着色的策略来减少这种令人不快的缓存行为:不同 将称为颜色的任意值分配给平板。

(1) 我无法理解平板着色试图解决的问题。当正常进程访问数据时,如果它不在缓存中并且遇到缓存未命中,则将数据与来自进程尝试访问的数据的周围地址的数据一起提取到缓存中以提高性能。如何会出现相同的特定缓存行不断被交换的情况?一个进程在两个不同内存区域的内存区域内不断访问相同偏移量的两个不同数据地址的概率非常低。即使确实发生了,缓存策略通常也会根据某些议程(例如 LRU、Random 等)选择要交换的行。不存在这样的策略可以根据被访问地址的最低有效位中的匹配来选择驱逐行.

(2) 我无法理解平板着色如何解决缓存问题,它从平板的末尾到开头占用空闲字节并导致不同平板的第一个对象具有不同的偏移量-交换问题?

[已解决] 经过一番小调查后,我相信我找到了问题的答案。答案已发布。

【问题讨论】:

【参考方案1】:

假设你有一个 256 KB 的缓存,它使用了一个超级简单的算法,它缓存 line = (real address AND 0x3FFFFF)。

现在,如果您在每个兆字节边界上都有平板,那么平板 1 中的第 20 项将把平板 2 的第 20 项踢出缓存,因为它们使用相同的缓存行标记。

通过偏移slab,不同的slab共享相同缓存行标记的可能性降低。如果 Slab 1 和 Slab 2 都保存 32 字节的对象,并且 Slab 2 偏移了 8 个字节,那么它的缓存标记将永远不会完全等于 Slab 1。

我确定我的某些细节有误,但请记住它的价值。

【讨论】:

让我看看我是否理解正确;考虑slab0切片地址0x0、0x20、0x40等。slab1切片地址0x8、0x28、0x48等。使用您提供的简单缓存行不会浪费任何缓存行,因为没有两个地址会给出相同的结果,对吧? 在阅读了有关缓存策略和缓存组织的信息后,我看不出您的答案与缓存基础知识的匹配程度如何。选择要交换的行是根据许多可能的策略之一选择的,例如 LRU,而不是根据地址的最低有效位的匹配,我找不到任何这样做的策略。 @user2162550:查找“虚假共享”并缓存。 我找到了我的答案,它与缓存关联性有关。您的回答是一个很好的参考,但缓存关联性级别指出了我的问题。【参考方案2】:

我想我明白了,答案与关联性有关。

一个缓存可以分成若干个集合,每个集合只能缓存一个特定的内存块类型在里面。例如,set0 将包含地址为 8 的倍数的内存块,set1 将包含地址为 12 的倍数的内存块。这样做的原因是为了提高缓存性能,避免每个地址都在整个缓存中搜索的情况.这样只需要搜索特定的一组缓存。

现在,来自链接Understanding CPU Caching and performance

从 Henessey 和 Patterson 的第 377 页,缓存放置公式如下: (块地址)MOD(缓存中的集合数)

让我们获取内存块地址0x10000008(来自slabX,颜色为C)和内存块地址0x20000009(来自slabY,颜色为Z)。对于大多数N(缓存中的集合数),<address> MOD <N> 的计算将产生不同的值,因此缓存数据的集合也不同。如果地址具有相同的最低有效位值(例如0x100000080x20000008),那么对于大多数N,计算将产生相同的值,因此块将碰撞到相同缓存集。

因此,通过为不同slab中的对象保持不同的偏移量(colors),slabs对象可能会到达缓存中的不同集合,并且不会碰撞相同的集合,整体缓存性能提高。

编辑: 此外,如果缓存是直接映射的,那么根据***CPU Cache,不存在缓存替换策略,并且模计算产生将存储内存块的缓存块:

直接映射缓存 在这种缓存组织中,主存中的每个位置只能进入缓存中的一个条目。因此,直接映射缓存也可以称为“单向集相联”缓存。它没有这样的替换策略,因为没有选择要驱逐哪个缓存条目的内容。这意味着如果两个位置映射到同一个条目,它们可能会不断地相互淘汰。虽然更简单,但直接映射缓存需要比关联缓存大得多才能提供可比的性能,而且更不可预测。令 x 为缓存中的块数,y 为内存的块数,n 为缓存中的块数,然后借助等式 x = y mod n 进行映射。

【讨论】:

有用的信息。此外,添加一些关于着色如何在物理内存地址的设置位中结束的信息也会很好(请记住,还有块偏移位和标记位)。可能应该有一些典型的缓存的具体例子的分析。 我最近在挖掘原因。我读了你的回答。很抱歉它不能说服我。除了举一个具体的例子,还有很多答案。是的,也许它适合这种情况。着色为所有块添加偏移量,从而避免两条线(即 A 与 B)碰撞。但这肯定会导致 A 与 C(另一个块/线,也偏移)碰撞。那么它最终是如何运作的呢?【参考方案3】:

经过多次学习和思考,我得到的解释似乎更合理,不仅仅是具体的地址示例。 首先要学习缓存、标签、集合、行分配等基础知识。

可以确定 colour_off 的单位是 linux 内核代码中的 cache_line_size。 colour_off 是基本的偏移量单位,colour 是 struct kmem_cache 中 colour_off 的数量。

int  __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
   cachep->align = ralign;
   cachep->colour_off = cache_line_size();  // colour_off's unit is cache_line_size
    /* Offset must be a multiple of the alignment. */
   if (cachep->colour_off < cachep->align)
      cachep->colour_off = cachep->align;
   .....
   err = setup_cpu_cache(cachep, gfp);

https://elixir.bootlin.com/linux/v4.6/source/mm/slab.c#L2056

所以我们可以分两种情况来分析。 首先是缓存>slab。 你看到slab 1slab2slab3 ...不可能发生碰撞,主要是因为缓存足够大,除了slab1 vsslab5可能发生碰撞。所以着色机制不是那么清楚,在提高性能的情况下。但是对于slab1和slab5我们只是忽略解释它的原因,我相信你在阅读以下内容后会解决它。

二是slab>缓存。 空行表示 color_off 或缓存行。显然,slab1 和slab2 不可能在由tick 和slab2、slab3 标记的线上发生碰撞。 我们确保着色机制优化两个相邻slab之间的两条线,更不用说slab1 vsslab3优化更多的线,2+2 = 4条线,你可以数一下。

总而言之,着色机制通过尽可能使用原本无用的内存来优化缓存性能(详细地只是优化开头和结尾的一些 colour_off 行,而不是其他仍然可以碰撞的行)。

【讨论】:

我不明白你的回答。我认为一般的答案是具有相同模数减少的地址(地址 mod N,其中 N 是缓存中的集合数)将存储在相同的缓存集中(假设没有完整的关联缓存放置策略)。因此稍微改变slabs地址将提高缓存利用率 这是一个非常不透明的,没有明确的解释。为什么会发生?图片说明了这一点。另外,如果cache >slab,我认为offset并没有优化多少。

以上是关于Linux 平板分配器和缓存性能的主要内容,如果未能解决你的问题,请参考以下文章

Linux 内核 内存管理内存管理架构 ③ ( Linux 内核中的内存管理模块 | 页分配器 | 不连续页分配器 | 内存控制组 | 硬件设备内存管理 | MMU | 页表缓存 | 高速缓存 )

Linux 内核 内存管理内存管理架构 ③ ( Linux 内核中的内存管理模块 | 页分配器 | 不连续页分配器 | 内存控制组 | 硬件设备内存管理 | MMU | 页表缓存 | 高速缓存 )

Linux [buff/cache]内存缓存占用过高分析和优化

Linux 系统缓存机制学习

Linux系统清除缓存

linux学习之缓存机制