AnyLogic:提高网络模型的计算性能
AnyLogic: Improving computational performance of a network model
我正在使用基于代理的流行病模型。这个想法是,个体代理根据他们在网络中观察到的内容(基于距离)做出决策。我在每个代理中都有几个功能,可以动态更新受感染联系人的计数、显示特定行为的联系人等。
下面的代码用于计算代理网络中的受感染联系人。
int infectedConnections = 0;
if (getConnections() != null)
for (Agent a : this.getConnections())
{
Person p = (Person) a;
if (p.IsCurrentlyInfected())
infectedConnections++;
}
return infectedConnections ;
将至少有 3 个这样的功能,用于记录在代理网络中表达其他功能的其他代理的数量。现在,这似乎 运行 当我有 <500 个代理时,这似乎很好,但是当我将代理人数增加到大约 1,000 左右时,模型变得非常慢。我希望模拟至少 5,000 个代理,此时,模型甚至没有初始化。
是否有计算效率更高的方法来跟踪 Anylogic 中更大人群的网络统计信息?
你的结果是在 1000 到 5000 之间的某处停滞不前,这在我见过的基于代理的模型中很常见。这是一个基本的计算复杂性问题。对于 N 个智能体,2 向交互的数量为 N.choose.2,即 O(N^2)。 5000 个代理的工作量大约是 1000 个代理的 25 倍。
您可以通过本地化来完成一些特技表演。基本上,根据特定区域中的代理无法与其他区域中的代理交互这一事实,将您的沙盒划分为不同的游戏区域,因此您只需要检查交互的一个子集。如果可能,将 N 个智能体分成 k 个独立的组,将在 运行 次内产生 O(k) 倍的改进。
另一种选择可能是摆脱时间步长框架并为您的问题制定基于事件的设计。您可以在 this paper.
中找到此方法的示例
模型未初始化,因为默认内存量不足以容纳 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();
然后,然后 1 个模型秒在 0.5 个真实秒(x2 增益)中执行。如果统计数据收集是并行执行的(使用多个线程,由 Java 代码创建),那么您可能会获得相应的收益,具体取决于 PC 的内核数量。
不管怎样,这是计算复杂度的问题,所以你需要改变方法(),否则性能真的很差。
如其他答案所述,您的问题实际上是两个问题:
内存使用和 'underlying' 模型速度,因为随着代理数量的增加非线性增加总网络连接(因为每个代理都连接到每个其他代理);
您的统计数据收集效率。
我很惊讶没有人提到它,但后者的主要性能问题是因为(看起来)你在需要时重新计算统计数据 (并且您没有指定需要多久计算一次)而不是仅仅维护计数 随着影响它们的状态变化 .
(这是 (a) 最小化内存和避免在所有适当时间不更新计数的潜在错误 [如您的方法] 与 (b) 速度 保留 计数并仅在它们依赖的事件发生时更新它们。)
因此只要让每个代理在其从未感染变为感染时更新其连接代理中的计数,反之亦然。
举例来说,假设您有 10 个代理,因此每个代理有 9 个连接(总共 90 个连接)。假设代理每 10 分钟(平均)更改 to/from 感染,而你 运行 持续 60 分钟。并且您每分钟更新每个代理中的 'infected connections count'。 (如果你是高效的,这个间隔将是可能转换之间的最短时间,但很可能你查询它的频率比这高得多,或者最短时间非常小。)
使用您的方法,您将检查 90 个连接 60 次(因此对代理的 5400 次访问,以及每个代理通过连接的 getting/looping 开销)。
使用我的方法,将有 6x10 = 60 个相关转换,因此 60x9 = 540 次访问代理(increment/decrement 计数),另外仅 getting/looping 通过代理的连接 60 次60x10 = 600 次。 所以性能提高了 10 倍以上。
效率明显提高 'rarer' 与您需要使用统计信息的频率相比(反之亦然),因此,在某些情况下,这两种方法的性能相似。
我正在使用基于代理的流行病模型。这个想法是,个体代理根据他们在网络中观察到的内容(基于距离)做出决策。我在每个代理中都有几个功能,可以动态更新受感染联系人的计数、显示特定行为的联系人等。
下面的代码用于计算代理网络中的受感染联系人。
int infectedConnections = 0;
if (getConnections() != null)
for (Agent a : this.getConnections())
{
Person p = (Person) a;
if (p.IsCurrentlyInfected())
infectedConnections++;
}
return infectedConnections ;
将至少有 3 个这样的功能,用于记录在代理网络中表达其他功能的其他代理的数量。现在,这似乎 运行 当我有 <500 个代理时,这似乎很好,但是当我将代理人数增加到大约 1,000 左右时,模型变得非常慢。我希望模拟至少 5,000 个代理,此时,模型甚至没有初始化。
是否有计算效率更高的方法来跟踪 Anylogic 中更大人群的网络统计信息?
你的结果是在 1000 到 5000 之间的某处停滞不前,这在我见过的基于代理的模型中很常见。这是一个基本的计算复杂性问题。对于 N 个智能体,2 向交互的数量为 N.choose.2,即 O(N^2)。 5000 个代理的工作量大约是 1000 个代理的 25 倍。
您可以通过本地化来完成一些特技表演。基本上,根据特定区域中的代理无法与其他区域中的代理交互这一事实,将您的沙盒划分为不同的游戏区域,因此您只需要检查交互的一个子集。如果可能,将 N 个智能体分成 k 个独立的组,将在 运行 次内产生 O(k) 倍的改进。
另一种选择可能是摆脱时间步长框架并为您的问题制定基于事件的设计。您可以在 this paper.
中找到此方法的示例模型未初始化,因为默认内存量不足以容纳 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();
然后,然后 1 个模型秒在 0.5 个真实秒(x2 增益)中执行。如果统计数据收集是并行执行的(使用多个线程,由 Java 代码创建),那么您可能会获得相应的收益,具体取决于 PC 的内核数量。
不管怎样,这是计算复杂度的问题,所以你需要改变方法(
如其他答案所述,您的问题实际上是两个问题:
内存使用和 'underlying' 模型速度,因为随着代理数量的增加非线性增加总网络连接(因为每个代理都连接到每个其他代理);
您的统计数据收集效率。
我很惊讶没有人提到它,但后者的主要性能问题是因为(看起来)你在需要时重新计算统计数据 (并且您没有指定需要多久计算一次)而不是仅仅维护计数 随着影响它们的状态变化 .
(这是 (a) 最小化内存和避免在所有适当时间不更新计数的潜在错误 [如您的方法] 与 (b) 速度 保留 计数并仅在它们依赖的事件发生时更新它们。)
因此只要让每个代理在其从未感染变为感染时更新其连接代理中的计数,反之亦然。
举例来说,假设您有 10 个代理,因此每个代理有 9 个连接(总共 90 个连接)。假设代理每 10 分钟(平均)更改 to/from 感染,而你 运行 持续 60 分钟。并且您每分钟更新每个代理中的 'infected connections count'。 (如果你是高效的,这个间隔将是可能转换之间的最短时间,但很可能你查询它的频率比这高得多,或者最短时间非常小。)
使用您的方法,您将检查 90 个连接 60 次(因此对代理的 5400 次访问,以及每个代理通过连接的 getting/looping 开销)。
使用我的方法,将有 6x10 = 60 个相关转换,因此 60x9 = 540 次访问代理(increment/decrement 计数),另外仅 getting/looping 通过代理的连接 60 次60x10 = 600 次。 所以性能提高了 10 倍以上。
效率明显提高 'rarer' 与您需要使用统计信息的频率相比(反之亦然),因此,在某些情况下,这两种方法的性能相似。