多处理中不同工作人员的输出相同

时间:2012-10-16 12:53:21

标签: python parallel-processing multiprocessing

我有非常简单的案例,可以将工作分解并分配给工人。我尝试了here

中一个非常简单的多处理示例
import multiprocessing
import numpy as np
import time

def do_calculation(data):
    rand=np.random.randint(10)
    print data, rand
    time.sleep(rand)
    return data * 2

if __name__ == '__main__':
    pool_size = multiprocessing.cpu_count() * 2
    pool = multiprocessing.Pool(processes=pool_size)

    inputs = list(range(10))
    print 'Input   :', inputs

    pool_outputs = pool.map(do_calculation, inputs)
    print 'Pool    :', pool_outputs

上述程序产生以下输出:

Input   : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
0 7
1 7
2 7
5 7
3 7
4 7
6 7
7 7
8 6
9 6
Pool    : [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

为什么打印相同的随机数? (我的机器里有4个cpus)。这是最好/最简单的方法吗?

3 个答案:

答案 0 :(得分:13)

我认为您需要在do_calculation函数中使用numpy.random.seed重新播种随机数生成器。

我的猜测是,在导入模块时,随机数生成器(RNG)会被播种。然后,当您使用多处理时,您使用已经播种的RNG分叉当前进程 - 因此,您的所有进程都为RNG共享相同的种子值,因此它们将生成相同的数字序列。

e.g:

def do_calculation(data):
    np.random.seed()
    rand=np.random.randint(10)
    print data, rand
    return data * 2

答案 1 :(得分:0)

blog post提供了使用numpy.random和多处理时好与坏做法的示例。更重要的是要了解何时创建伪随机数生成器(PRNG)的种子:

import numpy as np
import pprint
from multiprocessing import Pool

pp = pprint.PrettyPrinter()

def bad_practice(index):
    return np.random.randint(0,10,size=10)

def good_practice(index):
    return np.random.RandomState().randint(0,10,size=10)

p = Pool(5)

pp.pprint("Bad practice: ")
pp.pprint(p.map(bad_practice, range(5)))
pp.pprint("Good practice: ")
pp.pprint(p.map(good_practice, range(5)))

输出:

'Bad practice: '
[array([4, 2, 8, 0, 1, 1, 6, 1, 2, 9]),
 array([4, 2, 8, 0, 1, 1, 6, 1, 2, 9]),
 array([4, 2, 8, 0, 1, 1, 6, 1, 2, 9]),
 array([4, 2, 8, 0, 1, 1, 6, 1, 2, 9]),
 array([4, 2, 8, 0, 1, 1, 6, 1, 2, 9])]
'Good practice: '
[array([8, 9, 4, 5, 1, 0, 8, 1, 5, 4]),
 array([5, 1, 3, 3, 3, 0, 0, 1, 0, 8]),
 array([1, 9, 9, 9, 2, 9, 4, 3, 2, 1]),
 array([4, 3, 6, 2, 6, 1, 2, 9, 5, 2]),
 array([6, 3, 5, 9, 7, 1, 7, 4, 8, 5])]

优良作法是每个线程创建一次种子,而不良作法是在导入numpy.random模块时仅创建一次种子。

答案 2 :(得分:0)

这是我使用的(可能需要更新版本的 NumPy):

import numpy as np
from multiprocessing import Pool

entropy = 42
seed_sequence = np.random.SeedSequence(entropy)

number_processes = 5

seeds = seed_sequence.spawn(number_processes)

def good_practice(seed):
    rng = np.random.default_rng(seed)
    return rng.integers(0,10,size=10)

pool = Pool(number_processes)


print(pool.map(good_practice, seeds))

输出:

[array([4, 9, 5, 9, 2, 8, 3, 3, 5, 9]), 
 array([0, 4, 1, 0, 6, 5, 3, 1, 7, 9]), 
 array([7, 0, 7, 7, 1, 0, 1, 3, 9, 6]), 
 array([8, 7, 9, 9, 1, 7, 4, 0, 5, 2]), 
 array([9, 0, 8, 9, 3, 8, 6, 6, 7, 9])]

NumPy documentation on this 实际上很有帮助。 See also