为什么对本地列表求和比用“GHC -O2”对教会编码列表求和慢?

2024-06-01

为了测试教会编码的列表如何针对用户定义的列表和本机列表执行,我准备了 3 个基准测试:

用户定义的列表

data List a = Cons a (List a) | Nil deriving Show
lenumTil n        = go n Nil where
    go 0 result   = result
    go n result   = go (n-1) (Cons (n-1) result)
lsum Nil          = 0
lsum (Cons h t)   = h + (lsum t)

main = print (lsum (lenumTil (100000000 :: Int)))

本地列表

main = print $ sum ([0..100000000-1] :: [Int])

教会名单

fsum   = (\ a -> (a (+) 0))
fenumTil n cons nil = go n nil where
    go 0 result    = result
    go n result    = go (n-1) (cons (n-1) result)
main = print $ (fsum (fenumTil (100000000 :: Int)) :: Int)

基准测试结果出乎意料:

用户定义的列表

-- 4999999950000000
-- real 0m22.520s
-- user 0m59.815s
-- sys  0m20.327s

本地列表

-- 4999999950000000
-- real 0m0.999s
-- user 0m1.357s
-- sys  0m0.252s

教会名单

-- 4999999950000000
-- real 0m0.010s
-- user 0m0.002s
-- sys  0m0.003s

人们会期望,通过针对本机列表的大量特定优化,它们将表现最佳。然而,教会列表的表现比它们高出 100 倍,比用户定义的 ADT 高出 2250 倍。我已经编译了所有程序GHC -O2。我尝试过更换sum by foldl',结果相同。我尝试添加用户输入以确保教堂列表版本没有优化为常量。arkeet在 #haskell 上指出,通过检查 Core,原生版本有一个中间列表,但为什么呢?强制分配额外的reverse,所有 3 个的性能大致相同。


GHC 7.10 有调用数量 http://www.joachim-breitner.de/publications/CallArity-TFP.pdf分析,让我们定义foldl按照foldr从而让左边的折叠,包括sum,参与融合。 GHC 7.8 还定义了sum with foldl但它无法将列表融合掉。因此,GHC 7.10 的性能最佳且与 Church 版本相同。

Church 版本在任一 GHC 版本中进行优化都是轻而易举的事情。我们只需要内联(+) and 0 into fenumTil,然后我们就有了一个明显的尾递归go它可以很容易地拆箱,然后由代码生成器转换为循环。

用户定义的版本不是尾递归的,它在线性空间中工作,这当然会破坏性能。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么对本地列表求和比用“GHC -O2”对教会编码列表求和慢? 的相关文章

随机推荐

  • 嵌入式开发系统中JTAG的一般工作流程?

    在我的嵌入式项目中 我使用 JTAG 接口下载代码并调试下载的应用程序 但我不知道 JTAG 设置内部发生了什么 任何人都可以给我 JTAG 设置的基本想法 流程 高级视图 这将真正帮助我更好地理解我的开发系统 为了添加克利福德的答案 这里
  • 如何用js获取一个月的4个星期一?

    我正在构建一个图表 其中 x 轴应该是一个月的四个星期 我只想显示该月的四个星期一 我已经有了currentMonth和currentYear变量 而且我知道如何获取该月的第一天 我所需要的只是将一个月的四个星期一放入数组中 所有这些都在同
  • Django 评论和评级系统

    我正在寻找一个可以与我的 Django 网站顺利集成的博客和评论系统 我在网上发现了很多 但有点迷失了 我在这方面没有太多经验 希望大家能给我一些建议 以下是我想要拥有的东西 标签云 文章存档 按月 按年 文章评级 例如带有星星或自定义图标
  • MVC4 输入字段占位符

    Does MVC4默认支持placeholders对于生成的输入字段 我没有找到任何东西 所以我正在尝试实现我自己的 但不幸的是Prompt E Mail 没有传递到ViewData ModelMetadata Watermark同时产生控
  • 在cameraX中镜像

    如何在前置和后置摄像头模式下显示镜像 我知道这个位图可以像下面一样镜像 BitmapDrawable flip BitmapDrawable d Matrix m new Matrix m preScale 1 1 Bitmap src d
  • CSS 无法与 CodeIgniter 一起使用

    这是我的 CI 代码的一部分 class page extends CI Controller var Page public function construct parent construct this gt Page 1 this
  • 访问自定义表单控件的有效值

    我创建了代表密码表单控件的自定义组件 下面的代码已简化 密码组件 html
  • 从 Orbeon XForm 提交发送 HTTP 标头

    我有一个 API 它依赖于某些 HTTP 标头来实现特定行为 示例是 HTTP 标头If Matches仅当版本与值匹配时才支持更新If Matches 我如何从 Orbeon XForms 提交发送这些 HTTP 标头 The xf su
  • C# 线程和队列

    这不是关于我可以或应该使用的不同方法来以最佳方式利用队列 而是关于我所看到的对我来说毫无意义的事情 void Runner member variable queue Queue Synchronized new Queue while t
  • 带滚动条的 HTML 画布

    我正在宽度不等的画布上绘制图表 每个画布可以有自己的滚动条吗 我尝试将所有画布放在一个 div 中并指定最大宽度 但它不起作用 是否有可能所有画布在页面上的可见宽度均为 500 像素 并且每个画布都有其滚动条来查看画布的整个宽度 谢谢 指定
  • Matlab 中的多行匿名函数? [复制]

    这个问题在这里已经有答案了 是否可以在 Matlab 中创建多行匿名函数 没有合适的例子在文档中 http www mathworks com help matlab matlab prog anonymous functions html
  • 撤消多个文件和文件夹“git add”[重复]

    这个问题在这里已经有答案了 我执行了 git add 现在我想恢复 git add 我怎样才能做到这一点 git reset 这相当于git reset HEAD 将取消 add 更常见的是 取消暂存 所有文件 In Git revert用
  • 使用 Junit5 对 LiveDataobserverForever 进行单元测试会导致 NullPointer 异常

    我正在使用 Android 数据绑定来监听实时数据更改 并且我想观察视图模型级别的更改 而不是观察片段 然后向视图模型发送回调 这observerForever很有趣 因为它对我有用 但是 当我运行测试时 出现以下错误 java lang
  • 调整窗口大小后保持 winform 控件居中

    使用 Visual Studio 2008 Windows 窗体 C NET 2 0 是否有一种无代码的方法来使控件 在我的例子中恰好是 PictureBox 在调整窗口大小时保持居中 换句话说 使用属性设置的某种组合而不是手动编写代码来保
  • 如何自动执行使用 Maven 构建的 Eclipse 插件的版本号更新过程

    我正在处理一个与该项目类似的项目此处描述 http www vogella com articles EclipseTycho article html 因此 它在父 pom xml 中有一些模块
  • viewportFraction < 1.0 的 PageView 非中心对齐

    当您为 PageController 创建 viewportFraction 值为 我希望当前页面捕捉到视口的顶部 而下一页呈现在底部栏下方 我尝试对每个页面应用转换 Transform translate offset Offset 0
  • 使用 HttpClient 从 webapi 消费 xml

    我使用 WebClient 从 Restfull 服务 net web api 获取 Xml 对象 一切都运行良好 using WebClient client new WebClient client Encoding UTF8Encod
  • 调整离子卡中的图像大小

    我想显示一组图像 并在下面说明 我选择使用 Ionic 卡 我得到这个结果 第一张图片 虽然我想保留现在的相同布局 并添加描述 这是我的代码
  • 嵌套字段索引

    我正在尝试使用 AWS 开发人员控制台中的仪表板在嵌套字段上创建索引 例如 如果我有以下架构 id 1 nested mode mode1 text nice text 我能够创建索引nested mode 但是每当我通过索引进行查询时 就
  • 为什么对本地列表求和比用“GHC -O2”对教会编码列表求和慢?

    为了测试教会编码的列表如何针对用户定义的列表和本机列表执行 我准备了 3 个基准测试 用户定义的列表 data List a Cons a List a Nil deriving Show lenumTil n go n Nil where