У меня есть куча строк данных, и я хочу использовать Parallel.ForEach для вычисления некоторого значения на каждой строке, как это ...Несколько вызовов Parallel.ForEach, MemoryBarrier?
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 (как только первая параллельная .ForEach заканчивается). Есть ли вероятность, что чтение dr.B для строки 0 в потоке 43 вернет double.NaN, поскольку он еще не видел запись из потока 42?
И если да, то вставляет ли барьер памяти при помощи III вообще? Это заставит обновления с первого Parallel.ForEach быть видимыми для всех потоков до того, как будет запущен второй Parallel.ForEach?
Короче .. Я не думаю, что вам нужен явные барьеры памяти .. Образованные бы предположить, что реализация Parallel.ForEach имеет некоторую синхронизацию для завершения цикла/перед вызовом 'ForEach' возвращает –
Учитывая лучшую картину вашего фактического кода, я мог бы дать вам лучший ответ, кроме« Нет, не беспокойтесь об этом. " :) – jdphenix
Возможно, причина разделения немного ясна, если я скажу, что вычисление в каждой строке второго параллельного цикла (IV) зависит от некоторого значения, которое может быть известно только после завершения первого цикла (II). Скажем, нам нужна медиана значений dr.B для всех строк, прежде чем мы сможем вычислить значение dr.C для каждой строки. –