MemoryBarrier和并行扩展



使用并行扩展时是否需要关注MemoryBarrier?

编辑-由于最初的问题是开放式的,所以要详细说明:(@xanatos的答案是我正在寻找的答案)

举一个具体的例子:假设我使用Parallel.ForEach,每次迭代都会设置类中某个属性的值(每次迭代都设置自己的特定属性,没有两次迭代设置同一属性的值)。在调用Parallel.ForEach的同一个线程上,我访问从Parallel.ForEach.

class Program
{
  static void Main(string[] args)
  {
    var t = new Test();
    t.InitializePropertiesInParallel();
    var a = t.PropA; // Could never be 0?
    var b = t.PropB; // Could never be 0?
  }
}
public class Test
{
  public int PropA { get; set; }
  public int PropB { get; set; }
  public void InitializePropertiesInParallel()
  {
    var initializers = new List<Action<int>>()
    {
      i => PropA = i,
      i => PropB = i
    };
    initializers.AsParallel().ForAll(a => a(1));
  }
}

请记住一件事:缓存行无效。这是一个复杂的主题,但这里有一篇很棒的MSDN文章。

在这个特定的例子中,它的要点是,因为你正在从两个不同的线程修改同一个对象实例,即使你没有接触到内存中完全相同的位置,你也会接触到同一条缓存线,因此当处理器1上的第一个线程更改内存时,在处理器2可以再次读取/写入之前,缓存将被刷新和更新。

也就是说,再次考虑到你只有两个道具的具体例子,这是一个微观优化,绝对不需要担心。如果你要对其进行推断,需要注意的是。

如果每个工作者都不需要其他工作者准备的数据(因此不存在工作者1写入A而工作者2读取A的情况),则不需要MemoryBarrier。当所有任务完成时,有一个Wait充当MemoryBarrier(最终,即使您没有看到它,在某个地方也有一个同步结构等待所有工作人员完成)

相关内容

  • 没有找到相关文章

最新更新