Должен ли я хранить экземпляр объекта случайного распределения или я могу его воссоздать?
У меня есть этот код:
static std::mt19937 rnd;
// ...
static uint32_t rndInt(uint32_t min, uint32_t max) {
return std::uniform_int_distribution<uint32_t>(min,max)(rnd);
}
Это хорошая практика или я должен хранить uniform_int_distribution
?
Ответы
Ответ 1
Я сомневаюсь, что объект распределения дорог для создания и уничтожения, хотя я полагаю, что он может сделать немного больше, чем просто сохранить параметры min,max
. Он может предсказывать некоторые полезные значения на основе параметров, например, в очевидной реализации 2**32 % (max-min+1)
- это количество различных значений из генератора, которые будут отброшены и повторены.
В принципе, объекту распределения разрешено хранить внутри него некоторые биты энтропии, которые были извлечены из генератора при предыдущем вызове operator()
, но не нужны. Эти биты могут использоваться для более позднего вызова operator()
. Поэтому, если min==0
и max==1
, вы можете получить 32 звонка на operator()
в рассылке за звонок на генераторе. Это функция reset()
, чтобы очистить это состояние.
Итак, если вы неоднократно используете одни и те же значения min/max, то технически вы теряете случайные биты с использованием нового дистрибутива каждый раз - возможно, вы, возможно, получите меньше вызовов к движку, чем если бы вы сохранили объект распределения вокруг. Но я сомневаюсь, что это важно, тем более, что MT работает быстро.
Ответ 2
Я обычно делаю следующее:
std::uniform_int_distribution<uint32_t> distrib(16, 97);
Затем вы можете называть distrib(rnd)
несколько раз, не регенерируя распределение каждый раз.
Способ выполнения операции заставляет репликацию распределять каждый раз, когда вы совершаете вызов. Если ваши параметры min и max исправлены, создайте объект распределения и вызовите его, в противном случае оставайтесь с тем, что у вас есть.
Кстати, я бы сеял rnd
, используя time(NULL)
или какой-нибудь другой метод семени.
Ответ 3
Энтропия хранится в std::mt19937
, что означает, что вы продолжите случайную последовательность, но, как отметил Стив Джессоп, у нее все еще есть некоторые накладные расходы для создания объекта. Если вы ожидаете, что эта функция будет вызываться часто с теми же аргументами, вы можете кэшировать объекты std::uniform_int_distribution<uint32_t>
на карте, которая использует std::pair<uint32_t, uint32_t>
в качестве ключа.