由于我不知道LINQ的工作原理,因此我无法决定在执行速度方面最适合使用哪个版本。我已经对测试数据(点云)进行了一些测试,但我看不出两者之间有明显的区别。我唯一知道的是,现实生活中的数据将是更大的点云,所以我猜是LINQ会更快,但这仅在LINQ不在幕后的情况下进行。如果是这样,这两个功能将是相同的。您有什么建议?

对,cylindre是3D圆柱体,我想知道里面是哪一点。

没有LINQ的版本1

/>
for (int i = 0; i < fpc.Vertices.Length; i++)
{
    if (cylindre.IsPointInside(fpc.Vertices[i]))
        listPoint.Add(fpc.Vertices[i]);
}


版本2,带有LINQ

var insidePoint =
    from pt1 in fpc.Vertices
    where cylindre.IsPointInside(pt1)
    select pt1;

    foreach (Point3D pt2 in insidePoint)
    {
        listPoint.Add(pt2);
    }


评论

这可能会有所帮助:developers.stackexchange.com/questions/80084/…

@ANeves有趣的文章。我认为我的问题还为时过早,因为这是必需的,而且非常重要,因为每个用户每天要完成500次。我没有真实数据的唯一原因是最终产品尚未准备就绪,但我可以确定它会更大,因此此时的优化非常重要。我也在考虑其他改进功能的方法,但是linq和foreach之间的区别让我很感兴趣。

您是否在算法上压缩了每一点性能?您使用哪种数据结构和算法很重要。 .Net的一些高度优化的库将更快地执行一些计算。另外,也许可以同时使用PLINQ并利用多个内核?我也会测量的。

谢谢(你的)信息。实际上,我们已经使用LINQ和foreach创建了一个很小的子集来运行foreach,现在它以超快的速度运行。

在LINQ版本中,您可以考虑使用AddRange()代替foreach。它不会提高性能,但是会使您的代码更具可读性。另外,直接使用Where()会比from / where / select短。

#1 楼

就像Q4312079Q一样,LINQ会在引擎上遍历整个集合。 LINQ和foreach的区别在于LINQ将推迟执行直到迭代开始。

性能方面的知识请看这篇博客文章。

评论


\ $ \ begingroup \ $
关于该链接的说明。该链接正在处理从列表中删除元素。它使用一个for循环,然后与一个双foreach循环和一个LINQ / foreach组合进行对比。这不是一个公平的比较。
\ $ \ endgroup \ $
– pstrjds
2012年8月9日13:40

\ $ \ begingroup \ $
此答案发布时,该链接已有3年历史,现在已超过11年。
\ $ \ endgroup \ $
–是
20年8月2日在6:59

\ $ \ begingroup \ $
链接不再有效
\ $ \ endgroup \ $
–Chase Florell
20-09-17在15:34

#2 楼

就像已经说过的那样,for循环很有可能会表现得更好,但是您仍然可以清理一些代码:

for (int i = 0; i < fpc.Vertices.Length; i++)
{
    if (cylindre.IsPointInside(fpc.Vertices[i]))
        listPoint.Add(fpc.Vertices[i]);
}


可以成为:

foreach (var vertice in fpc.Vertices)
{
    if (cylindre.IsPointInside(vertice))
        listPoint.Add(vertice);
}


编辑:根据性能问题。该代码将在LINQPad中运行。我发现foreach版本的性能比for循环好几毫秒。

var elements = Enumerable.Range(0, 4000000).Select(x => true).ToArray();


var sw = new Stopwatch();
var result = new List<bool>();
int trueCount = 0;
sw.Start();
for(int i=0; i < elements.Length; ++i)
{
    if (elements[i])
    {
        ++trueCount;
        result.Add(elements[i]);
    }
}

sw.Stop();
sw.ElapsedMilliseconds.Dump();

sw.Reset();
trueCount = 0;
result = new List<bool>();
sw.Start();
foreach(var element in elements)
{
    if (element)
    {
        ++trueCount;
        result.Add(element);
    }
}
sw.Stop();
sw.ElapsedMilliseconds.Dump();


EDIT2-关于链接似乎表明在foreach循环中性能如此差劲

链接(http://www.schnieds.com/2009/03/linq-vs-foreach-vs-for-loop-performance.html)涉及从列表中删除元素。在您具有通用列表的情况下,通过for循环删除元素通常不是最佳方法。更好的方法是使用RemoveAll方法。 RemoveAll将删除所有与谓词匹配的元素,然后合并列表(与RemoveAt相反),RemoveAll需要将所有元素移到已删除元素上方。对于删除的性能比较,请参见以下代码(再次,可以在LINQPad中运行)。在我的测试中,RemoveAll的运行速度大约快了250倍。

var elements = Enumerable.Range(0, 100000).Select(x => x % 2 == 0).ToArray();

var sw = new Stopwatch();
var source = new List<bool>(elements);
sw.Start();
for(int i=0; i < source.Count; ++i)
{
    if (!source[i])
    {
        source.RemoveAt(i);
        --i;
    }
}

sw.Stop();
sw.ElapsedMilliseconds.Dump();
int count = source.Count;

sw.Reset();
source = new List<bool>(elements);

sw.Start();
source.RemoveAll((bool x) => {return x;});
sw.Stop();
sw.ElapsedMilliseconds.Dump();


评论


\ $ \ begingroup \ $
如Xharze的链接schnieds.com/2009/03/…所述,用foreach代替for循环会降低性能。
\ $ \ endgroup \ $
– Goldoldak84
2012年8月9日13:09

\ $ \ begingroup \ $
@ Goldorak84-如果查看该链接的代码示例,您将看到在foreach和LINQ情况下,代码遍历该列表两次,而for情况仅遍历该列表两次。该链接正在处理从列表中删除项目,并且可以使用RemoveAll编写而没有循环,这甚至比for循环还要快。
\ $ \ endgroup \ $
– pstrjds
2012年8月9日13:29

\ $ \ begingroup \ $
@pstrjds-对不起,您说得很对。我修改了代码示例,将foreach和linq列表删除机制应用于for循环。 for和foreach之间的区别几乎不明显。
\ $ \ endgroup \ $
– Goldoldak84
2012年8月9日14:51

#3 楼

更新:

如果目标是.net 4或更高版本,则可以使用:

Parallel.ForEach()




RemoveAll().Parallel();


它们应该比其他方法更快。

评论


\ $ \ begingroup \ $
List .RemoveAll()返回一个int,它表示从列表中删除的元素数。您是说List .AsParallel()吗?
\ $ \ endgroup \ $
– Mathieu Guindon♦
14年4月15日在22:13

#4 楼

我认为它不会在LINQ上运行得更快。仍然必须在每个顶点上调用函数cylindre.IsPointInside