我正在阅读有关MESI协议的信息,如果我们对每个写操作都具有独占访问权,从而导致其他内核的高速缓存中的高速缓存行无效,那么我为什么不理解为什么会出现数据争夺的情况?在此示例中:
CYCLE # CORE 1 CORE 2
0 reg = load(&counter);
1 reg = reg + 1; reg = load(&counter);
2 store(&counter, reg); reg = reg + 1;
3 store(&counter, reg);
据说总体结果是变量只增加了一次,而两个内核都试图增加它(结果是两个)。因此,问题在于,如果在写操作期间,两个内核都请求对缓存行的排他访问(因此其他内核“等待”它们的修改,从而也获得了排他访问),为什么在该变量上存在数据竞争?
答案 0 :(得分:4)
如果我没看错的话,MESI就是这里的红鲱鱼:
0 reg = load(&counter);
counter
现在已加载到CPU的寄存器中。
1 reg = reg + 1; reg = load(&counter);
第一个处理器递增该值,第二个处理器加载旧的值。
2 store(&counter, reg); reg = reg + 1;
第一个处理器存储值,第二个处理器存储其过时的值。
3 store(&counter, reg);
第二个处理器根据过时的值存储计算结果。
到目前为止应该很清楚。现在,如果添加MESI状态,那将如何改变:
0 reg = load(&counter);
counter
在CPU 1高速缓存中,标记为E
。
1 reg = reg + 1; reg = load(&counter);
counter
仍位于CPU 1高速缓存中,但也已加载到CPU 2高速缓存中。因此,两个缓存行都需要标记为S
2 store(&counter, reg); reg = reg + 1;
现在counter
被存储回缓存中。因此,CPU 1缓存需要标记为M
,而CPU 2缓存则无效(标记为I
)。
3 store(&counter, reg);
由于CPU 2缓存无效,因此需要在进行store
操作之前进行更新,这反过来又要求将CPU 1缓存先(当然)写回到内存中。
但是现在所做的所有工作,reg
中的值仍然是基于过时的值计算的,并且仍然会覆盖缓存中的(现在已更新)值...
添加最后的详细信息:操作完成后,CPU 2缓存将标记为M
,CPU 1缓存将标记为I
。