缓存一致性有什么意义?

时间:2010-07-14 00:34:05

标签: multithreading caching concurrency x86 low-level

在像x86这样提供缓存一致性的CPU上,从实际角度来看这有什么用呢?我知道这个想法是在一个核心上完成内存更新,在所有其他核心上立即可见。这是一个有用的属性。但是,如果不用汇编语言编写,就不能过分依赖它,因为编译器可以在寄存器中存储变量赋值,而不会将它们写入内存。这意味着必须采取明确的步骤,以确保在当前线程中可以看到在其他线程中完成的内容。因此,从实际角度来看,缓存一致性实现了什么?

6 个答案:

答案 0 :(得分:10)

简短的说法是,非缓存一致系统特别难以编程,特别是如果你想保持效率 - 这也是今天大多数NUMA系统都是缓存一致的主要原因。

如果缓存不一致,“显式步骤”必须强制执行一致性 - 显式步骤通常是关键部分/互斥体(例如,C / C ++中的volatile是非常的)。对于诸如互斥体之类的服务来说,如果不是不可能只跟踪那些已经发生变化且需要在所有缓存中更新的内存,那将非常困难 - 这可能需要更新所有内存,即使它甚至可以跟踪哪些内核在其缓存中具有哪些内存。

可以预测硬件可以在跟踪已更改的内存地址/范围方面做得更好,更高效,并使它们保持同步。

并且,假设一个进程在核心1上运行并被抢占。当它再次被安排时,它被安排在核心2上。

如果缓存不是很有效,这将是非常致命的,否则核心1的缓存中可能存在过程数据的残余,而核心2的缓存中不存在这些残余。但是,对于以这种方式工作的系统,操作系统必须在调度线程时强制执行缓存一致性 - 这可能是“更新所有内核之间的缓存中的所有内存”操作,或者它可能跟踪脏页面MMU的帮助,只同步已更改的内存页面 - 再次,硬件可能使缓存以更精细和有效的方式保持连贯。

答案 1 :(得分:8)

其他作者的回应并没有涵盖一些细微差别。

首先,请考虑CPU不是逐字节处理内存,而是使用缓存行。一行可能有64个字节。现在,如果我在位置P分配一个2字节的内存,而另一个CPU在位置P + 8分配一个8字节的内存,并且P和P + 8都存在于同一个缓存线上,请观察没有缓存一致性两个CPU不能同时更新P和P + 8而不会破坏彼此的变化!因为每个CPU都在高速缓存行上进行读 - 修改 - 写,所以它们都可能写出不包含其他CPU更改的行的副本!最后一位作家将获胜,你对记忆的一次修改会“消失”!

要记住的另一件事是区分一致性和一致性。因为即使x86派生的CPU使用存储缓冲区,也没有保证您可能期望已经完成的指令修改了内存,使得其他CPU可以看到这些修改,即使编译器已决定将值写回记忆(也许是因为volatile?)。相反,mod可能位于商店缓冲区中。通常使用的所有CPU都是缓存一致的,但很少有CPU具有与x86一样宽容的一致性模型。例如,请查看http://www.cs.nmsu.edu/~pfeiffer/classes/573/notes/consistency.html以获取有关此主题的更多信息。

希望这有帮助,顺便说一句,我在Corensic工作,这是一家正在构建并发调试器的公司,您可能想要查看。当关于并发性,连贯性和一致性的假设被证明是没有根据时,它有助于获取部分:)

答案 2 :(得分:7)

想象一下你这样做:

lock(); //some synchronization primitive e.g. a semaphore/mutex
globalint = somevalue;
unlock();

如果没有缓存一致性,那么最后unlock()必须确保globalint现在随处可见,缓存一致性所需要做的就是将其写入内存并让硬件做魔术。一个软件解决方案可以保持哪些内存存在于哪个内存中,哪些内核,以及某种方式确保它们在原子上同步。

如果您能找到一个软件解决方案来跟踪需要保持同步的缓存中存在的所有内存,那么您将赢得奖励,这比当前的硬件解决方案更有效。

答案 3 :(得分:1)

当您处理多个线程并从多个线程访问相同的变量时,缓存一致性变得非常重要。在这种特殊情况下,您拥有以确保所有处理器/核心在同时访问变量时确实看到相同的值,否则您将具有奇妙的非确定性行为。

答案 4 :(得分:1)

锁定不需要它。如果需要,锁定代码将包括缓存刷新。主要需要确保不同处理器对同一缓存行中的不同变量的并发更新不会丢失。

答案 5 :(得分:0)

高速缓存一致性是在硬件中实现的,因为程序员不必担心在多核/多处理器环境中运行时确保所有线程都能看到内存位置的最新值。缓存一致性给出了一个抽象,即所有核心/处理器都在一个统一的缓存上运行,尽管每个核心/处理器都有自己的独立缓存。

它还确保传统的多线程代码在新的处理器型号/多处理器系统上工作,而无需进行任何代码更改以确保数据的一致性。