У меня есть набор чисел ~ 100, я хочу выполнить симуляцию MC на этом наборе, основная идея состоит в том, что я полностью рандомизирую набор, провожу сравнение / проверку первых ~ 20 значений, сохраняю результат и повторяю.
Теперь фактический алгоритм сравнения / проверки чрезвычайно быстр, он фактически завершается примерно за 50 циклов ЦП. Имея это в виду и чтобы оптимизировать эти симуляции, мне нужно как можно быстрее сгенерировать случайные наборы.
В настоящее время я использую алгоритм Multiply With Carry Джорджа Марсальи, который довольно быстро предоставляет мне случайное целое число за 17 циклов процессора. Однако, используя алгоритм перетасовки Фишера-Йейтса, мне нужно сгенерировать 100 случайных целых чисел, ~ 1700 циклов ЦП. Это намного затмевает мое время сравнения.
Итак, мой вопрос: есть ли другие хорошо известные / надежные методы для выполнения этого типа моделирования MC, где я могу избежать длительного времени генерации случайного набора?
Я думал о том, чтобы просто случайным образом выбрать 20 значений из набора, но тогда мне пришлось бы выполнить проверки на коллизии, чтобы убедиться, что были выбраны 20 уникальных записей.
Обновление:
Спасибо за ответы. У меня есть еще один вопрос относительно метода, который я только что придумал после своего поста. Вопрос в том, обеспечит ли это надежный действительно (при хорошем ГСЧ) случайный вывод. В основном мой метод состоит в том, чтобы создать массив целочисленных значений той же длины, что и мой входной массив, установить каждое значение в ноль. Теперь я начинаю случайным образом выбирать 20 значений из входного набора следующим образом:
int pcfast[100];
memset(pcfast,0,sizeof(int)*100);
int nchosen = 0;
while (nchosen<20)
{
int k = rand(100); //[0,100]
if ( pcfast[k] == 0 )
{
pcfast[k] = 1;
r[nchosen++] = s[k]; // r is the length 20 output, s the input set.
}
}
В основном то, что я упомянул выше, случайный выбор 20 значений, за исключением того, что это кажется несколько оптимизированным способом обеспечения отсутствия коллизий. Обеспечит ли это хороший случайный вывод? Это довольно быстро.
int rand(int n) { int r; do { r = rand100() } while (r >= n); return r}
. Но он выполняет немного меньше копирования, и на x64 у вас может быть даже достаточно регистров, чтобы хранить эти 100 флагов в двух длинных переменных и не перетекать в стек. - person Steve Jessop   schedule 08.08.2009