簡體   English   中英

是否random.seed(seed)在多個進程中生成相同的序列?

[英]Does random.seed(seed) generate same sequence in multiple processes?

2017年7月19日更新

在此處找到解決方案: https : //stackoverflow.com/a/10021912/5729266

如果您不想讀到最后,可以快速得出結論。

我之前的代碼中隨機數的不一致是由線程不安全引起的,因為即使每個線程處理一個包含隨機模塊的單獨實例,隨機模塊也被視為全局變量。

要解決該問題,您必須使用線程鎖定或生成獨立的隨機實例,如上面的鏈接中所述。 請參閱下面的測試代碼。

import threading
import random

class do_threads:

    def __init__(self):
        # Using random directly is thread-unsafe
        # self.random = random 

        # instead of using random, create a local random instance
        self.random = random.Random()

    def __call__(self, n):
        self.n = n
        self.run_thread()

    def get_balance(self, e):
        self.random.seed(self.n)
        return self.random.uniform(0, 1)


    def run_thread(self):
        total = []
        for i in range(100000):
           total.append(self.get_balance())
        print(sum(total) / 100000)

a = do_threads()
b = do_threads()

t1 = threading.Thread(target=a, args=(5,))
t2 = threading.Thread(target=b, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()

舊帖子:

在我的Python程序中,我需要使用multiprocessing.pool運行N個子multiprocessing.pool 每個子進程產生M個線程,每個線程都需要為數據幀的“ ID”列中的ID生成哈希碼。

哈希碼需要遵循uniform(0,1)的分布。 為此,我使用ID作為種子( random.seed(ID) )設置隨機狀態,然后從random.uniform(0, 1)生成一個隨機密鑰。 但是,ID有大約0.01%的機會具有不同的隨機數。 例如,在所有這些線程/子進程中,ID'200300'出現10000次,但是它具有一個隨機密鑰的9999次和具有另一個隨機密鑰的1倍。

所以,我的問題是:random.seed(seed)是否始終在並行程序中生成相同的序列? 如果不是,我該如何解決隨機狀態以確保random.uniform(0, 1)在給定相同ID的情況下彈出相同的數字? 我也對其他可以將ID哈希為具有均勻(0,1)分布的隨機變量的方法持開放態度。

只是請注意,我想在工作中使用進程和線程,並且無法在程序運行期間將這些數據幀連接在一起以一次生成隨機密鑰。

我嘗試使用multiprocessing.Manager共享隨機狀態或在父進程中導入隨機狀態,或將random_generator()作為實例或對象從父進程傳遞到子環境。 但是似乎事情沒有按預期進行。

這是我的代碼的簡單版本:

#mythreads.py
from foo import Foo

class TaskWorker(Thread):
        def __init__(self, queue):
            Thread.__init__(self)
            self.queue = queue
        def run(self):
            while True:
                Foo, task = self.queue.get()
                Foo(task).generate_data(df)

def mythreads():
    queue = Queue()
    for x in range(10):
        worker = TaskWorker(queue)
        worker.daemon = True
        worker.start()
    for task in sub_list:
        queue.put((Foo, task))
    queue.join()

# foo.py
import random
class Foo:
    def __init__(self, task):
        ...

    def random_generator(self, e):
        random.seed(e)
        randomkey = random.uniform(0, 1)

    def generate_data(self, df):
        df['RK'] = df[‘ID’].apply(self.random_generator)
        ...

#main.py
from multiprocessing.pool import Pool
from mythreads import mythreads
with Pool(N) as p:
    p.map(mythreads, list_of_sublists)

注意 :我使用Python 3.6

摘要

問: random.seed(seed)是否始終在並行程序中生成相同的序列?

答:是的。

在給定相同的起始種子的情況下,保證了隨機數生成器會重現相同系列的隨機值。

另一種想法:使用random.random()代替random.uniform(0, 1) 兩者都給出相同范圍的隨機變量,但是前者既更快又慣用。

演示從同一種子開始運行不同生成器的單獨進程:

from multiprocessing.pool import Pool
from pprint import pprint
import random

def make_seq(identifier):
    random.seed(8675309)
    seq = [random.random() for i in range(4)]
    return identifier, seq

p = Pool(10)
pprint(list(p.map(make_seq, range(10))), width=100)

輸出:

[(0, [0.40224696110279223, 0.5102471779215914, 0.6637431122665531, 0.8607166923395507]),
 (1, [0.40224696110279223, 0.5102471779215914, 0.6637431122665531, 0.8607166923395507]),
 (2, [0.40224696110279223, 0.5102471779215914, 0.6637431122665531, 0.8607166923395507]),
 (3, [0.40224696110279223, 0.5102471779215914, 0.6637431122665531, 0.8607166923395507]),
 (4, [0.40224696110279223, 0.5102471779215914, 0.6637431122665531, 0.8607166923395507]),
 (5, [0.40224696110279223, 0.5102471779215914, 0.6637431122665531, 0.8607166923395507]),
 (6, [0.40224696110279223, 0.5102471779215914, 0.6637431122665531, 0.8607166923395507]),
 (7, [0.40224696110279223, 0.5102471779215914, 0.6637431122665531, 0.8607166923395507]),
 (8, [0.40224696110279223, 0.5102471779215914, 0.6637431122665531, 0.8607166923395507]),
 (9, [0.40224696110279223, 0.5102471779215914, 0.6637431122665531, 0.8607166923395507])]

請注意,所有過程都生成相同的值。

聽起來您真正想要的不是隨機數,而是ID的哈希。 查看使用Python哈希字符串

使用散列,您將獲得散布均勻且相同的散列鍵,但是相同的ID將始終轉換為相同的散列鍵。 Hashe鍵將看起來是隨機的。 從哈希鍵推導出原始ID將很困難。 如果安全是一個問題(如果真的很難從密鑰中找出ID),請避免使用MD5,否則MD5應該可以。

>>> import hashlib
>>> print (hashlib.md5('This is a test').hexdigest())
ce114e4501d2f4e2dcea3e17b546f339

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM