我正在尝试优化我的代码并在其上运行VS性能监视器。
它表明浮点数的简单分配占用了大部分计算能力?我不明白这是怎么可能的。
以下是TagData的代码:
public class TagData
{
public int tf;
public float tf_idf;
}
所以我真正做的就是:
float tag_tfidf = td.tf_idf;
我很困惑。
答案 0 :(得分:7)
我将发布另一个理论:它可能是第一次访问td
成员的缓存未命中。内存负载需要100-200个周期,在这种情况下似乎相当于该方法总持续时间的1/3左右。
测试这一理论的要点:
TagData
?我打赌他们在记忆中并不顺序。这会导致CPU的内存预取功能失效。int dummy = td.tf;
。这条新线路现在将成为最昂贵的线路,因为它会触发缓存未命中。找到一些方法来执行JIT未优化的虚拟加载操作。可能会将所有td.tf
值添加到本地,并在方法结束时将该值传递给GC.KeepAlive
。这应该在JIT发出的x86中保持内存负载。我可能错了,但与其他理论相反,到目前为止我的可测试。
尝试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 =...;
并不需要太多,因为它是通过引用复制的。
编辑:正如评论指出我在这方面可能是错的,这也可能是探查器中的错误,请尝试重新分析,看看是否有任何区别。