首页 > 解决方案 > 有什么方法可以加快 Netlogo 的“校验码”功能?

问题描述

前言:我是一名经济学家——没有接受过正规的编程培训。

我在 Netlogo 中组装了一个 ABM,随着代码变得更长,“检查”功能——在任何更改后运行代码所需的——花费的时间越来越长。现在在我非常快的桌面上大约需要 30 秒。我尝试在一台速度非常慢的超极本上运行代码,检查需要 10 分钟。我想知道是否有任何方法可以加快或绕过此过程,或者是否有任何最佳实践来构建我的代码以使其可以更快地处理。

编辑:我有大量代码(大约 5,000 行,100,000 个字符),并且随着程序变大,“检查”时间按比例增加。我不知道代码的哪些组件导致执行时间增加,或者如何以与此问题相关的方式将模型简化为伪代码。

但是,我添加了示例代码,它捕获了我的程序的一个元素(许多品种类型——尽管不是这么多),并且需要相当长的时间来检查。

我的模型有很多品种类型,因为我有数千个代理,需要定期调用搜索特定代理,发现代理集太慢了。

breed [types1 type1]
breed [types2 type2]
...
breed [types250 type250]


types1-own [ a b c d]
types2-own [ a b c d]
...
types250-own [ a b c d]

globals [
  iter

]
to setup
  ca
ask types1 [set a 1 set b 2 set c 3 set d 4 set xcor 1 set ycor 1]
ask types2 [set a x set b y set c z set d w set xcor 15 set ycor 12]
....
ask types250 [set a A set b B set c C set d D set xcor 3 set ycor 14]


end

编辑2:

针对品种数量可能存在问题的建议,我将品种数量从大约 75 个减少到大约 25 个,并用代理集替换它们。这显着改善了我的模型中的设置时间(从 ~0.8 秒到 ~0.3 秒),但对语法检查/编译/单击“检查”时实际发生的事情没有明显影响。

标签: netlogo

解决方案


我制作了一个包含 250 个品种和 250 个breeds-own声明的示例 NetLogo 模型,它在我的 2015 MacBook Pro 上检查/编译得非常快,不到 1 秒。我setup为每个品种添加了一些命令,例如create-types1 [ ; ... ]检查速度有点慢。然后我go像你的例子一样添加了一些语句,ask types1 [ ; ... ]它变得更慢了,大约 1000 行代码达到大约 5 秒。

我从models库中打开了DNA Replication Fork模型,大概有900行代码,大概有十几个品种,加载似乎也需要5秒左右。这是非常不科学的,我只是想弄清楚问题的根源。至少在我的 MacBook 上,我不能完全确定许多品种是检查/编译缓慢的罪魁祸首,但这肯定是编写模型的一种不寻常的方式,所以我也不会把它排除在外。

无论哪种方式,30 秒到 10 分钟对于检查/编译来说肯定听起来太长了。如果您愿意将您的完整模型提交给 bugs@ccl.northwestern.edu,我们可以仔细查看,并可能会针对导致缓慢的核心原因最终得到修复的问题提出问题。

除了查看更新

我在创建以下示例时遇到了一件事情:当我reset-ticks使用约 75,000 个代理进行呼叫时,NetLogo 桌面更新视图的速度非常慢。您提到与成千上万的代理一起运行,但我不确定是否有那么多。在任何情况下,如果您在模型运行时不需要查看某些代理,则可以set hidden? true在创建它们时执行,或完全关闭视图更新。

您提到切换到多品种有助于您的模型的运行时性能,所以我认为这不是您的问题,但我想提一下以防万一。

纯种选项

冒着回答您没有提出的问题的风险,这里有一个选项可以尝试让非品种解决方案发挥作用。

正如 JenB 指出的那样,您可以将代理集预先存储在变量中以避免重复计算它们。您给出的示例只是为每种类型设置了品种自己的变量值,我不希望仅使用过滤的代理集会很慢(但我可能错了!)。

你提到寻找特定的代理,我想知道这里是否存在嵌套搜索问题。使用大量代理ask turtles with [type = 1] [ ask turtles with [type = 2] [ ; ... do something ] ]可能会变得非常慢,因为turtles with [type = 2]将为每个 1 型海龟计算内部。预先计算过滤的代理集应该对此有所帮助,setup如果您的代理没有死亡或更改类型,则每次一次,或者go如果他们这样做,则每次滴答。

这是一个例子。我正在使用扩展来存储这个版本table预先计算的代理集,因为有这么多类型的代理,它会大大简化代码。事实上,它已经有一个原语group-agents,可以根据变量的值来处理分组代理。因为我不确切知道代理在您的模型中做什么,所以我填写了一些go设置一些链接的代码,只是为了展示您如何实际使用存储的代理集。

extensions [ table ]

globals [ turtle-type-numbers turtle-sets ]

turtles-own [ turtle-type a b c d ]

to setup
  clear-all

  ; store the turtle type number list so we don't keep re-creating it
  set turtle-type-numbers range 250
  set turtle-sets table:make

  foreach turtle-type-numbers [ turtle-type-number ->
    create-turtles 100 [
      set turtle-type turtle-type-number
      set hidden? true
      set a random 10
      set b random 10
      set c one-of [true false]
      set d one-of ["apples" "oranges" "bananas"]
    ]
  ]

  reset-ticks
end

to go
  ; at the start of each tick, re-query our turtle-sets
  ; if new turtles are not made and existing turtles do not change types
  ; then this could just be done once at the end of `setup` instead
  set turtle-sets table:group-agents turtles [turtle-type]

  ask links [ die ]

  foreach turtle-type-numbers [ turtle-type-number ->
    let typed-turtles (table:get turtle-sets turtle-type-number)
    ask typed-turtles [
      fd turtle-type mod 10

      ; link this turtle to one of the other types
      ; we just choose the next type number, get the agentset
      ; we stored previosuly, then choose `one-of` those
      ; turtles to link to.
      let next-type (turtle-type + 1) mod 250
      let next-turtles (table:get turtle-sets next-type)
      create-link-with one-of next-turtles
    ]
  ]

  tick
end

我希望这会有所帮助。


推荐阅读