当前位置:  开发笔记 > 编程语言 > 正文

我可以在多核x86 CPU上强制缓存一致吗?

如何解决《我可以在多核x86CPU上强制缓存一致吗?》经验,为你挑选了5个好方法。

另一周,我写了一个小线程类和一个单向消息管道,以允许线程之间的通信(每个线程两个管道,显然,用于双向通信).在我的Athlon 64 X2上一切正常,但我想知道如果两个线程都在查看相同的变量并且每个核心上的此变量的本地缓存值不同步,我是否会遇到任何问题.

我知道volatile关键字会强制变量从内存中刷新,但多核x86处理器是否有办法强制所有内核的缓存同步?这是我需要担心的事情,还是易失性和正确使用轻量级锁定机制(我使用_InterlockedExchange设置我的易失性管道变量)处理我想为多核x86 CPU编写"无锁"代码的所有情况?

我已经知道并使用了Critical Sections,Mutexes,Events等等.我主要想知道是否有x86内在函数,我不知道哪种力量或可用于强制缓存一致性.



1> SoapBox..:

volatile只强制您的代码重新读取该值,它无法控制从中读取值的位置.如果你的代码最近读取了这个值,那么它可能会在缓存中,在这种情况下,volatile会强制它从缓存中重新读取,而不是从内存中读取.

x86中没有很多缓存一致性指令.有预取指令prefetchnta,但不影响内存排序语义.它曾经通过将值带到L1缓存而不会污染L2来实现,但对于具有大型共享包含 L3缓存的现代英特尔设计而言,情况更为复杂.

x86 CPU的使用上的变化MESI协议(MESIF英特尔,MOESI为AMD),以保持它们的高速缓存相干互相(包括不同的内核的专用L1高速缓存).想要编写缓存行的核心必须强制其他核心使其副本无效,然后才能将其自己的副本从"共享"更改为"已修改"状态.


您不需要任何围栏指令(如MFENCE)在一个线程中生成数据并在x86上使用另一个线程,因为x86加载/存储具有内置的获取/释放语义.您确实需要MFENCE(全屏障)以获得顺序一致性.(此答案的先前版本表明clflush需要,这是不正确的).

您确实需要阻止编译时重新排序,因为C++的内存模型是弱排序的. volatile这是一个古老而糟糕的方式; C++ 11 std :: atomic是一种更好的编写无锁代码的方法.


答案是对的.@SoapBox可能意味着cpu缓存 - 但你所说的是将结果缓存到寄存器中.本质上,volatile用于声明"设备寄存器"变量 - 它告诉编译器"这不是从内存中读取,而是从外部源读取" - 因此编译器会在任何时候重新读取它,因为它不能确保读取值等于上次写入的值.如果你的实现的"读取"被定义为发出"loadw",那么它肯定会从CPU缓存中读取 - 但从C的角度来看这很好.

2> 小智..:

由于x86处理器采用的MESI协议,核心之间保证了高速缓存一致性.在处理外部硬件时,您只需要担心内存一致性,外部硬件可能会在数据仍位于内核缓存上时访问内存.但是,这看起来不像你的情况,因为文本暗示你在用户区编程.


MESI协议不在x86中使用,但MESIF和MOESI是.
x86确实处理连贯性.但是要读取内存*一致性*:不能保证所有写入(例如写入数据和释放锁定,以及命名为2)将以相同的顺序对所有CPU可见!这就是记忆围栏的用途.
@Wim On x86/x64内存写入保证以相同的顺序可见,因此在此平台上不需要内存防护,唯一可能的问题是编译器重新排序.阅读英特尔开发人员手册或此处获取简短版本http://www.multicoreinfo.com/research/papers/2008/damp08-intel64.pdf

3> Ferruccio..:

您不必担心缓存一致性.硬件将负责这一点.您可能需要担心的是由于缓存一致性导致的性能问题.

如果核心#1写入变量而核心#2读取相同的变量,则处理器将确保更新核心#2的高速缓存.由于必须从内存中读取整个高速缓存行(64字节),因此会产生一些性能成本.在这种情况下,这是不可避免的.这是期望的行为.

问题是,当您在同一缓存行中有多个变量时,即使内核正在同一缓存行中读取/写入不同的变量,处理器也可能会花费额外的时间来保持缓存同步.通过确保这些变量不在同一缓存行中,可以避免该成本.此效果称为False Sharing,因为您强制处理器同步线程之间实际不共享的对象的值.


"必须从内存中读取"位有误导性,因为数据可能会从另一个缓存中窥探​​.
我没有想到这一点.我假设仍然会有性能成本,但与RAM的读取幅度不同.

4> dsimcha..:

挥发无法做到.在C++中,volatile仅影响编译器优化,例如将变量存储在寄存器而不是内存中,或者完全删除它.



5> Eclipse..:

您没有指定要使用的编译器,但如果您使用的是Windows,请在此处查看本文.另请参阅此处可用的ynchronization函数.您可能需要注意,通常volatile不足以完成您希望它执行的操作,但在VC 2005和2008中,添加了非标准语义,这会在读取和写入之间添加隐含的内存屏障.

如果你想让事物变得便携,那么你将面临更艰难的道路.

推荐阅读
乐韵答题
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有