为什么堆栈的深度使用会导致简单解释器的超线性时间行为?

2024-01-27

type Expr =
    | Lit of int
    | Add of Expr * Expr

let rec intr = function
    | Lit _ as x -> x
    | Add(Lit a,Lit b) -> Lit <| a + b
    | Add(a,b) -> intr <| Add(intr a, intr b)

let rec intr_cps x ret =
    match x with
    | Lit _ as x -> ret x
    | Add(Lit a,Lit b) -> Lit (a + b) |> ret
    | Add(a,b) -> 
        intr_cps a <| fun a ->
            intr_cps b <| fun b ->
                intr_cps (Add(a, b)) ret

let rec add n =
    if n > 1 then Add(Lit 1, add (n-1))
    else Lit 1

open System.Threading

let mem = 1024*1024*512 // ~536mb
// It stack overflows without being spun on a separate thread.
// By default, the program only has a few mb of stack memory at its disposal.
let run f = Thread(ThreadStart f,mem).Start() 

run <| fun _ ->
    let f n =
        let x = add n
        let stopwatch = System.Diagnostics.Stopwatch.StartNew()
        printfn "%A" (intr x)
        printfn "n_%i_std = %A" n stopwatch.Elapsed

        stopwatch.Restart()
        printfn "%A" (intr_cps x id)
        printfn "n_%i_cps = %A" n stopwatch.Elapsed
    f <| 1000*1000/2
    f <| 1000*1000
    f <| 1000*1000*2

//Lit 500000
//n_500000_std = 00:00:00.7764730
//Lit 500000
//n_500000_cps = 00:00:00.0800371
//Lit 1000000
//n_1000000_std = 00:00:02.9531043
//Lit 1000000
//n_1000000_cps = 00:00:00.1941828
//Lit 2000000
//n_2000000_std = 00:00:13.7823780
//Lit 2000000
//n_2000000_cps = 00:00:00.2767752

我有一个更大的解释器,我试图更好地理解它的性能行为,所以我做了上面的事情。我现在确信我在一些示例中看到的超线性时间缩放与它使用堆栈的方式有关,但我不确定为什么会发生这种情况,所以我想在这里问。

正如你所看到的,当我改变n2 倍后,时间变化远不止于此,而且似乎是指数级的,这让我感到惊讶。同样令人惊讶的是,CPS 的解释器比基于堆栈的解释器更快。这是为什么?

我还想问,如果我用非 .NET 语言甚至 C 语言编写与上述内容等效的代码,是否会看到相同的行为?


看起来您正在测量的大部分内容都是在构建数据结构。分解出

let data = add n

在时间测量之外(并替换add n with data内)并且 CPS 呈线性。

我对具有大堆栈的线程和内存性能了解不够,无法立即解释其余部分,也没有分析内存来获得任何感觉。

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

为什么堆栈的深度使用会导致简单解释器的超线性时间行为? 的相关文章

  • 该变量未声明或从未分配警告

    这是基类 public class BaseClass UserControl protected ListView list protected TreeView tree public BaseClass 儿童班 public part
  • 非泛型类型 Type 不需要类型参数

    我正在创建一个简单的测试类型提供程序 我想提供一个字符串 并返回一个类型名称等于所提供的字符串的类型 但结果不行 说BasicProvider是非泛型类型 Error 非泛型类型 SimpleStringProvider BasicProv
  • 在 .Net 中创建 EPUB

    有没有可以用来在 NET C 中创建 epub 文件的库 Flowdocument gt epub 转换工具将是理想的选择 但任何类型的库都很棒 我还对评估编写一个程序的复杂程度感兴趣 我知道它基本上是一堆压缩的 XHTML 文件 但我不断
  • 如何以一种形式发布两个或多个模型?

    我正在为一个项目开发互联网课程计划应用程序 该课程计划是根据以下模型构建的 使用数据库优先方法中的实体框架生成 public partial class Subject public int Id get set public string
  • 在 Javascript 中本地化字符串

    我目前正在使用 resx文件来管理我的 NET 服务器端资源 我正在处理的应用程序还允许开发人员将 JavaScript 插入各种事件处理程序中以进行客户端验证等 对我来说本地化 JavaScript 消息和字符串的最佳方法是什么 理想情况
  • 如果浏览器在 asp .net 中关闭,请从浏览器中注销?

    我的要求有点复杂 用户正在使用 Web 浏览器访问数据库 而在访问数据库时 如果用户关闭活动页面而不是注销会话 该会话需要自动注销 有人可以指导我如何做这个吗 我在母版页中使用了jquery onbeforeunload 我收到消息离开页面
  • 抽象类或接口。哪种方式是正确的?

    有两种方法可以选择抽象类或接口 微软解决方案和Oracle解决方案 微软 设计指南 请使用抽象 在 Visual Basic 中为 MustInherit 类而不是接口来将协定与实现分离 http msdn microsoft com en
  • 将标签文本的一部分设置为粗体

    有什么办法可以使一部分label text要大胆吗 label text asd string 想要string部分要加粗 有可能吗 这怎么办 下面的类说明了如何通过覆盖来做到这一点OnPaint in the LabelWinForms
  • .NET 中严格浮点数学的库

    我有 Java 算法 计算及其单元测试 单元测试期望结果具有一定的精度 增量 现在我将算法移植到 NET 中 并希望使用相同的单元测试 我使用双数据类型 问题在于 Java 使用 strictfp 64 位 来执行 Math 类中的某些操作
  • 当用户打开文件时如何锁定对文件的访问?

    我正在编写一个 C NET 程序 该程序使用 XmlSerializer 对当前用户正在处理的项目与 XML 文件进行序列化和反序列化 这工作正常 但我试图找到一种方法来防止两个用户从网络驱动器打开同一个文件并让一个用户覆盖前一个用户的保存
  • 结构中的内存布局差异

    我在 C 中有以下结构 struct A int a double b float c 该结构与添加了函数的结构之间的内存布局是否存在差异 struct B int a double b float c void foo B foo do
  • DataGridView 中的 C# FormatException

    我创建了一个带有一些列的 DataGridView 订单列仅允许用户输入 int 数字 当我输入 j 例如 时 它会抛出 FormatException 并且我尝试添加 try catch 来解决问题 但它看起来不起作用 private v
  • 将变量作为参数传递与传递另一个函数的返回值时出现“无效过程调用”错误

    我收到错误 无效的过程调用或参数 AddRange 当传递一个变量到ArrayList AddRange https msdn microsoft com en US library zhfwys3c 28v vs 110 29 aspx
  • 如何为从源文件编译的应用程序分配自定义图标?

    在我的程序中 我使用 CSharpCodeProvider 来从源文件编译另一个应用程序 我使用的代码如下 public static bool CompileExecutable String sourceName FileInfo so
  • 为使用 SSH.NET SshClient.CreateShellStream 执行的命令 (sudo/su) 提供子命令

    我正在尝试使用 Renci SSH NET 从 C Web 应用程序连接到远程 Linux 服务器并执行 shell 脚本 我想一个接一个地运行脚本 但不知道如何运行脚本并读取输出并将其存储在标签中 我已经尝试了下面的代码 但无法一行接一行
  • 每个托管线程是否都有自己对应的本机线程?

    我想知道是否在 Net 中创建托管线程 通过调用Thread Start 导致在后台创建一个本机线程 那么托管线程是否有对应的本机线程呢 如果是 当托管线程等待或睡眠时 是否意味着相应的本机线程也在等待或睡眠 是的 NET 线程映射到所有当
  • 如何区分用户点击链接和页面自动重定向?

    拥有 C WebBrowser control http msdn microsoft com en us library system windows forms webbrowser aspx在我的 WinForms 应用程序中 并意识
  • 使用自定义堆的类似 malloc 的函数

    如果我希望使用自定义预分配堆构造类似 malloc 的功能 那么 C 中最好的方法是什么 我的具体问题是 我有一个可映射 类似内存 的设备 已将其放入我的地址空间中 但我需要获得一种更灵活的方式来使用该内存来存储将随着时间的推移分配和释放的
  • C# 中的合并运算符?

    我想我记得看到过类似的东西 三元运算符 http msdn microsoft com en us library ty67wk28 28VS 80 29 aspx在 C 中 它只有两部分 如果变量值不为空 则返回变量值 如果为空 则返回默
  • 从 Excel 应用程序对象中查找位数(32 位/64 位)?

    是否可以从 Microsoft Office Interop Excel ApplicationClass 确定 Excel 是以 32 位还是 64 位运行 Edit该解决方案应该适用于 Excel 2010 和 Excel 2007 此

随机推荐

  • C# 中的心电图数字信号处理

    我正在寻找用于数字滤波 低通 高通 陷波 的 C NET 库 以实时过滤心电图波形 有什么建议么 如果这是非商业用途 我听说过关于信号实验室库 http www mitov com html signallab html 非商业用途免费 商
  • MDX - TopCount 加“其他”或“其余”

    我创建了一个 MDX 查询 用于计算前 10 个邮政编码 根据我的患者住院测量 如下所示 WITH MEMBER Discharge Date Y M D Aggregation AS AGGREGATE EXISTING Current
  • 如何在 Github Actions 中查看已取消步骤的日志?

    我的工作流程中有一个步骤是运行命令 python 脚本 这个 python 脚本似乎挂在执行过程中的某个地方 GitHub 显示该步骤在运行时被卡住并且没有任何反应 为了调试这个 我想查看 python 脚本的日志输出 我怎样才能做到这一点
  • PHP 中的测试驱动开发

    我是一名使用 PHP 工作的 Web 开发人员 我在 C 桌面应用程序中使用测试驱动开发的经验有限 在这种情况下 我们使用 nUnit 作为单元测试框架 我想在新项目中开始使用 TDD 但我真的不知道从哪里开始 对于基于 PHP 的单元测试
  • 通知在 flutter 上显示两次

    我被困住了 我的后台通知显示两次 但前台只有一个通知 这是我的代码 Future
  • 谷歌数据存储中的节点分页

    我在使用 Google Datastore 进行分页时遇到问题 我有一个查询 没有限制 有几百个结果 我想检索 5 个 将它们发送回用户 如果用户想要更多 他们会检索下 5 个 根据文档 我创建了查询 var query datastore
  • div 相对于窗口的位置?

    尝试找到 div 相对于窗口的位置 我有一个水平 div 我想获取相对于窗口的左侧值 因此 如果我将第二个 div 滚动到窗口左侧 它将显示 0 不确定如果没有父 div 这是否可行 这是我的小提琴 http jsfiddle net FS
  • 如何在 Symfony2 配置中添加带有值的数组?

    我想在配置文件 config yml 中添加一个简单的值列表 例如 my bundle columns col1 col2 将节点添加到配置解析器时 它只是失败 rootNode treeBuilder gt root my bundle
  • NHibernate 测试,模拟 ISession

    我正在使用 NHibernate 和 Rhinomocks 但在测试我想要的东西时遇到了困难 我想在不访问数据库的情况下测试以下存储库方法 其中 session 作为 ISession 注入存储库 public class Reposito
  • SQL语句只删除一行重复项

    所以我正在使用 Ruby 工作 并假设我的两列表中有 6 行完全相同 就我而言 我的表 campaign items 有两列 campaign name 和 item 我想使用单个查询仅删除 6 个重复项中的一行 我是这样开始的 db ex
  • Flex 页脚在 Chrome 中不会停留在底部

    仅当内容短于视口时 我才使用 Flexbox 让页脚保持在底部 如果它较高 页脚应保持在内容下方 以便您必须滚动才能看到它 这在 Firefox 和 Edge 中可以正常工作 但在 Chrome 或 IE 中则不行 在 Chrome 中 正
  • WCF - 自定义凭据和安全令牌

    我对 WCF 开发相当陌生 在学习该框架时遇到了一些问题 我有一个必须支持 REST 和 SOAP 的服务 API 到目前为止 这很容易实现 尤其是使用 WCF4 和路由 我目前正在研究授权 并通过创建两个新的管理器类来扩展 Authori
  • 如何在Apache中设置mod_lua来访问第三方Lua模块?

    我正在尝试为 Apache 设置 mod lua 模块 但在访问第三方 Lua 模块时遇到了困难 假设我在 Apache 的 htdocs 文件夹中有一个 hello world lua 其中包含以下内容 require apache2 f
  • 尽管已传输,但仍出现错误“无法传输文件 *.jar,状态代码为 409”

    我正在尝试将项目发布到azure artefacts 项目pom是这样的
  • Django 使用 selenium 进行测试,未加载固定装置

    我正在使用 Selenium 为 Django 网站设置功能测试 我有一个固定文件 users fixtures users json 并在另一个应用程序的功能测试中使用它 accounts 运行测试时 我还运行我的开发服务器来接受来自 S
  • 为什么 std::visit 必须有单一返回类型?

    玩耍的同时std variant and std visit出现了以下问题 考虑以下代码 using Variant std variant
  • m2eclipse过滤测试资源

    我正在使用 m2eclipse 我想右键单击并从 eclipse 内部运行测试 同时从 Maven 过滤测试资源 我怎样才能做到这一点 从 Eclipse 中 当我右键单击测试时 我没有得到任何 m2eclipse 选项 Julia 如同
  • LinqPad 在每个表的末尾添加一个 S

    我刚刚下载了 LinqPad 以探索在我正在开发的应用程序中使用 Linq 查询的好处 但是当我查看左侧列中的数据库表时 LinqPad 显示我的所有表 末尾带有 s 例如实例 CategoryTbl 变为 CategoryTbls 但是当
  • S3 PUT 不适用于 JavaScript 中的预签名 URL

    我已经在 java 中为 HTTP PUT 方法生成了一个预签名的 S3 URL URL 的稍微修改版本 https s3 amazonaws com somebucket pre signed url key 2 AWSAccessKey
  • 为什么堆栈的深度使用会导致简单解释器的超线性时间行为?

    type Expr Lit of int Add of Expr Expr let rec intr function Lit as x gt x Add Lit a Lit b gt Lit lt a b Add a b gt intr