在 linq 中正确有效地使用 .AsParallel()

Correctly using .AsParallel() efficiently with linq

我有一个元组,我正在使用 LINQ 对其进行迭代

List<Tuple<string[], double[]>> tt = new List<Tuple<string[], double[]>>();

var t1 = new Tuple<string[], double[]>(
    new string[] { "java", "c#", "nn" },
    new double[] { 2, 3, 0 });

var t2 = new Tuple<string[], double[]>(
    new string[] { "java", "c#", "nn" },
    new double[] { 0, 3, 1 });

var t3 = new Tuple<string[], double[]>(
    new string[] { "java", "c#", "nn" },
    new double[] { 2, 1, 0 });

tt.Add(t1);
tt.Add(t2);
tt.Add(t3);  

var XX = (from tuples in tt
          let rows = tuples.Item2.ToArray()
          let result = rows.Select(x => x/rows.Count(i => i != 0)).ToArray()
         select new Tuple<string[], double[]>(tuples.Item1, result)
       ).ToList();

如果我想使用 .Asparallel 我可以执行以下方法之一:

我可以在遍历列表时添加它:

        var XX = (from tuples in tt
                  .AsParallel() //Parallel added here
                  let rows = tuples.Item2.ToArray()
                  let result = rows.Select(x => x/rows.Count(i => i != 0)).ToArray()
                 select new Tuple<string[], double[]>(tuples.Item1, result)
               ).ToList();

我可以在使用 .ToArray().ToList

转换内容时添加它
        var XX = (from tuples in tt

                  let rows = tuples.Item2.ToArray()
                  let result = rows.Select(x => x / rows.Count(i => i != 0)).AsParallel().ToArray() //Parallel added right here
                 select new Tuple<string[], double[]>(tuples.Item1, result)
               ).ToList();

使用 .Asparallel 最有效的方法是什么?所有这些方法都没有错误,但我不确定它们是否会影响性能。

像这样添加 .Asparallel 是个坏主意吗?:

        var XX = (from tuples in tt
                  .AsParallel() //added here
                  let rows = tuples.Item2.AsParallel().ToArray() //here
                  let result = rows.Select(x => x / rows.Count(i => i != 0)).AsParallel().ToArray()//here
                 select new Tuple<string[], double[]>(tuples.Item1, result)
               ).AsParallel().ToList(); // and here

您应该在开始 LINQ 查询时在 from 子句中添加 AsParallel。这将使两个 let 语句并行执行,然后在最后调用 ToList 时合并在一起。

您还可以在查询中调用 Select 之前添加另一个 AsParallel

var XX = (from tuples in tt.AsParallel()
          let rows = tuples.Item2.ToArray()
          let result = rows.AsParallel().Select(x => x/rows.Count(i => i != 0)).ToArray()
         select new Tuple<string[], double[]>(tuples.Item1, result)
       ).ToList();

但是,您应该记住 AsParallel 有一些开销,因此在某些情况下它可能比常规的非并行处理慢。取决于元素的数量和计算的成本。