在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子流程。每个子过程都会产生M线程,每个线程都需要在'iD'iD'中生成IDS的标签。
哈希码需要遵循统一(0,1(的分布。为此,我使用ID作为种子(random.seed(ID)
(来设置随机状态,然后从random.uniform(0, 1)
产生一个随机键。但是,ID的随机数有大约0.01%的机会。例如,在所有这些线程/子过程中,ID'200300'出现了10000次,但是9999次它具有一个随机键,1次具有另一个随机键。
那么,我的问题是:随机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
摘要
q。 random.seed(seed(是否一直在并行程序中生成相同的序列?
a。是。
保证随机数生成器在给定种子相同的开始种子中再现相同的一系列随机值。
另一个想法:使用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的哈希字符串。
使用哈希,您会得到均匀分布和相同witdth的哈希键,但是同一ID总是会转换为同一哈希键。Hashe键将 look 随机。很难从哈希键中推导原始ID。如果安全性是一个问题(如果需要是确实很难从键中弄清楚ID(,请避免使用MD5,但是MD5应该可以。
>>> import hashlib
>>> print (hashlib.md5('This is a test').hexdigest())
ce114e4501d2f4e2dcea3e17b546f339