为什么换档比给旧哈斯克尔供电慢呢? 如何让它更快?

当第一次搜索到我的代码很慢的时候,我真的很惊讶,不期望这样,驱动(或乘法)可以更快,所以移位代码中的某些东西真的很慢。

(整数)供电的代码

{-# OPTIONS_GHC -O2 #-}

import System.Environment(getArgs)

main = do
  [a,b] <- getArgs
  let c = ( read a::Integer ) ^ ( read b::Int )
  print ( mod c 2 )

用于移位的示例代码

{-# OPTIONS_GHC -O2 #-}

import Data.Bits
import System.Environment(getArgs)

main = do
  [a,b] <- getArgs
  let c = shift ( read a::Integer ) ( read b::Int )
  print( mod c 2 )

和我在旧的和最新的haskell上运行:

c: ghc ghc-6.10.4 bin> cmd / v:on / c“echo!TIME!&pow.exe 33 40000000&echo!TIME!”
1:24:29,02
1
1:24:41,48
- 12.46秒 供电

c: ghc ghc-6.10.4 bin> cmd / v:on / c“echo!TIME!&shift.exe 3 200000000&echo!TIME!”
1:27:08,76
0
1:27:22,06
- 13.30秒 换班

c: ghc ghc-7.6.3 bin> cmd / v:on / c“echo!TIME!&pow.exe 33 40000000&echo!TIME!”
2:19:29,39
1
2:19:37,06
- 7.67秒 供电(所以供电有所改善)

c: ghc ghc-7.6.3 bin> cmd / v:on / c“echo!TIME!&shift.exe 3 200000000&echo!TIME!”
2:20:49,61
0
2:20:49,69
- 0.08秒 (这意味着加速大约150倍)


甚至(这里有20亿比特的转换):
c: ghc ghc-7.6.3 bin> cmd / v:on / c“echo!TIME!&shift.exe 3 2000000000&echo!TIME!”
3:07:22,05
0
3:07:22,56
- 0.51秒


在运行中,这些数字相当大,以至于看到很长的运行时间。 在第一个代码中,我们计算33 ^ 40000000(mod 2),在第二个代码3 * 2 ^ 200000000(mod 2)中。 mod操作(或别的东西)必须看到不是0的时间(因为在这种情况下,haskell不会计算它)。 如前所述,电力供应速度更快,并注意到在这种情况下,33 ^ 40000000大于3 * 2 ^ 200000000。 此外在内存使用上,你可以看到3 ^ 200000000也是在最新的haskell上计算的,所以在这里没有深层次的优化技巧。

这个旧的haskell版本有可能获得加速吗? 我有兴趣在两个方向上移动(大整数),我们可以假设我们以64位的倍数(或63或32或31; haskell上的整数表示中的单词的大小)进行移位,所以在那里没有环绕。

试图计算2 ^ n然后执行乘法(或除法)做转变,但它没有给旧的haskell加速。

UPDATE
使用-v标志运行编译器开始打印:(我也可以发布其余的)格拉斯哥Haskell编译器版本6.10.4,用于Haskell 98,阶段2由GHC版本6.10.1启动使用包配置文件:C: ghc ghc-6.10.4 package.conf隐藏软件包base-3.0.3.1以避免与更高版本的base-4.1.0.0 wired-in软件包发生冲突ghc-prim映射到ghc-prim-0.1.0.0 wired-in软件包整数映射到整数-0.1.0.1线内包基底映射到基-4.1.0.0连线包中rts映射到rts-1.0连线包中haskell98映射到haskell98-1.0.1.0连线包syb映射到syb -0.1.0.1线内包模板-haskell映射到模板-haskell-2.3.0.1线内包dph-seq映射到dph-seq-0.3线内包dph-par映射到dph-par-0.3 Hsc静态标志:-static


我的猜测是GHC的旧版本没有针对Integer转换的专门实现,因此会回落到默认的Haskell实现,请参阅Data.Bits

shift x i | i >= 0    = x * 2^i
          | otherwise = x `div` 2^(-i)  

但是,当前版本的左右偏移都是基于GMP的primops,请参阅integer-gmp包中的GHC.Integer.Type模块中的shiftLIntegershiftRInteger函数。

链接地址: http://www.djcxy.com/p/61409.html

上一篇: Why shifting is slower than powering on old haskell !? How to make it faster?

下一篇: Maven custom plugin error