Я ищу стратегии для ускорения агентной модели, основанной на объектах класса Host
, указатели на которые хранятся в многоиндексном контейнере Boost.Я использовал Shark, чтобы определить, что подавляющее большинство времени занимает функция calcSI()
:
Функция calcSI()
должна вычисляться для каждого экземпляра классаHost
определенные вероятности, которые зависят от атрибутов других экземпляров класса Host
.(Примерно 10 000–50 000 экземпляров Host
, и эти вычисления выполняются для каждого хоста приблизительно 25 600 раз.)
Если я правильно интерпретирую профиль, большую часть времени я потратил на calcSI()
переходит к Host::isInfectedZ(int)
, который просто считает экземпляры чего-либо в Boost unordered_multimap типа InfectionMap
:
<code>struct Infection {
public:
explicit Infection( double it, double rt ) : infT( it ), recT( rt ) {}
double infT;
double recT;
};
typedef boost::unordered_multimap< int, Infection > InfectionMap;
Все члены Host
содержат InfectionMap carriage
, а Host::isInfectedZ(int)
просто подсчитывает число Infections
, связанное с определенной клавишей int
:
<code>int Host::isInfectedZ( int z ) const {
return carriage.count( z );
}
Явозникли проблемы с поиском информации о том, насколько дорогой является функция count
для неупорядоченных мультикарт в Boost.Стоит ли увеличивать накладные расходы, добавляя к Host
отдельный двумерный массив для отслеживания количества экземпляров каждого ключа (т. Е. Числа Infections
, связанного с каждым int
)?
Мне интересно, был бы более полезным структурный пересмотр мультииндекса Boost, такой как устранение одного или двух менее необходимых составных ключевых индексов.Фоновое обслуживание мультииндекса не отображается в профилировщике, что (возможно, глупо) заставляет меня беспокоиться, что оно может быть большим.У меня есть 8 индексов в мультииндексе, большинство из которых - order_non_unique.
Есть ли еще какие-то вопросы, которые могут меня беспокоить, которые могут не отображаться в профилировщике, или я пропускаюосновной результат от профилировщика?
Распараллеливание и многопоточность calcSI()
, к сожалению, не подходят.
Обновление: Может быть полезно знатьчто InfectionMap carriage
редко имеет более 10 пар и обычно <5. </p>
Обновление 2: Я попробовал стратегию, предложенную в № 1 выше, давая каждому Host
массив int carriageSummary[ INIT_NUM_STYPES ]
, который индексируется возможными значениями z
(для большинства симуляций существует <10 возможных значений).Значение каждой записи отслеживает изменения, сделанные до <code>carriage.Функция Host::isInfectedZ( int z )
теперь читает:
<code>int Host::isInfectedZ( int z ) const {
//return carriage.count( z );
return carriageSummary[ z ];
}
И время, выделенное для этой функции
, кажется значительно уменьшилось - я не могу сейчас сделать точное сравнение:
Очевидно, что использование массива довольно громоздко, но хорошо для небольших диапазонов z
.Может ли какой-нибудь другой контейнер (т.е. не unordered_map) быть более эффективным для больших диапазонов? Хотелось бы также получить какие-либо отзывы об изменении мультииндекса.