Windows – Euler问题的性能问题和Int64类型的递归
我正在学习
Haskell使用项目欧拉问题作为我的操场.
我很惊讶,我的Haskell计划结果比较相似 以其他语言编写的程序.我想知道我是否会看到某些东西,或者是使用Haskell时这种表现的惩罚. 以下程序灵感来自于问题331,但是我在发布之前已经改变了,所以我不会为别人破坏任何东西.它计算在2 ^ 30 x 2 ^ 30网格上绘制的离散圆的弧长.这是一个简单的尾递归实现,我确保累积变量跟踪弧长度的更新是严格的.然而,完成需要将近一个半分钟(用ghc的-O标志编译). import Data.Int arcLength :: Int64->Int64 arcLength n = arcLength' 0 (n-1) 0 0 where arcLength' x y norm2 acc | x > y = acc | norm2 < 0 = arcLength' (x + 1) y (norm2 + 2*x +1) acc | norm2 > 2*(n-1) = arcLength' (x - 1) (y-1) (norm2 - 2*(x + y) + 2) acc | otherwise = arcLength' (x + 1) y (norm2 + 2*x + 1) $! (acc + 1) main = print $arcLength (2^30) 这是Java中相应的实现.完成约需4.5秒 public class ArcLength { public static void main(String args[]) { long n = 1 << 30; long x = 0; long y = n-1; long acc = 0; long norm2 = 0; long time = System.currentTimeMillis(); while(x <= y) { if (norm2 < 0) { norm2 += 2*x + 1; x++; } else if (norm2 > 2*(n-1)) { norm2 += 2 - 2*(x+y); x--; y--; } else { norm2 += 2*x + 1; x++; acc++; } } time = System.currentTimeMillis() - time; System.err.println(acc); System.err.println(time); } } 编辑:在评论中讨论之后,我对Haskell代码进行了一些修改,并进行了一些性能测试.首先我将n改为2 ^ 29以避免溢出.然后我尝试了6个不同的版本:使用Int64或Int,并且在norm2或者两者之前都有bangs,而norm2和acc在声明arcLength’x y!norm2!acc.所有都是编译的 ghc -O3 -prof -rtsopts -fforce-recomp -XBangPatterns arctest.hs 结果如下: (Int !norm2 !acc) total time = 3.00 secs (150 ticks @ 20 ms) total alloc = 2,892 bytes (excludes profiling overheads) (Int norm2 !acc) total time = 3.56 secs (178 ticks @ 20 ms) total alloc = 2,892 bytes (excludes profiling overheads) (Int norm2 acc) total time = 3.56 secs (178 ticks @ 20 ms) total alloc = 2,892 bytes (excludes profiling overheads) (Int64 norm2 acc) arctest.exe: out of memory (Int64 norm2 !acc) total time = 48.46 secs (2423 ticks @ 20 ms) total alloc = 26,246,173,228 bytes (excludes profiling overheads) (Int64 !norm2 !acc) total time = 31.46 secs (1573 ticks @ 20 ms) total alloc = 3,032 bytes (excludes profiling overheads) 我在64位Windows 7(Haskell平台二进制分发)下使用GHC 7.0.2.根据注释,在其他配置下进行编译时,不会出现此问题.这使我觉得Int64类型在Windows版本中被破坏.
嗯,我用7.0.3安装了一个新的Haskell平台,并为您的程序大概地获得了以下内核(-ddump-simple):
Main.$warcLength' = (ww_s1my :: GHC.Prim.Int64#) (ww1_s1mC :: GHC.Prim.Int64#) (ww2_s1mG :: GHC.Prim.Int64#) (ww3_s1mK :: GHC.Prim.Int64#) -> case {__pkg_ccall ghc-prim hs_gtInt64 [...] ww_s1my ww1_s1mC GHC.Prim.realWorld# [...] 所以GHC已经意识到它可以打包整数,这是很好的.但是这个hs_getInt64调用看起来像C调用一样可疑.看看汇编器输出(-ddump-asm),我们看到的东西就像: pushl %eax movl 76(%esp),%eax pushl %eax call _hs_gtInt64 addl $16,%esp 所以这看起来非常像Int64中的每个操作在后台变成一个完整的C调用.这很慢,显然. GHC.IntWord64的source code似乎验证了:在32位版本(如当前与平台一起提供的版本)中,您将只能通过FFI界面进行仿真. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- windows-server-2003 – 如何修复“系统启动期间至少有一个
- 通过Powershell或Batch将文件从Windows转换为UNIX
- Windows上的Vim设置文件
- windows-server-2003 – 可以从“开始”菜单中删除“关机”
- go 工具链目前[不支持编译 windows 下的动态链接库]解决方案
- windows – 为什么`cmd / k`和`cmd / c`记住已经完成的cmd子
- windows cmd install nscp
- 在Windows 2016上安装NFS服务时出错
- windows-server-2003 – 需要IPX的Server 2003 Guest的Hype
- Window.Top将.NET 4中的不同结果读取到.NET 3.5
- windows-mobile – 安排Windows Mobile应用程序运
- window下redis的安装和创建redis启动服务
- windows-server-2003 – 需要另一个域控制器
- windows-server-2012-r2 – 在Windows Server 20
- Windows Phone开发使用wpf?
- windows-phone-8 – Windows Phone 8 Web浏览器控
- Dll的放置目录&在指定目录打开命令行&查
- windows-server-2012-r2 – DFS-R在克隆后创建42
- windows-server-2003 – 无法删除Windows 2003 S
- Windows内存映射文件