【问题标题】:Which is faster, for loop or LINQ哪个更快,for循环或LINQ
【发布时间】:2014-01-02 21:14:56
【问题描述】:

我有两个与此处相同的双精度值列表:

 List<double> list1 = something;
 List<double> list2 = somethingElse;

我想减去这两个列表。清单很大,我想尽快完成。以下哪种方法更快:

public double CalculateDistance(List<double> list1, List<double> list2)
{
    double dist = 0;
    for (int i = 0; i != list1.Count; i++)
    {
        dist += Math.Pow(list1 [i] - list2 [i], 2.0);
    }
    return dist;
}

或者这个:

public double CalculateDistance(List<double> list1, List<double> list2)
{
    double dist = list1.Zip(list2, (v1, v2) => Math.Pow(v1 - v2, 2.0)).Sum();
    return dist;
}

我不知道 LINQ 在底层做了什么,所以我不确定哪个更好。

【问题讨论】:

  • 自己测量...但首先,分析并确定此方法确实在您的应用程序的热门路径上。
  • 你应该做一些错误检查以确保两个列表包含相同数量的记录,如果不愿意处理或抛出异常。
  • 是的,他们有相同的金额或记录。我确定。我只是想了解哪个会带来更好的性能
  • LINQ 在后台并没有做任何“魔法”——如果有的话,它会引入更多开销,因为它只是在后台像往常一样迭代。 LINQ 的好处更多在于代码的简单性和可读性。
  • 我不知道为什么这里的人总是试图变得复杂(老实说)。当然,我想在更短的时间内(秒)处理这两个列表。

标签: c# linq loops collections


【解决方案1】:

两者都没有。使用循环的开销比 LINQ 少,所以这是一个好的开始。

在循环条件中使用&lt;运算符,这是编写这样一个循环的标准方式,因此编译器更有可能识别它并对其进行适当的优化。

使用Math.Pow 对数字求平方无效。将其自身相乘大约快 100 倍:

public double CalculateDistance(List<double> list1, List<double> list2) {
  double dist = 0;
  for (int i = 0; i < list1.Count; i++) {
    double n = list1[i] - list2[i];
    dist += n * n;
  }
  return dist;
}

编辑:

使用 PLINQ,您可以在大型集合中获得更好的性能。在我的电脑上测试它,我发现少于 10000 个项目使用 PLINQ 并不快。对于包含 1000 万个项目的列表,我的执行时间缩短了大约 40%。

我还发现使用投影比使用Zip 的执行时间缩短了大约 30%:

public double CalculateDistance(List<double> list1, List<double> list2) {
  return
    ParallelEnumerable.Range(0, list1.Count).Select(i => {
      double n = list1[i] - list2[i];
      return n * n;
    }).Sum();
}

【讨论】:

  • 对于非常长的集合(例如,每个集合有 10+ 百万个元素),使用 PLINQ 与 zipping 和 sum 可能会比常规命令式循环更快... :)
  • 是的列表可能有数百万的数据,但不是 10+。
  • @xXx 处理两个包含 500 万个项目的列表,每个列表产生约 50 毫秒的命令式解决方案,约 144 毫秒的 LINQ 和约 20 毫秒的 PLINQ(全部在 LINQPad 中)。那么什么性能是“足够好”的呢?感知性能是一样的...
  • @PatrykĆwiek 谢谢你的回答。在这种情况下,我将使用 PLINQ。
  • @xXx 你应该先衡量自己。如果您碰巧有一个较小的数据集,PLINQ 的开销可能会使其变慢。这一切取决于...
猜你喜欢
  • 2011-06-13
  • 2016-06-03
  • 1970-01-01
  • 1970-01-01
  • 2012-06-23
  • 2011-06-18
  • 1970-01-01
  • 2017-03-11
  • 1970-01-01
相关资源
最近更新 更多