2013-06-28 4 views
0

Я работаю над приложением, где мне нужны воспроизводимые случайные числа. Я использую srandom() с семенем для инициализации последовательности случайных чисел. Затем я использую random() для генерации случайных чисел из этого семени. Если это единственный поток, генерирующий случайные числа, все работает нормально. Однако, если существует несколько потоков, генерирующих случайные числа, они мешают друг другу.Использование функции random() для нескольких потоков

По-видимому, последовательность случайных чисел не является потокобезопасной. Должен быть центральный генератор случайных чисел, который вызывается всеми потоками.

Мое приложение генерирует сотни объектов, каждый из которых имеет четыре последовательности из 14 случайных чисел, сгенерированных таким образом. Каждая из этих 4 последовательностей имеет свое собственное неслучайное семя. Таким образом, случайные числа должны быть воспроизводимыми. Проблема состоит в том, что из-за помех потока, которые я только что описал, иногда последовательность из 14 чисел, сгенерированных, прерывается запросом случайного числа другим потоком.

Подумав об этом на некоторое время, я решил позвонить

dispatch_sync(dispatch_get_main_queue(), ^{//generate the 14 numbers}); 

, чтобы получить каждую последовательность. Это должно заставить их сформироваться в правильной последовательности. При чтении документации говорится, что может быть тупик, если в очереди запущен dispatch_sync. Как я могу узнать, уже ли я в главной очереди? Если я, мне не нужно ничего отправлять, так?

Есть ли лучший способ сделать это?

Я подозреваю, что другой способ сделать это аналогичен этому, но использует выделенную очередь вместо основной очереди. Раньше я никогда не пробовал делать свою собственную очередь. Кроме того, метод, который должен вызывать очередь, является эфемерным, поэтому мне нужно каким-то образом передать пользовательскую очередь, если я собираюсь пройти этот маршрут. Как передать очередь в качестве аргумента?

На данный момент я работаю с моей идеей, выше, синхронно отправляясь в основную очередь, и приложение, похоже, работает нормально. В худшем случае этот фрагмент кода будет выполняться примерно в 4800 раз (по 4 для каждого из 1200 объектов, что в настоящее время является максимальным).

ответ

0

Я предполагаю, что вы хотите вычислить случайные числа, а не криптографические случайные числа.

Мое предложение состояло в том, чтобы иметь отдельные RNG для каждой нити, причем каждая нить RNG посеяна централизованно из основного RNG. Поскольку система RNG не является потокобезопасной, создайте свой собственный небольшой метод RNG - хороший LCG должен работать - для использования исключительно в одном потоке.

Используйте встроенный random() для получения только начальных семян для каждой из ваших подтипов. Установка начального начального семени с помощью srandom() гарантирует, что локальные методы потока my_random() будут получать согласованное первоначальное повторение, пока потоки запускаются в том же порядке каждый раз.

Эффективно вы строите иерархию RNG, чтобы соответствовать вашей иерархии потоков.

+1

Что такое RNG и LCG? Похоже на правительственные учреждения. –

+0

Хммм. По-видимому, RNG = Random Number Genrator и LCG = линейный конгруэнтный генератор. –

+0

Правильно. Приношу свои извинения за жаргон. – rossum

0

Другим вариантом является то, чтобы одноточечный вычислить. Объект, требующий набора случайных чисел, задавал бы один сингл для них в пакете.