我正在构建一个包含社交扩散组件的Net徽标模型,并且在使用Table扩展时遇到了一个令人惊讶的性能问题。
对于某些上下文:在模型中,每个代理都有一个带有字符串键的态度表(例如:(“环境”)和浮动值为-1到1。每一个滴答,代理商更新他们的态度根据他们的接触和每个接触的重量。为了实现原型,我对每个联系人使用了简单的更新规则:
a(t) = a(t-1) + w * [b(t-1) - a(t-1)]
其中a是代理人的态度,b是接触态度,w是重量。每个特工有5-10个联系人。
我用两种方式实现了这一点。第一种方法使用执行得体的链接。但是,随着我的扩展,这方面的内存占用似乎变得相当大。由于网络不是动态的,所以我尝试将其实现为一个表,其中键是联系人海龟is,值是权重(严格地说,我创建了一个名为“contact”的海龟is列表和一个相应的权重表,以避免每次迭代时重新创建列表)。这似乎对许多代理使用的内存要少得多,但出乎意料地慢了一个数量级。
下面是基于网络的更新的一个片段:
ask my-in-links [
let neighborAttitude table:get [attitudes] of other-end "Environment"
let myAttitude table:get [attitudes] of myself "Environment"
let influence weight * (neighborAttitude - myAttitude)
set myAttitude myAttitude + influence
table:put [attitudes] of myself "Environment" myAttitude
]而基于表格的版本:
foreach (contacts) [ i ->
let myAttitude table:get attitudes "Environment"
let neighborAttitude table:get [attitudes] of homeowner i "Environment"
let w table:get contactWeights i
let influence w * (neighborAttitude - myAttitude)
set myAttitude myAttitude + influence
table:put attitudes "Environment" myAttitude
]从一些测试来看,大幅度的放缓似乎发生在获得neighborAttitude上。如果我注释掉这一行,从代理的态度表中获取和放置的速度就像基于网络的块一样快。所以它似乎找到了另一只海龟(“房主”)。
在NetLogo中,是否存在某种通过id查找海龟/代理的内在速度?这似乎应该是基本免费的,但我不知道这个数据结构是什么。
发布于 2020-09-11 09:28:08
这段代码非常不像NetLogo,所以我在解析它时遇到了一些困难,我的评论/回答可能完全偏离了重点。
我完全不理解table在这些行中的用法:
ask my-in-links [
let neighborAttitude table:get [attitudes] of other-end "Environment"你从ask my-in-links开始。这大概是在一个ask turtles或类似的块中。因此,运行代码首先选择一只海龟,假设海龟有5个链接到其他海龟。它会命中这段代码并运行这5个链接中的每一个,并创建一个表,其中的5个值以某种方式存储在一个带有键[attitudes] of other-end "Environment"的表中。
假设您有链接(您必须能够使用ask my-in-links),那么更多的NetLogo方式可以这样做,如下所示。注意,这是一个完整的模型,您可以将它放入一个空的NetLogo模型中来运行它。
turtles-own
[ myAttitude
myUpdatedAttitude
]
links-own
[ wgt
]
to setup
clear-all
create-turtles 20
[ setxy random-xcor random-ycor
set myAttitude -1 + random-float 2
]
; create a network
repeat 50
[ ask one-of turtles
[ create-link-to one-of other turtles
[ set wgt random-float 1 ]
]
]
reset-ticks
end
to go
type "average attitude: " print mean [myAttitude] of turtles
let w 0.4
; calculate next value and store until all calculated
ask turtles with [any? in-link-neighbors]
[ let wtd-diffs [([myAttitude] of other-end - [myAttitude] of myself) * wgt] of my-in-links
set myUpdatedAttitude (1 - w) * myAttitude + w * sum wtd-diffs
]
; make the change
ask turtles [ set myAttitude myUpdatedAttitude ]
tick
end对于每只海龟,这个代码构建了海龟与受其影响的海龟之间态度值的加权差异的列表。因此,如果它有5 in-link-neighbors,wtd列表将有5个值.下一行计算总影响,将其存储在不同的值中,以便对当前值进行所有计算。请注意,我没有准确地使用您的等式,因为我不知道您是如何防止它简单地失控增长的。
我意识到这并不能回答您关于表性能的问题,但我希望这种方法能够解决所有的性能问题。
发布于 2020-09-11 05:36:21
在提交这份报告后,我尝试了一项实验,证实了我的怀疑,我认为结果是找到了一个可以接受的解决方案。事实证明,简单地要求海龟去看“海龟i”是很慢的,而且随着越来越多的药剂的增加,速度也会变慢。
我猜想,使用of turtle i网络徽标可以执行与of turtles with [who = i]相当的操作,并且必须遍历所有海龟的列表,直到找到匹配的ID为止。因此,作为一个测试,再次使用表扩展,我手动创建了一个所有海龟的表:
globals [turtleTable]
...
to initialize-turtleTable
set turtleTabletable:make
ask turtles [
table:put turtleTable who self
]
end然后,您可以说是of turtle i而不是of table:get turtleTable i。这是稍微麻烦一些的语法,但可以由记者清理。这样做的结果与最初预期的一样,与使用链接大致相同,但与完全退出和重新启动NetLogo相比,大约25000个代理使用了将近一半的内存(<3GB vs >5GB)。
https://stackoverflow.com/questions/63840962
复制相似问题