python写算法太慢_FSharp运行我的算法比Python慢

我通过电子邮件联系了乔恩·哈罗普医生,他解释了发生的事情:The problem is simply that the program has been optimized for Python. This is common when the programmer is more familiar with one language than the other, of course. You just have to learn a different set of rules that dictate how F# programs should be optimized...

Several things jumped out at me such as the use of a "for i in 1..n do" loop rather than a "for i=1 to n do" loop (which is faster in general but not significant here), repeatedly doing List.mapi on a list to mimic an array index (which allocated intermediate lists unnecessarily) and your use of the F# TryGetValue for Dictionary which allocates unnecessarily (the .NET TryGetValue that accepts a ref is faster in general but not so much here)

... but the real killer problem turned out to be your use of a hash table to implement a dense 2D matrix. Using a hash table is ideal in Python because its hash table implementation has been extremely well optimized (as evidenced by the fact that your Python code is running as fast as F# compiled to native code!) but arrays are a much better way to represent dense matrices, particularly when you want a default value of zero.

有趣的是,当我第一次编码这个算法时,我确实使用了一个表——为了清晰起见,我将实现改为字典(避免数组边界检查使代码更简单,也更容易推理)。

Jon将我的代码(back:-)转换为它的array version,它以100倍的速度运行。

故事的寓意:字典需要工作。。。当使用元组作为键时,编译的F#比解释的Python哈希表慢!

很明显,但重复并没有坏处:更干净的代码有时意味着。。。更慢的代码。

谢谢你,乔恩——非常感谢。

编辑:事实上,用数组替换字典使F最终以编译语言预期的运行速度运行,这并不意味着需要修正字典的速度(我希望来自MS的F#人正在阅读这个)。其他的算法依赖于字典/散列,并且不能很容易地切换到使用数组;使得程序在使用字典时遭受“解释器速度”的影响,可以说是一个bug。如果,正如一些人在评论中所说,问题不在于F,而在于.NET字典,那么我认为。。。是.NET中的一个bug!

EDIT2:最清晰的解决方案是,不需要算法切换到数组(有些算法根本不适合这样做)来更改:let optimalResults = new Dictionary<_>()

进入这个:let optimalResults = new Dictionary<_>(HashIdentity.Structural)

这一变化使F#代码的运行速度提高了2.7倍,从而最终击败了Python(提高了1.6倍)。奇怪的是元组默认情况下使用结构比较,因此原则上,字典对键进行的比较是相同的(有或没有结构)。Harrop博士认为,速度差可能是由于虚拟调度造成的:“AFAIK,.NET对优化虚拟调度几乎没有作用,而且在现代硬件上,虚拟调度的成本极高,因为它是一个“计算的goto”,将程序计数器跳到一个不可预测的位置,因此,破坏分支预测逻辑,几乎肯定会导致整个CPU管道被刷新和重新加载“。

简单地说,正如Don Syme(look at the bottom 3 answers)所建议的,“在将引用类型的键与.NET集合结合使用时,要明确使用结构哈希”。(Harrop博士在下面的评论中还说,在使用.NET集合时,我们应该始终使用结构比较)。

亲爱的微软团队,如果有办法自动解决这个问题,请这样做。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值