对于我的学士论文,我必须分析虚假共享对多核系统的影响.因此,我在维基百科上看到了不同的缓存一致性协议类型,英特尔已经开发出MESIF缓存一致性协议,但英特尔也没有使用此信息.
查看手册英特尔®64和IA-32架构开发人员手册:Vol.3A我找不到任何关于MESIF但是MESI协议的内容.所以问题是,英特尔不使用自己的缓存一致性协议.或者我在错误的文件中搜索它.
multithreading caching multicore state-machine false-sharing
我不明白,release sequence如果我们在下面的例子中有2个线程,为什么会没有问题.我们对原子变量只有2个操作count.count按顺序递减,如输出中所示.
从C++并发在行动由安东尼·威廉姆斯:
我提到你可以
synchronizes-with relationship在一个store原子变量和load另一个线程的原子变量之间得到一个原子变量,即使在和read-modify-write之间有一系列操作,只要所有操作都被适当标记.如果商店标有,或,并且负载标有,或,并且链中的每个操作都加载了前一个操作所写的值,则操作链构成一个释放序列和初始存储(用于或者)或(是)最终负荷.链中的任何原子读 - 修改 - 写操作都可以有任何内存排序(偶数).storeloadmemory_order_releasememory_order_acq_relmemory_order_seq_cstmemory_order_consumememory_order_acquirememory_order_seq_cstsynchronizes-withmemory_order_acquirememory_order_seq_cstdependency-ordered-beforememory_order_consumememory_order_relaxed要查看这意味着什么(发布顺序)及其重要性,请考虑将
atomic<int>其用作共享队列中项目数的计数,如下面的清单所示.处理事情的一种方法是让生成数据的线程将项目存储在共享缓冲区中,然后执行
count.store(number_of_items, memory_order_release)#1以让其他线程知道数据可用.在实际读取共享缓冲区#4之前,消耗队列项的线程可以执行count.fetch_sub(1,memory_ order_acquire)#2以从队列中声明项目.一旦计数变为零,就没有更多的项目,并且线程必须等待#3.
#include <atomic>
#include <thread>
#include <vector>
#include <iostream>
#include <mutex>
std::vector<int> queue_data;
std::atomic<int> count;
std::mutex m;
void process(int i)
{
std::lock_guard<std::mutex> …Run Code Online (Sandbox Code Playgroud) 共享内存多处理系统通常需要为缓存一致性生成大量流量。核心 A 写入缓存。Core B 稍后可能会读取相同的内存位置。因此,内核 A,即使它本来可以避免写入主内存,也需要向内核 B 发送通知,告诉 B 如果该地址正在缓存中,则该地址无效。
究竟什么时候需要这样做,这是一个复杂的问题。不同的 CPU 架构有不同的内存模型,这里上下文中的内存模型是一组关于观察到的事情发生的顺序的保证。内存模型越弱,A 在发送通知的确切时间就越放松对于 B,A 和 B 更容易并行做更多的事情。不同 CPU 架构的内存模型总结:https : //en.wikipedia.org/wiki/Memory_ordering#Runtime_memory_ordering
所有的讨论似乎是关于当失效发生时,什么为了事情发生英寸
但在我看来,在许多工作负载中,A 写入的大部分数据永远不会被 B 使用,因此如果可以完全消除那些缓存失效的总线流量会更好。专用于执行缓存一致性的硬件仍然需要存在,因为 A 和 B 有时需要共享数据,但写入共享总线是 CPU 可以做的更耗能的事情之一,并且电池寿命和散热通常是现在限制资源,因此减少总线流量将是一个有用的优化。有没有办法做到这一点?
从效率的角度来看,理想的情况是如果忽略总线流量是默认的(因为大多数写入的数据不与其他线程共享),并且您必须在需要缓存一致性的地方显式地发出内存屏障。另一方面,这可能是不可能的,因为假设它在 x86 或 ARM 上运行的现有代码量很大;有没有办法反过来,向 CPU 指示给定的缓存行永远不会对任何其他线程感兴趣?
我会对任何系统的答案感兴趣,但最特别是 x64、ARM 或 RISC-V 上 Linux 最常见的当前/未来服务器配置。
multithreading cpu-architecture memory-model memory-barriers cpu-cache
这是关于跨不同层的缓存一致性协议cache。我的理解(X86_64)L1是,它由一个核心独占,L2介于两个核心之间,并且L3适用于一个CPU插槽中的所有核心。我已经阅读了MESI协议功能,关于存储缓冲区、无效队列、无效消息等。我的疑问是,它仅MESI适用于L1还是适用于L2并且L3也适用。L2或者 for和之间是否有不同的缓存同步L3。
与我之前的问题类似,请考虑以下代码
-- Initially --
std::atomic<int> x{0};
std::atomic<int> y{0};
-- Thread 1 --
x.store(1, std::memory_order_release);
-- Thread 2 --
y.store(2, std::memory_order_release);
-- Thread 3 --
int r1 = x.load(std::memory_order_acquire); // x first
int r2 = y.load(std::memory_order_acquire);
-- Thread 4 --
int r3 = y.load(std::memory_order_acquire); // y first
int r4 = x.load(std::memory_order_acquire);
Run Code Online (Sandbox Code Playgroud)
是怪异的结果 r1==1, r2==0,并r3==2, r4==0有可能在C ++ 11内存模型下,这种情况下?如果我要全部替换std::memory_order_acq_rel成该std::memory_order_relaxed怎么办?
在x86上,这样的结果似乎是被禁止的,请参见此SO问题,但我一般是在询问C ++ 11内存模型。
奖励问题:
我们都同意,与std::memory_order_seq_cst该怪异的结果不会在C ++ 11被允许。现在,赫伯·萨特(Herb Sutter)在他著名的- …
我对缓存一致性系统在现代多核 CPU 中的功能有些困惑。我已经看到基于侦听的协议,如基于 MESIF/MOESI 侦听的协议已在 Intel 和 AMD 处理器中使用,另一方面,基于目录的协议似乎对多核更有效,因为它们不广播但发送消息具体节点。
AMD 或 Intel 处理器中的现代缓存一致性解决方案是什么,它是基于侦听的协议,如 MOESI 和 MESIF,还是仅基于目录的协议,还是两者的组合(基于侦听的协议,用于同一节点内的元素之间的通信? ,以及基于节点到节点通信的目录)?