如何防止两个进程争夺公共缓存?

时间:2016-01-18 21:38:51

标签: multithreading caching mpi cpu-cache

考试时我被问到这个问题。我们在同一个CPU中有两个CPU或两个内核共享一个公共缓存(例如,L3)。在每个CPU上都有一个MPI进程(或一个共同进程的线程)。我们如何确保这两个进程不会发生干扰,这意味着它们不会将每个进程输入或者使用每个或类似的缓存的一半。目标是在这里提高内存访问速度。

操作系统是某种Unix,如果这很重要的话。

3 个答案:

答案 0 :(得分:3)

根据您的评论,似乎需要“教科书答案”,因此我建议在进程之间对缓存进行分区。这样,您可以保证它们不会在相同的缓存集上竞争并相互颠簸。这假设您不希望在两个进程之间实际共享任何内容,在这种情况下,此方法将失败(尽管可能的修复方法是将缓存空间分为3 - 一个范围用于每个进程,一个用于共享数据)。

由于您可能不希望重新设计缓存并提供硬件分区方案(除非问题出现在计算机体系结构课程的范围内),实现此目的的最简单方法就是检查缓存大小和关联性,计算我们的集合数量,并将每个进程/线程的数据集对齐到不同的部分。

例如,如果您的共享缓存大小为2MB,并且有16路和64B线,那么您将拥有2k套。在这种情况下,每个进程都希望将其物理地址(假设缓存是物理映射的)与不同的半1k集对齐,或者将每个0x20000中的不同0x10000对齐。换句话说,P0可​​以自由地使用位16等于0的任何物理地址,P1将使用位16等于1的地址。

注意,由于它超过了基本4k页面的大小(对齐为0x1000),您需要破解操作系统以将页面分配给每个进程的相应物理地址,或者只是使用更大的页面(2M)就够了)。 另请注意,通过保持每个分配的连续0x10000,我们仍然享受空间局部性和高效的硬件预取(否则您可以通过使用第6位简单地选择任何其他分割,甚至偶数/奇数集,但这会使您的数据断开。

最后一个问题是对于大于此0x10000配额的数据集 - 要进行对齐,您只需要将它们分成最多为0x10000的块,并将它们分别对齐。还有代码/堆栈/页面映射和其他类型的操作系统/系统数据的问题,你可以控制较少(实际上代码也可以对齐,或者更有可能在这种情况下 - 共享) - 我假设这可以忽略不计在捶打。

再次 - 这会尝试在不知道您使用什么系统,您需要实现什么,甚至是课程背景的情况下回答。有了更多的上下文,我们可以将其重点放在一个更简单的解决方案上。

答案 1 :(得分:1)

缓存中的方式有​​多大?

例如,如果您有一个缓存,其中每条路的大小为128KiB,则对内存进行分区,使得对于每个模128KiB的地址,进程A使用0-64KiB区域,进程B使用低64KiB -128KiB地区。 (这假定私有L1-per-core)。

如果您的物理页面大小是4KiB(并且您的CPU使用物理地址进行缓存,而不是虚拟 - 这在某些CPU上会发生),您可以使这个更好。假设您将相同数量的内存映射到每个内核的虚拟地址空间 - 16KiB。第0,2,4,6页进入处理A的存储器映射,第1,3,5,7页进入处理B的存储器映射。只要您只在精心布局的区域中处理内存,缓存就永远不应该打架。当然,你通过这样做有效地减少了缓存方式的大小,但是你有多种方式......

答案 2 :(得分:0)

您需要在多线程编程方面使用锁定。由于不了解您的具体情况,很难提供示例。

当一个进程具有访问权限时,将所有其他进程锁定,直到“访问”进程完成该资源。