- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一堆数据行,我想使用 Parallel.ForEach 像这样计算每一行的一些值...
class DataRow
{
public double A { get; internal set; }
public double B { get; internal set; }
public double C { get; internal set; }
public DataRow()
{
A = double.NaN;
B = double.NaN;
C = double.NaN;
}
}
class Program
{
static void ParallelForEachToyExample()
{
var rnd = new Random();
var df = new List<DataRow>();
for (int i = 0; i < 10000000; i++)
{
var dr = new DataRow {A = rnd.NextDouble()};
df.Add(dr);
}
// Ever Needed? (I)
//Thread.MemoryBarrier();
// Parallel For Each (II)
Parallel.ForEach(df, dr =>
{
dr.B = 2.0*dr.A;
});
// Ever Needed? (III)
//Thread.MemoryBarrier();
// Parallel For Each 2 (IV)
Parallel.ForEach(df, dr =>
{
dr.C = 2.0 * dr.B;
});
}
}
(在这个例子中,不需要并行化,如果有的话,它可以全部放在一个 Parallel.ForEach 中。但这意味着是一些代码的简化版本,像这样设置它是有意义的).
是否可以在此处重新排序读取,以便我最终得到 B != 2A 或 C != 2B 的数据行?
假设第一个 Parallel.ForEach (II) 分配工作线程 42 处理数据行 0。第二个 Parallel.ForEach (IV) 分配工作线程 43 处理数据行 0(第一个 Parallel.ForEach (IV) 分配工作线程 43 处理数据行 0)。 ForEach 完成)。是否有可能在线程 43 上读取第 0 行的 dr.B 返回 double.NaN,因为它还没有看到来自线程 42 的写入?
如果是这样,在 III 处插入内存屏障是否有帮助?这会强制第一个 Parallel.ForEach 的更新在第二个 Parallel.ForEach 开始之前对所有线程可见吗?
最佳答案
工作由 Parallel.ForEach()
开始将在它返回之前完成。在内部,ForEach()
产生一个 Task
对于每次迭代,并调用 Wait()
在每一个上。因此,您不需要在 ForEach()
之间同步访问电话。
对于使用 ForEach()
的单个任务,您确实需要记住这一点允许您访问循环状态、聚合任务结果等的重载。例如在这个简单的例子中,它总结了 1 ≤ x ≤ 100
。 , Action
传递给 localFinally
的 Parallel.For()
不得不关心同步问题,
var total = 0;
Parallel.For(0, 101, () => 0, // <-- localInit
(i, state, localTotal) => { // <-- body
localTotal += i;
return localTotal;
}, localTotal => { <-- localFinally
Interlocked.Add(ref total, localTotal); // Note the use of an `Interlocked` static method
});
// Work of previous `For()` call is guaranteed to be done here
Console.WriteLine(total);
在您的示例中,没有必要在 ForEach()
之间插入内存屏障。电话。具体来说,循环 IV
可以取决于 II
的结果正在完成,并且Parallel.ForEach()
已插入 III
为你。
关于c# - 多个 Parallel.ForEach 调用,MemoryBarrier?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30250980/
VB.Net 没有等效的 C# volatile 关键字,因此您必须手动实现 volatile,这通常通过在读取之前和写入之后调用 Thread.MemoryBarrier() 来完成。所以这样的事情
using System; using System.Threading; using System.Threading.Tasks; class Program { static void
我修改了 Non-Blocking Synchronization 上给出的程序如下: class DemoProg { int _answer; bool _complete;
如果我理解正确,在 C# 中,一个 lock block 保证对一组指令的独占访问,但它也保证从内存中读取的任何内容都反射(reflect)了任何 CPU 缓存中该内存的最新版本.我们将 lock b
我需要一种可靠的方法来获得系统正常运行时间,并最终使用了如下方法。添加了一些评论以帮助人们阅读它。我不能使用任务,因为它必须在 .NET 3.5 应用程序上运行。 // This is a struc
由于似乎上下文切换可能发生在指令执行的任何时刻,所以我现在想知道为什么代码“部分有问题”(那两条指令)有意义,如果上下文切换可以在任何指令之间发生并且我们可能在不同的CPU上第二条指令的核心。 voi
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Why we need Thread.MemoryBarrier()? 摘自 O'Reilly 的 C# i
在 Java 中,我如何显式触发一个完整的内存栅栏/屏障,等于调用 System.Threading.Thread.MemoryBarrier(); 在 C# 中? 我知道,自从 Java 5 读取和
对于以下场景,使用MemoryBarrier在线程安全性、结果和性能方面是否有任何差异 private SomeType field; public SomeType Property { g
在这本线程在线书籍中:http://www.albahari.com/threading/part4.aspx 有一个 Thread.MemoryBarrier() 的例子 class Foo
这个网站的新手,所以如果我没有以可接受的方式发帖请告诉我。 我经常按照下面的示例编写代码(为清楚起见,省略了 Dispose 之类的内容。)。我的问题是,是否需要如图所示的 volatile ?或者
在“C# 4 in a Nutshell”中,作者展示了这个类有时可以在没有 MemoryBarrier 的情况下写入 0,尽管我无法在我的 Core2Duo 中重现: public class Fo
在 .NET 中 lock关键字是 Monitor.Enter 周围的语法糖和 Monitor.Exit ,所以你可以说这段代码 lock(locker) { // Do something }
下面的 GLSL 计算着色器简单地复制了 inImage至 outImage .它源自更复杂的后处理过程。 在main()的前几行,单个线程将 64 个像素的数据加载到共享数组中。然后,在同步之后,6
根据Web,我找到了如下代码,相当于C# Volatile for VB.NET。 代码引用:How do I specify the equivalent of volatile in VB.net
只是在业余时间玩并发性,并想尝试在不使用读取器端锁定的情况下防止撕裂读取,以便并发读取器不会相互干扰。 这个想法是通过锁序列化写入,但在读取端仅使用内存屏障。这是一个可重用的抽象,它封装了我提出的方法
通过浏览 MEF 源代码,我找到了这篇文章。有人可以解释为什么锁内需要 MemoryBarrier 吗? 整个方法是: public void SatisfyImportsOnce(Composabl
假设我有一个字段控制某个循环的执行: private static bool shouldRun = true; 我有一个正在运行的线程,其代码如下: while(shouldRun) { /
在 msdn 上 http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208(v=vs.85).aspx , MemoryBarr
如果我正确理解 volatile 和 MemoryBarrier 的含义,那么下面的程序将永远无法显示任何结果。 每次我运行它时,它都会捕获写入操作的重新排序。我在 Debug 或 Release 中
我是一名优秀的程序员,十分优秀!