Подтвердить что ты не робот

Эффективный способ генерации и использования миллионов случайных чисел в Python

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

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

Или какой-нибудь другой, несомненно, более умный метод?

4b9b3361

Ответ 1

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

Пример:

# do this:
import random

for x in xrange(SOMEVERYLARGENUMBER):
    n = random.randint(1,1000) # whatever your range of random numbers is
    # Do stuff with n

# don't do this:
import random

# This list comprehension generates random numbers in a list
numbers = [random.randint(1,1000) for x in xrange(SOMEVERYLARGENUMBER)]

for n in numbers:
    # Do stuff with n

Очевидно, что на практике это действительно не имеет значения, если вы не имеете дело с миллиардами и миллиардами итераций, но зачем беспокоиться о создании всех этих чисел, если вы собираетесь использовать только один за раз?

Ответ 2

Python встроенный модуль random, например. random.random(), random.randint(), (некоторые доступные дистрибутивы, вероятно, вы хотите гауссовский) делает около 300K сэмплов/с.

Поскольку вы выполняете численное вычисление, вы, вероятно, используете numpy в любом случае, что обеспечивает лучшую производительность, если вы производите произвольный массив номер один за раз вместо одного числа за раз и более широкий выбор дистрибутивов. 60K/s * 1024 (длина массива), что ~ 60M сэмплов/с.

Вы также можете прочитать /dev/urandom в Linux и OSX. мой hw/sw (ноутбук osx) управляет ~ 10 МБ/с.

Конечно, должны быть более быстрые способы генерации случайных чисел в массе, например:

from Crypto.Cipher import AES
from Crypto.Util import Counter
import secrets

aes = AES.new(secrets.token_bytes(16), AES.MODE_CTR, secrets.token_bytes(16), counter=Counter.new(128))
data = "0" * 2 ** 20
with open("filler.bin", "wb") as f:
    while True:
        f.write(aes.encrypt(data))

Это генерирует 200 Мбайт/с на одном ядре i5-4670K

Общие шифры, такие как aes и blowfish, управляют 112MB/s и 70MB/s в моем стеке. Кроме того, современные процессоры делают еще быстрее до 700 МБ/с см. Эту ссылку, чтобы протестировать прогоны на нескольких аппаратных комбинациях. (изменить: ссылка сломана). Вы можете использовать более слабый режим ECB, если вы вставляете в него отдельные входы и достигаете до 3 ГБ/с.

Сверхточный шифр лучше подходит для задачи, например. RC4 работает на 300 Мбайт/с на моем оборудовании, вы можете получить лучшие результаты от самых популярных шифров, поскольку больше усилий было потрачено на оптимизацию этих программ и программного обеспечения.

Ответ 3

import random
for x in (random.randint(0,80) for x in xrange(1000*1000)):
    print x

Код между скобками будет генерировать только один элемент за раз, чтобы он был безопасным.

Ответ 4

Код для генерации 10M случайных чисел эффективно и быстрее:

import random
l=10000000
listrandom=[]
for i in range (l):
    value=random.randint(0,l)
    listrandom.append(value)
print listrandom

Принятое время включало время ввода-вывода, отложенное при печати на экране:

real    0m27.116s
user    0m24.391s
sys 0m0.819s