使用
GHC 7.0.3,
gcc 4.4.6,
Linux 2.6.29一个x86_64的Core2双核(2.5GHz的)机器上,编译使用
ghc-O2 -fllvm -fforce-recomp用于Haskell和
gcc -O3 -lm为C.
- 您的C例程在8.4秒内运行(比运行速度快,原因可能是
-O3
) - Haskell解决方案可在36秒内运行(由于显示
-O2
标记) - 您的
factorCount'
代码未明确输入且默认为Integer
(感谢Daniel在这里纠正了我的误诊!)。使用给出显式类型签名(无论如何都是标准做法)Int
,时间更改为 11.1秒 - 在
factorCount'
你不必要的呼唤fromIntegral
。修复不会产生任何变化(编译器很聪明,对您来说很幸运)。 - 您
mod
在rem
更快更充分的地方使用了。这将时间更改为 8.5秒 。 factorCount'
不断应用两个永不改变的自变量(number
,sqrt
)。工人/包装工人的转型为我们提供了:$ time ./so
842161320real 0m7.954s
user 0m7.944s
sys 0m0.004s
没错, 7.95秒 。始终 比C解决方案快半秒 。没有
-fllvm标记,我仍然会收到消息
8.182seconds,因此NCG后端在这种情况下也表现良好。
结论:Haskell很棒。
结果代码
factorCount number = factorCount' number isquare 1 0 - (fromEnum $ square == fromIntegral isquare) where square = sqrt $ fromIntegral number isquare = floor squarefactorCount' :: Int -> Int -> Int -> Int -> IntfactorCount' number sqrt candidate0 count0 = go candidate0 count0 where go candidate count | candidate > sqrt = count | number `rem` candidate == 0 = go (candidate + 1) (count + 2) | otherwise = go (candidate + 1) countnextTriangle index triangle | factorCount triangle > 1000 = triangle | otherwise = nextTriangle (index + 1) (triangle + index + 1)main = print $ nextTriangle 1 1
编辑:现在,我们已经探索了这一点,让我们解决问题
问题1:erlang,python和haskell是否会由于使用任意长度的整数而导致速度下降,还是只要它们的值小于MAXINT,它们就不会丢失吗?
在Haskell中,使用
Integer的速度慢于
Int但要慢多少,取决于执行的计算。幸运的是(对于64位计算机)
Int就足够了。出于可移植性考虑,您可能应该重写我的代码以使用
Int64或
Word64(C不是唯一带有的语言
long)。
问题2:为什么haskell这么慢?是否有编译器标志可以使您刹车?或者这是我的实现?(后者很可能因为haskell是一本对我有七个印章的书。)
问题3:能否为我提供一些提示,说明如何在不改变确定因素的方式下优化这些实现?以任何方式进行优化:对语言更好,更快,更“原生”。
那就是我上面回答的。答案是
- 0)通过使用优化
-O2
- 1)尽可能使用快速(特别是:不可装箱)类型
- 2)
rem
不是mod
(经常被遗忘的优化),并且 - 3)worker / wrapper转换(也许是最常见的优化)。
问题4:我的功能实现是否允许LCO,从而避免在调用堆栈中添加不必要的帧?
是的,这不是问题。做得好,很高兴您考虑了这一点。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)