Я использую MPICH2 для реализации сортировки «нечетный-четный».
Я сделал реализацию, но когда я рандомизирую каждому процессу его значение,
одно и то же число рандомизировано для всех процессов.
Вот код для каждого процесса, каждый процесс рандомизировал его значение.
int main(int argc,char *argv[])
{
int nameLen, numProcs, myID;
char processorName[MPI_MAX_PROCESSOR_NAME];
int myValue;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&myID);
MPI_Comm_size(MPI_COMM_WORLD,&numProcs);
MPI_Get_processor_name(processorName,&nameLen);
MPI_Status status;
srand((unsigned)time(NULL));
myValue = rand()%30+1;
cout << "myID: " << myID << " value: " << myValue<<endl;
MPI_Finalize();
return 0;
}
почему каждый процесс получает одинаковое значение?
Редактировать: спасибо за ответы 🙂
Я изменил линию
srand((unsigned)time(NULL));
в
srand((unsigned)time(NULL)+myID*numProcs + nameLen);
и это дает разные значения для каждого процесса 🙂
Эта задача не тривиальна.
Вы получаете те же номера, потому что вы инициализируете srand()
с time(0)
, Какие time(0)
делает возврат текущей секунды (начиная с эпохи). Так что, если все процессы имеют синхронизированные часы, все будут инициализироваться с тем же начальным числом, пока они вызывают srand()
в ту же секунду, что вполне вероятно. Я наблюдал это даже на больших машинах.
Решение 1. Используйте локальные значения для инициализации случайного начального числа.
Что я сделал, так это включил в вычисление случайного семени некоторое использование памяти от cat /proc/meminfo
в сочетании с /dev/random
, которые являются более локальными для физической машины, чем часы. Обратите внимание, что это все еще может не сработать для N задач на 1 машине. Но если я правильно помню, я также использовал task_id
, Все, что является локальным для задачи, будет достаточно. Объединение вещей тоже хорошая идея. После всего этого вычисления должны быть очень короткими по сравнению с реальными вычислениями. И лучше оставаться на безопасной стороне.
Решение 2. Подсчитайте семена как этап предварительной обработки.
Вы также можете генерировать случайные семена из task 0
используя ваш метод и распространять его с send-to-all
, Тем не менее, это может иметь проблемы с масштабированием при масштабировании (например, 10 ^ 5 процессов). Вы также можете использовать любой другой метод для загрузки параметров и просто подготовить семена в качестве шага предварительной обработки. Однако это также включает в себя некоторую нетривиальную работу.
Это потому, что ваше семя недостаточно меняется, и случайность зависит от вашего семени.
От srand
документы:
Для каждого другого начального значения, используемого в вызове srand,
Можно ожидать, что генератор псевдослучайных чисел будет генерировать другое
последовательность результатов в последующих вызовах rand.
РЕДАКТИРОВАТЬ: попробуйте сгенерировать семена заранее или поменяйте семена вручную для каждого srand
вызов.