【问题标题】:Python: How to fix random seed inside process?Python:如何修复进程内的随机种子?
【发布时间】:2019-08-20 15:14:40
【问题描述】:

我想让每个进程产生随机数,但我希望它们在运行中可重现。

这里是示例代码:

import random
from multiprocessing import Process

random.seed(2019)

def f2():
    print('from f2:')
    v = random.randint(0, 10)
    a = random.randint(0, 10)
    print('v:', v)
    return v, a


def python_process_test():
    n_workers = 2
    workers = []
    for i in range(n_workers):
        p = Process(target=f2, args=())
        p.start()
        workers.append(p)

    for p in workers:
        p.join()


if __name__ == '__main__':
    python_process_test()

这不是所希望的行为,因为运行中的值不同:

运行 1:

from f2:
v: 6
from f2:
v: 4

运行 2:

from f2:
v: 0
from f2:
v: 5

更新:

import time
import random
from multiprocessing import Process

random.seed(2019)

def get_random_sleep_time_v1():
    return random.randint(0,3)

def get_random_sleep_time_v2():
    from datetime import datetime
    random.seed(datetime.now())
    return random.randint(0,3)

def f2(rnd_seed, process_id):
    random.seed(rnd_seed)

    # To rundomize order in which process will print
    sleep_time = get_random_sleep_time_v1()
    #sleep_time = get_random_sleep_time_v2()
    time.sleep(sleep_time)

    print('process_id:', process_id)
    v = random.randint(0, 10)
    a = random.randint(0, 10)
    print('v:', v)
    return v, a


def python_process_test():
    n_workers = 4
    workers = []
    for i in range(n_workers):
        rnd_seed = random.randint(0,10)
        p = Process(target=f2, args=(rnd_seed,i))
        p.start()
        workers.append(p)

    for p in workers:
        p.join()


if __name__ == '__main__':
    python_process_test()

使用get_random_sleep_time_v1 我得到了想要的行为,但进程的顺序不会因运行而改变:

run 1:

    process_id: 0
    v: 1
    process_id: 3
    v: 1
    process_id: 1
    v: 9
    process_id: 2
    v: 2

run 2:

    process_id: 0
    v: 1
    process_id: 3
    v: 1
    process_id: 1
    v: 9
    process_id: 2
    v: 2

使用get_random_sleep_time_v2 的进程顺序是随机的,但生成的值在运行中不一致:

run 1:
process_id: 3
v: 10
process_id: 1
v: 8
process_id: 2
v: 7
process_id: 0
v: 6

run 2:
process_id: 0
v: 8
process_id: 3
v: 10
process_id: 2
v: 10
process_id: 1
v: 8 

【问题讨论】:

  • 这与您的预期有何不同?
  • @FredLarson 查看更新。
  • 那么您还有问题吗,或者您是否将解决方案编辑到问题中(应该是答案)?
  • @FredLarson 在顶部“我想让每个进程产生随机数,但我希望它们在运行中可重现。”
  • 如果你想让睡眠时间随机但仍然使用rnd_seed,请在调用get_random_sleep_v2()之后加上random.seed(rnd_seed)

标签: python random process python-multiprocessing random-seed


【解决方案1】:

您需要在流程中设置种子:

import random
from multiprocessing import Process, Manager

def f2(i):
    random.seed(2019+i)
    print('from f2:')
    v = random.randint(0, 10)
    a = random.randint(0, 10)
    print('v:', v, 'a:', a)
    return v, a


def python_process_test():
    n_workers = 2
    workers = []

    for i in range(n_workers):
        p = Process(target=f2, args=([i]))
        p.start()
        workers.append(p)

    for p in workers:
        p.join()


if __name__ == '__main__':
    python_process_test()

这每次都会产生以下输出:

from f2:
v: 2 a: 3
from f2:
v: 9 a: 9

编辑:更新以显示工人使用不同种子重新播种每个进程的传递

【讨论】:

【解决方案2】:
import time
import random
from multiprocessing import Process
from datetime import datetime

random.seed(2222)

def get_random_sleep_time():
    random.seed(datetime.now().microsecond)
    return random.randint(0,3)

def f2(rnd_seed, process_id):
    # To randomize order in which process will print
    sleep_time = get_random_sleep_time()
    time.sleep(sleep_time)

    random.seed(rnd_seed)

    v = random.randint(0, 10)
    a = random.randint(0, 10)
    print('process_id:', process_id, 'v:', v)
    return v, a

def python_process_test():
    n_workers = 4
    workers = []
    for i in range(n_workers):
        rnd_seed = random.randint(0,10)
        p = Process(target=f2, args=(rnd_seed,i))
        p.start()
        workers.append(p)

    for p in workers:
        p.join()

if __name__ == '__main__':
    python_process_test()

【讨论】:

    【解决方案3】:

    一个简单的修复,所以不用担心:

    如果要每次生成相同的数字,则需要每次传递相同的种子值。 1

    所以您需要做的就是在每个randint() 之前调用random.seed(2019)

    本质上,每次使用 random 模块获取值时,它都会从当前系统时间中拉取.seed() 值。因此,您每次都必须手动设置种子,否则它将默认返回该行为。

    【讨论】:

    • 如果你不断重置种子,你只会得到相同的数字。您只需要在第一次调用之前播种即可。
    猜你喜欢
    • 2020-04-18
    • 1970-01-01
    • 1970-01-01
    • 2012-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-12
    相关资源
    最近更新 更多