本文介绍了内存栅栏 - 需要帮助了解的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读Paul E. McKenney的内存障碍

一切都在很详细的解释,当我看到一切都清楚我遇到一个句子,扼杀了一切,让我认为我什么也不明白。让我举个例子。

I'm reading Memory Barriers by Paul E. McKenneyhttp://www.rdrop.com/users/paulmck/scalability/paper/whymb.2010.07.23a.pdfeverything is explained in great details and when I see that everything is clear I encounter one sentence, which stultifies everything and make me think that I understood nothing. Let me show the example

void foo(void)
{
   a = 1; #1
   b = 1; #2
}

void bar(void)
{
   while (b == 0) continue; #3
   assert(a == 1); #4
}

假设这两个函数在不同的处理器上运行。
现在可能发生的是,在第二处理器存储到b#2之后可以看到存储到#1,因为第一处理器队列存储到a并继续存储b指令。好的,我们在#1和#2之间添加一个写栅栏,但是这个代码仍然可能失败,因为第二个处理器可能会将无效的消息排队,所以我们再添加一个内存栅栏#4和#4之间的线。

let's say this two functions are running on a different processors.Now what could possibly happen is store to a #1 could be seen after store to b #2 by the second processor, because first processor queues store to "a" and proceed to store b instruction. OK, that's fine, we add a write fence in the line between #1 and #2, but this code still can fail, because second processor might queue the invalidate message, so we add one more memory fence (read fence this time) in the line between #4 and #4.

void foo(void)
{
   a = 1; #1
   write_memory_barrier();
   b = 1; #2
}

void bar(void)
{
   while (b == 0) continue; #3
   read_memory_barrier();
   assert(a == 1); #4
}

这将强制第二处理器处理所有排队的邮件通过发送读取MESI消息到#4上的第一处理器再次读取。好。接下来文章说

this enforce second processor to process all queued messages (invalidate a) and read it again by sending read MESI message to first processor on #4. OK. Next the article says

很好,请参见

所以
$ b已经在任何商店
之后完成。 b $ b

so

混合了前面解释过的所有内容。这是什么意思?在a#4负载之前,功能bar中的哪个负载必须完成?我知道断言可能会失败没有内存屏障在这个函数只是因为处理器可能读取一个旧的值,因为它仍然没有设法使它的缓存线,对象a位于无效。

that mixes up everything what was explained before. What does it mean? Which load in function "bar" have to complete before load of "a" #4? I understand the assert could fail without memory barrier in this function just because the processor may read an old value, because it still didn't manage to invalidate it's cache line, where object "a" is located.

详细说明会非常有帮助,我想全天了解。

Explanation in details would be really helpful, I'm trying to understand it all the day.

非常感谢。

推荐答案

是什么意思?

这意味着如果您有:

read
read
read
READ BARRIER
read
read
read

连接点将这些读取分为两个批次。

then the read barrier acts as a "join point" dividing these reads into two batches. All the reads preceding the read barrier will have been done before any read following the read barrier is begun.

在 bar()中加载的所有读取在读取屏障之前的任何读取之前已经完成。 )必须在加载 a (#4)之前完成吗?

Which loads in bar() must complete before the load of a (#4) is begun?

b (#3)的所有读取被强制在任何读取 a 。这意味着在 b 不再为0之前,不会读取 a 。因为 foo )使用写屏障来确保 a 已经更改为 1 1)改变 b (#2)的时间。因此,这两个障碍一起工作,以确保assert语句总是成功。

All reads of b (#3) are forced to precede any read of a (#4). This means that a is not read till after b is no longer 0. Because foo() uses a write barrier to ensure that a has already been changed to 1 (#1) by the time that b is changed (#2). The two barriers thus work together to ensure the assert statement will always succeed.

这篇关于内存栅栏 - 需要帮助了解的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-27 08:04
查看更多