其他的一周,我写了一个小螺类和一的方式消息管允许之间的通信线(两个管每线,显然,对双向通信)。一切工作的现在我的速64X2,但我想知道如果我想遇到任何问题,如果两个线都在看同一个变量和局部的缓存值为这个变量在每一个的核心是同步。

我知道的 易失性 关键词将力的一个变量以刷新记忆,但是没有一种方法,在多核x86处理武力的高速缓存的所有核心同步?这是我需要担心,或将 易失性 并且适当地使用轻型锁定机制(我采用_InterlockedExchange设置我的挥发性管变量)处理所有的情况下,我想写"锁"的代码,用于多核x86Cpu?

我已经知道的和有用的关键部分,互斥、事件,等等。我主要想知道,如果有x86内部函数,我不知道还有其力量或可以用来强制执行高速缓存的一致性。

有帮助吗?

解决方案

volatile 只有你的部队码要重新阅读的价值,它无法控制的价值是从阅读。如果价值是最近读过你的代码然后它可能会在缓存,在这种情况下,挥发性会迫使它将重新阅读,从高速缓存,而不是从存储器。

没有很多的高速缓存相关性的说明x86。没取指示喜欢 prefetchnta, 但这不会影响记忆排序的语义。它使用的是实现由带来的价值L1高速缓冲存储器而不污染L2,但是事情更复杂的现代英特尔的设计有一个很大的共享 包容 L3缓存。

x86处理器使用的变化 MESI协议 (MESIF英特尔,MOESI AMD),以保持他们的高速缓存连贯与每一个其他(包括私L1缓存的不同核心).一个核心要写一个高速缓冲存储器行有力的其他核心,以使他们复制它之前,它可以改变其自身的复制从共同来修改的状态。


你不需要任何栅栏的说明(如MFENCE)产生的数据在一个线程和消费它在另一个在x86,因为x86载荷/店 获取/剥义 内置。你需要MFENCE(全屏障),获得顺序的一致性。(以前的版本的这个答案建议, clflush 是需要的,这是不正确的).

你需要防止 编译时间重新排序, 因为C++'s存储器模型是弱命令。 volatile 是一个古老的,不好的方式来做到这一点;C++11std::原子是一个更好的方式来编写锁码。

其他提示

高速缓存相干性芯之间由于x86处理器中使用的MESI协议保证。你只需要担心内存的一致性与数据的同时仍然在内核的缓存选址可能访问内存的外部硬件打交道时。不像是你的情况下,在这里,虽然,因为文本建议你在用户级编程。

你不需要担心的高速缓存的一致性。硬件将采取的照顾。什么你可能需要担心的是性的问题,由于这一高速缓存的一致性。

如果核心#1写入一个变量,即使所有其他副本的高速缓存线的在其他核心(因为它已经得到 独家所有权 高速缓存线之前犯下的商店)。当核心#2读,同变量,它将错失在高速缓冲存储器(除非核心#1已编写的这回如今作为一个共用的水平的缓冲存储)。

由于整个缓线(64字节)已经可以从中读取存储器(或书面回来的共存,然后读取通过核心#2),将会有一些性能的成本。在这种情况下,这是不可避免的。这是所期望的行为。


问题是,当你有多个变量在同一个缓线,处理器可能会花费额外的时间保留的缓存在同步,即使核心是阅读或写作不同的变量内,同样的超高速缓冲存储器线。

该成本可避免通过确保这些变量不在相同的超高速缓冲存储器线。这种效应被称为 假共享 因为你是强迫处理同步的价值观的对象是不实之间共享的螺纹。

挥发性将不这样做。在C ++中,易失性仅影响编译器优化如在寄存器而非存储器中存储的变量,或者完全将其移除。

您没有说明您正在使用的编译器,但如果你使用的是Windows,看一看的这篇文章这里。也看看这里 ynchronization功能>。您可能要注意,通常volatile是不够的,做你想要它做的事情,但在2005年VC和2008下,也有不规范的语义添加到它那加暗示的记忆障碍,围绕读取和写入。

如果你想要的东西是便携式的,你将不得不提前你一个更难的道路。

有一系列文章,说明现代化的架构存储器 在这里,, 包括 英特尔的酷睿2缓存 和更多的现代建筑的主题。

文章也很容易阅读和良好的说明。享受!

您的问题中有几个子问题,因此我将尽我所知回答它们。

  1. 目前还没有在 C++ 中实现无锁交互的可移植方法。C++0x 提案通过引入原子库解决了这个问题。
  2. Volatile 不保证在多核上提供原子性,并且其实现是特定于供应商的。
  3. 在 x86 上,您不需要做任何特殊的事情,除了将共享变量声明为 volatile 以防止某些可能破坏多线程代码的编译器优化之外。易失性告诉编译器不要缓存值。
  4. 有些算法(例如 Dekker)即使在具有易失性变量的 x86 上也无法工作。
  5. 除非您确定在线程之间传递数据访问是程序中的主要性能瓶颈,否则请远离无锁解决方案。使用按值或锁传递数据。

以下是一篇好文章中参考使用 volatile w/螺纹的程序。

易失性几乎无用的多线程.

香草萨特似乎只需建议的任意两个变量应该驻留在单独的高速缓存行。他这样做在他的并发队列与他锁和节点指针之间填充。

编辑:如果您在使用英特尔编译器GCC或者,你可以使用的原子建宏的,这似乎尽最大可能的情况下优先占有高速缓存中。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top