AnyLogic: повышение вычислительной производительности сетевой модели
Я работаю с агентной моделью эпидемии. Идея заключается в том, что отдельные агенты принимают решения на основе того, что они наблюдают в своих сетях (на основе расстояния). У меня есть несколько функций в каждом агенте, которые динамически обновляют количество зараженных контактов, контакты, показывающие определенное поведение и т. Д.
Приведенный ниже код предназначен для подсчета зараженных контактов в сети агента.
int infectedConnections = 0;
if (getConnections() != null)
for (Agent a : this.getConnections())
{
Person p = (Person) a;
if (p.IsCurrentlyInfected())
infectedConnections++;
}
return infectedConnections ;
Будет как минимум еще 3 такие функции, которые будут вести подсчет других агентов, выражающих другие функции в сети агента. Теперь, кажется, все работает хорошо, когда у меня <500 агентов, но когда я увеличиваю популяцию агентов примерно до 1000 или около того, модель становится чрезвычайно медленной. Я собираюсь смоделировать по крайней мере 5000 агентов, и на данный момент модель даже не инициализируется.
Есть ли более эффективный в вычислительном отношении способ отслеживания сетевой статистики в Anylogic для больших групп населения?
3 ответа
Ваш результат того, что дела идут где-то между 1000 и 5000, довольно часто встречается в моделях на основе агентов, которые я видел. Это основная проблема вычислительной сложности. С N агентами число двусторонних взаимодействий равно N.choose.2, что равно O(N^2). 5000 агентов - это примерно в 25 раз больше работы, чем 1000 агентов.
Вы можете тянуть некоторые трюки с локализацией. По сути, разделите свою песочницу на разные игровые зоны, основываясь на том факте, что агенты в определенной области не могут взаимодействовать с агентами в других областях, поэтому вам нужно только проверить подмножество взаимодействий. Разделение N агентов на k независимых группировок, если это возможно, даст увеличение в O(k) раз во время выполнения.
Другой альтернативой может быть отказ от временной структуры и разработка основанного на событиях проекта для вашей проблемы. Вы можете найти пример такого подхода в этой статье.
Модель не инициализируется, поскольку объема памяти по умолчанию недостаточно для 5000 агентов. Это занимает>1,300 МБ ОЗУ в случае, если каждый агент связан со всеми другими агентами (4999 подключений на каждого агента), в то время как эксперимент по моделированию по умолчанию выделяет всего 512 МБ ОЗУ. Измените объем памяти в свойствах эксперимента. Затем код занимает около 1 реальной секунды для всех 5000 агентов. Другими словами, если я собираю статистику каждую секунду, максимальная скорость выполнения составляет около 1 модельной секунды за 1 реальную секунду.
Вы можете увеличить его, если переписать код с помощью Java Stream API:return (int)getConnections().stream()
.filter( a -> (Person)a).IsCurrentlyInfected())
.count();
Затем выполняется 1 модель с за 0,5 реальных секунды (усиление х2). В случае, если сбор статистики выполняется параллельно (с несколькими потоками, созданными кодом Java), вы можете получить соответствующее усиление, в зависимости от количества ядер на ПК. В любом случае, это проблема сложности вычислений, поэтому вам нужно изменить подход ( см. Ответ @pjs), в противном случае производительность действительно плохая.
Поскольку другие ответы покрывают, Ваш вопрос - действительно два вопроса:
использование памяти и "базовая" скорость модели из-за увеличения общего количества сетевых подключений по мере увеличения числа агентов;
Ваша статистика собирает эффективность.
Я удивлен, что никто не упомянул об этом, но очевидная альтернатива для последнего состоит в том, что, если вы просто сохраняете статистику по числу зараженных в настоящее время, почему бы просто не заставить агентов обновлять соответствующие подсчеты, когда они входят / выходят из зараженных состояний (либо с "фактическими" состояниями через диаграмму состояний AnyLogic или другими способами представления его через функции и т. д.)? И аналогично для любой статистики по другим изменениям состояния, передаваемым по сети...