【问题标题】:AnyLogic: Improving computational performance of a network modelAnyLogic:提高网络模型的计算性能
【发布时间】:2018-04-27 07:38:51
【问题描述】:

我正在使用基于代理的流行病模型。这个想法是个体代理根据他们在网络中观察到的内容(基于距离)做出决策。我在每个代理中都有几个函数可以动态更新受感染联系人的计数、显示特定行为的联系人等。

以下代码用于计算代理网络中受感染的联系人。

int infectedConnections = 0;

if (getConnections() != null)
    for (Agent a : this.getConnections())
        {
        Person p = (Person) a;

        if (p.IsCurrentlyInfected()) 
            infectedConnections++;
            }

return infectedConnections ;

至少还有 3 个这样的功能,用于记录在代理网络中表达其他功能的其他代理的数量。现在,当我有

是否有一种计算效率更高的方法可以在 Anylogic 中为更大的人群跟踪网络统计信息?

【问题讨论】:

  • 这个问题你可以用一个更好的标题;目前非常笼统/模糊。

标签: java performance simulation anylogic agent-based-modeling


【解决方案1】:

模型未初始化,因为默认内存量不足以容纳 5000 个代理。如果每个代理都与所有其他代理连接(每个代理 4999 个连接),则需要 > 1.300 Mb 的 RAM,而默认模拟实验仅分配 512 Mb 的 RAM。更改实验属性中的内存量。然后,所有 5000 个代理的代码大约需要 1 秒。换句话说,如果我每秒收集一次统计信息,最大执行速度大约是每 1 个真实秒 1 个模型秒。

如果用Java Stream API重写代码,你可以增加它: return (int)getConnections().stream() .filter( a -> (Person)a).IsCurrentlyInfected()) .count();

然后,在 0.5 实际秒(x2 增益)内执行 1 个模型秒。如果统计数据收集是并行执行的(使用多个线程,由 Java 代码创建),那么您可能会获得相应的收益,具体取决于 PC 上的内核数量。 无论如何,这是计算复杂度的问题,所以你需要改变方法(see @pjs answer),否则性能真的很差。

【讨论】:

  • 关于初始化问题的很好的具体答案。
【解决方案2】:

你的结果是事情在 1000 到 5000 之间停滞不前,这在我见过的基于代理的模型中很常见。这是一个基本的计算复杂性问题。使用 N 个代理,2-way 交互的数量为 N.choose.2,即 O(N^2)。 5000 个代理的工作量大约是 1000 个代理的 25 倍。

您可以通过本地化实现一些特技。基本上,根据特定区域中的代理无法与其他区域中的代理交互的事实将您的沙盒划分为不同的游戏区域,因此您只需检查交互的子集。如果可能的话,将 N 个代理分成 k 个独立的组,运行时间会提高 O(k) 倍。

另一种选择可能是摆脱时间步长框架,为您的问题制定基于事件的设计。您可以在 this paper 中找到这种方法的示例。

【讨论】:

    【解决方案3】:

    正如其他答案所涵盖的那样,您的问题实际上是两个问题:

    • 随着代理数量的增加(因为每个代理都连接到其他所有代理),总网络连接非线性增加导致的内存使用和“基础”模型速度;

    • 您的统计数据收集效率。

    我很惊讶没有人提到它,但后者的主要性能问题是因为(似乎)你在需要时重新计算统计数据(而你没有' t 指定需要计算的频率),而不仅仅是维护计数随着影响它们的状态变化

    (这是一个通用的编程权衡:(a)最小化内存并避免在所有适当的时间不更新计数的潜在错误[如您的方法]与(b)通过保留 em> 计数并仅在它们依赖的事件发生时更新它们。)

    因此,只要每个代理从未感染变为受感染或反之亦然,就让每个代理更新其连接代理中的计数。

    例如,假设您有 10 个代理,因此每个代理有 9 个连接(总共 90 个连接)。假设一个代理每 10 模拟分钟(平均)更改一次感染/从感染更改,并且您运行了 60 分钟。并且您每分钟更新每个代理中的“受感染连接数”。 (如果你效率很高,这个间隔将是可能转换之间的最短时间间隔,但很可能你查询它的频率比那个高得多,或者最短时间间隔非常小。)

    使用您的方法,您将检查 90 个连接 60 次(因此对代理的 5400 次访问,以及获取/循环每个代理的连接的开销)。

    使用我的方法,将有 6x10 = 60 次相关转换,因此 60x9 = 540 次访问代理(以增加/减少计数),加上仅获取/循环通过代理的连接 60 次,而不是 60x10 = 600 次。 因此性能提升 >10 倍

    与您需要使用统计数据的频率(反之亦然)相比,“稀有”转换明显提高了效率,因此在某些情况下,这两种方法的性能相似。

    【讨论】:

    • 它导致总体上相同数量的操作,因此它可能使执行更顺畅,但总时间是相同的。
    • @GregoryMonahov 怎么会一样呢?从他写的内容来看,他似乎有 extra 日常事件进行所有循环以计算每日计数(而不是在没有额外循环的情况下更新它们)。我们对问题的看法不同吗?
    • 如果我正确理解你的建议,每个代理都应该通知其他连接的代理有关感染标志的变化,这样他们就会知道他们有多少感染连接代理。成像他们同时更新它们(它是模型逻辑的一部分,而不是统计数据收集的一部分)。在传染性更新时向每个连接的代理发送“通知”的情况下,以及每个代理的当前计算,操作的数量是相同的。
    • @GregoryMonahov 不,因为他会在每次需要时更新计数,而不仅仅是每次更改时。请参阅明确的答案。 (仅 3 年后!)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-18
    • 2019-04-25
    • 2011-10-28
    • 1970-01-01
    • 2011-08-06
    • 2018-10-19
    相关资源
    最近更新 更多