C#巨大性能下降分配浮点值

时间:2013-12-05 20:35:38

标签: c# performance

我正在尝试优化我的代码并在其上运行VS性能监视器。

enter image description here

它表明浮点数的简单分配占用了大部分计算能力?我不明白这是怎么可能的。

以下是TagData的代码:

public class TagData
{
    public int tf;
    public float tf_idf;
}

所以我真正做的就是:

float tag_tfidf = td.tf_idf;

我很困惑。

3 个答案:

答案 0 :(得分:7)

我将发布另一个理论:它可能是第一次访问td成员的缓存未命中。内存负载需要100-200个周期,在这种情况下似乎相当于该方法总持续时间的1/3左右。

测试这一理论的要点:

  1. 您的数据集是否很大?它打赌它是。
  2. 您是否以随机内存顺序访问TagData?我打赌他们在记忆中并不顺序。这会导致CPU的内存预取功能失效。
  3. 在昂贵的广告系列之前添加新行int dummy = td.tf;。这条新线路现在将成为最昂贵的线路,因为它会触发缓存未命中。找到一些方法来执行JIT未优化的虚拟加载操作。可能会将所有td.tf值添加到本地,并在方法结束时将该值传递给GC.KeepAlive。这应该在JIT发出的x86中保持内存负载。
  4. 我可能错了,但与其他理论相反,到目前为止我的可测试

    尝试TagData一个struct。这将使term.tags中的所有项目在内存中顺序排列并为您提供良好的性能提升。

答案 1 :(得分:1)

您使用的是LINQ吗?如果是这样,LINQ使用延迟枚举,所以当你第一次访问你拔出的值时,它会很痛苦。

如果您使用的是LINQ,请在查询后调用ToList(),只支付一次价格。

看起来您的数据结构也是次优的,但由于我无法访问您的源代码(即使我这样做也可能无法帮助:)),我无法告诉您哪些更好。

编辑:正如评论者指出的那样,LINQ可能不是罪魁祸首;但是我的问题是基于这两个foreach语句都使用IEnumerable这一事实。 TagData赋值是指向IEnumerable集合中的项目的指针(可能已经或可能尚未枚举)。合法数据的第一次访问是从对象中提取属性的行。第一次发生这种情况时,它可能正在执行整个LINQ语句,并且由于分析使用平均值,因此可能会关闭。对于tagScores(我猜测它是数据库支持的),它的首次访问速度非常慢,然后加速,这也是一样的。鉴于我对IEnumerable的理解,我没有指出解决方案只是一个可能的问题。

请参阅http://odetocode.com/blogs/scott/archive/2008/10/01/lazy-linq-and-enumerable-objects.aspx

答案 2 :(得分:0)

我们可以看到,可疑者的下一行只需要0.6

float tag_tfidf = td.tf_idf;//29.6
string tagName =...;//0.6

我怀疑这是由于过多的调用引起的,并且还注意float是值类型,这意味着它们是按值复制的。因此,每次分配它时,运行时都会创建新的float(单个)结构,并通过复制td.tf_idf中的值来进行初始化,这需要花费大量时间。

您可以看到string tagName =...;并不需要太多,因为它是通过引用复制的。

编辑:正如评论指出我在这方面可能是错的,这也可能是探查器中的错误,请尝试重新分析,看看是否有任何区别。