【发布时间】:2015-05-15 03:19:22
【问题描述】:
我有一堆数据行,我想使用 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 相同) ForEach 完成)。线程 43 上第 0 行的 dr.B 读取是否有可能返回 double.NaN,因为它还没有看到线程 42 的写入?
如果是这样,在 III 处插入内存屏障是否有帮助?这是否会强制第一个 Parallel.ForEach 的更新在第二个 Parallel.ForEach 启动之前对所有线程可见?
【问题讨论】:
-
简而言之..我认为您不需要显式的内存屏障..有根据的猜测是 Parallel.ForEach 的实现具有某种同步来结束循环/在调用@之前987654322@返回
-
如果您能更好地了解您的实际代码,我或许可以给您一个更好的答案,而不是“不,别担心”。 :)
-
如果我说第二个并行循环(IV)的每一行中的计算取决于一些只有在第一个循环之后才能知道的值(II ) 完成。假设我们需要所有行的 dr.B 值的中位数,然后才能计算每行的 dr.C 值。
标签: c# multithreading task-parallel-library parallel.foreach