内存 models-/Cache 一致性协议:TSO 如何与 MESIF 一起使用
Memory models-/Cache coherence protocols: How TSO goes together with MESIF
刚刚完成我的系统编程讲座 material,我偶然发现了内存模型和缓存一致性协议的关键概念。虽然它们作为独立的概念是有意义的,但它们如何结合在一起并不十分清楚。具体来说,在查看 x86 时,我正在使用执行 TSO 内存模型的 ISA,以及使用 MESIF 缓存一致性协议的 CPU(对于 Intel)。
一开始,教授引入了缓存一致性协议,以确保对于芯片中的任何内核,它们看起来都好像都访问一个大的单片内存块。然后,在结束缓存一致性之后,他继续研究内存模型,特别是 TSO(我们已经在并行编程 class 中介绍了 linearizability-/sequential 一致性)。以下直接引用material关于x86内存模型的讲座:
- Standard for 64-bit x86 processors
- Sometimes called Total Store Ordering (TSO)
- Earlier 32-bit x86 implemented PRAM – weaker!
- Write-to-read relaxation: later reads can bypass earlier writes
- All processors see writes from one processor in the order they were issued.
- Processors can see different interleavings of writes from different processors.
似乎我们 "solved" 通过在缓存层次结构中引入什么是(又一个)层,即(有序的)存储缓冲区来解决顺序一致性慢的问题。
对我来说,TSO 似乎与缓存一致性原则正交。我们非常努力地让我们的缓存匹配,只是为了在两者之间添加另一个缓存一致性未涵盖的层。
问题:
- 为什么缓存一致性协议未涵盖存储缓冲区?是否假设从存储缓冲区回写到 L1 的速度如此之快,以至于在大多数情况下,中间回写导致的不一致不会成为问题? (即我估计存储缓冲区 -> L1 传输只需要几个周期,所以一旦 L1 接收到数据,它就会通过总线发送一个事务,告诉其他内核使它们的副本无效)
- 缓存一致性和内存模型这两个概念应该怎么理解?按照我的理解,内存模型是我们想要的理论概念,缓存一致性是实现该模型的实际实现的一部分。
非常感谢您的澄清!
最好的,
菲利克斯
顺序一致性模型是共享内存并行编程最常规定的内存模型。包含多个任务或线程的并行程序,顺序一致性需要两个条件,如下所述。
- 程序顺序执行:每个任务中的所有内存操作似乎都按照该任务的程序顺序执行。
- 内存访问原子性:内存操作(在并行程序的所有任务中)似乎一次执行一个。
每个程序员都假设这些条件来推理他们的并行程序。
不幸的是,顺序一致性模型并没有想象中那么有用。主要原因是这两个属性的实现成本。执行这些
属性禁止许多基本的编译器和硬件优化[1]。
提出了其他 weak/relaxed 内存模型来放宽这些属性并允许编译器和硬件优化。这些弱记忆模型交易
性能的可编程性。
为什么缓存一致性协议未涵盖存储缓冲区?
出于性能原因,这是 TSO 的设计选择。从存储缓冲区提供加载服务或在其前一个存储(不同地址)仍在存储缓冲区中时提供加载服务,可减少存储延迟。为了保持存储缓冲区的一致性,加载必须等到所有其他处理器确认收到存储生成的无效数据。而且,大多数时候,其他缓存中可能没有任何存储地址的副本(变量是任务的本地变量),那么等待确认是浪费时间。如果其他任务共享此变量,则可以使用原子或栅栏指令显式强制等待确认。
缓存一致性和内存模型这两个概念应该怎么想?
缓存一致性协议涉及将存储序列化到相同的内存位置,并确保加载 returns 最近存储的值到相同的内存位置。缓存一致性协议仅在存在缓存或同一内存位置的多个副本时才需要,其工作是保持所有副本的一致性。
内存一致性模型与(同一任务的)加载和存储到不同内存位置的相对顺序有关。任何涉及执行共享内存并行程序(多个任务或线程通过共享内存通信)的系统都必须定义其内存一致性模型。
从广义上讲,缓存一致性协议实现了内存一致性模型的一部分。更准确地说,它是核心管道和高速缓存一致性协议(以及内存指令遍历的所有其他组件)必须遵守内存模型规范的组合。
[1]: Shared memory consistency models: a tutorial
刚刚完成我的系统编程讲座 material,我偶然发现了内存模型和缓存一致性协议的关键概念。虽然它们作为独立的概念是有意义的,但它们如何结合在一起并不十分清楚。具体来说,在查看 x86 时,我正在使用执行 TSO 内存模型的 ISA,以及使用 MESIF 缓存一致性协议的 CPU(对于 Intel)。
一开始,教授引入了缓存一致性协议,以确保对于芯片中的任何内核,它们看起来都好像都访问一个大的单片内存块。然后,在结束缓存一致性之后,他继续研究内存模型,特别是 TSO(我们已经在并行编程 class 中介绍了 linearizability-/sequential 一致性)。以下直接引用material关于x86内存模型的讲座:
- Standard for 64-bit x86 processors
- Sometimes called Total Store Ordering (TSO)
- Earlier 32-bit x86 implemented PRAM – weaker!
- Write-to-read relaxation: later reads can bypass earlier writes
- All processors see writes from one processor in the order they were issued.
- Processors can see different interleavings of writes from different processors.
似乎我们 "solved" 通过在缓存层次结构中引入什么是(又一个)层,即(有序的)存储缓冲区来解决顺序一致性慢的问题。 对我来说,TSO 似乎与缓存一致性原则正交。我们非常努力地让我们的缓存匹配,只是为了在两者之间添加另一个缓存一致性未涵盖的层。
问题:
- 为什么缓存一致性协议未涵盖存储缓冲区?是否假设从存储缓冲区回写到 L1 的速度如此之快,以至于在大多数情况下,中间回写导致的不一致不会成为问题? (即我估计存储缓冲区 -> L1 传输只需要几个周期,所以一旦 L1 接收到数据,它就会通过总线发送一个事务,告诉其他内核使它们的副本无效)
- 缓存一致性和内存模型这两个概念应该怎么理解?按照我的理解,内存模型是我们想要的理论概念,缓存一致性是实现该模型的实际实现的一部分。
非常感谢您的澄清!
最好的, 菲利克斯
顺序一致性模型是共享内存并行编程最常规定的内存模型。包含多个任务或线程的并行程序,顺序一致性需要两个条件,如下所述。
- 程序顺序执行:每个任务中的所有内存操作似乎都按照该任务的程序顺序执行。
- 内存访问原子性:内存操作(在并行程序的所有任务中)似乎一次执行一个。
每个程序员都假设这些条件来推理他们的并行程序。 不幸的是,顺序一致性模型并没有想象中那么有用。主要原因是这两个属性的实现成本。执行这些 属性禁止许多基本的编译器和硬件优化[1]。 提出了其他 weak/relaxed 内存模型来放宽这些属性并允许编译器和硬件优化。这些弱记忆模型交易 性能的可编程性。
为什么缓存一致性协议未涵盖存储缓冲区?
出于性能原因,这是 TSO 的设计选择。从存储缓冲区提供加载服务或在其前一个存储(不同地址)仍在存储缓冲区中时提供加载服务,可减少存储延迟。为了保持存储缓冲区的一致性,加载必须等到所有其他处理器确认收到存储生成的无效数据。而且,大多数时候,其他缓存中可能没有任何存储地址的副本(变量是任务的本地变量),那么等待确认是浪费时间。如果其他任务共享此变量,则可以使用原子或栅栏指令显式强制等待确认。
缓存一致性和内存模型这两个概念应该怎么想?
缓存一致性协议涉及将存储序列化到相同的内存位置,并确保加载 returns 最近存储的值到相同的内存位置。缓存一致性协议仅在存在缓存或同一内存位置的多个副本时才需要,其工作是保持所有副本的一致性。
内存一致性模型与(同一任务的)加载和存储到不同内存位置的相对顺序有关。任何涉及执行共享内存并行程序(多个任务或线程通过共享内存通信)的系统都必须定义其内存一致性模型。
从广义上讲,缓存一致性协议实现了内存一致性模型的一部分。更准确地说,它是核心管道和高速缓存一致性协议(以及内存指令遍历的所有其他组件)必须遵守内存模型规范的组合。 [1]: Shared memory consistency models: a tutorial