ove*_*mer 15 python random numpy multiprocessing
我正在研究Python的多处理模块.我有两个案例:
防爆.1
def Foo(nbr_iter):
for step in xrange(int(nbr_iter)) :
print random.uniform(0,1)
...
from multiprocessing import Pool
if __name__ == "__main__":
...
pool = Pool(processes=nmr_parallel_block)
pool.map(Foo, nbr_trial_per_process)
Run Code Online (Sandbox Code Playgroud)
例2.(使用numpy)
def Foo_np(nbr_iter):
np.random.seed()
print np.random.uniform(0,1,nbr_iter)
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,随机数生成器都在其分叉进程中播种.
为什么我必须在numpy示例中明确地进行种子设定,而不是在Python示例中?
ali*_*i_m 20
如果未明确提供种子,numpy.random则将使用依赖于操作系统的随机源来播种自身.通常它将/dev/urandom在基于Unix的系统(或某些Windows等效系统)上使用,但如果由于某种原因这不可用,那么它将从挂钟开始播种.由于自动种子在新的子进程分叉时发生,因此如果它们同时分叉,则多个子进程可以继承相同的种子,从而导致由不同子进程生成相同的随机变量.
这通常与您运行的并发线程数相关.例如:
import numpy as np
import random
from multiprocessing import Pool
def Foo_np(seed=None):
# np.random.seed(seed)
return np.random.uniform(0, 1, 5)
pool = Pool(processes=8)
print np.array(pool.map(Foo_np, xrange(20)))
# [[ 0.14463001 0.80273208 0.5559258 0.55629762 0.78814652] <-
# [ 0.14463001 0.80273208 0.5559258 0.55629762 0.78814652] <-
# [ 0.14463001 0.80273208 0.5559258 0.55629762 0.78814652] <-
# [ 0.14463001 0.80273208 0.5559258 0.55629762 0.78814652] <-
# [ 0.14463001 0.80273208 0.5559258 0.55629762 0.78814652] <-
# [ 0.14463001 0.80273208 0.5559258 0.55629762 0.78814652] <-
# [ 0.14463001 0.80273208 0.5559258 0.55629762 0.78814652] <-
# [ 0.64672339 0.99851749 0.8873984 0.42734339 0.67158796]
# [ 0.64672339 0.99851749 0.8873984 0.42734339 0.67158796]
# [ 0.64672339 0.99851749 0.8873984 0.42734339 0.67158796]
# [ 0.64672339 0.99851749 0.8873984 0.42734339 0.67158796]
# [ 0.64672339 0.99851749 0.8873984 0.42734339 0.67158796]
# [ 0.11283279 0.28180632 0.28365286 0.51190168 0.62864241]
# [ 0.11283279 0.28180632 0.28365286 0.51190168 0.62864241]
# [ 0.28917586 0.40997875 0.06308188 0.71512199 0.47386047]
# [ 0.11283279 0.28180632 0.28365286 0.51190168 0.62864241]
# [ 0.64672339 0.99851749 0.8873984 0.42734339 0.67158796]
# [ 0.11283279 0.28180632 0.28365286 0.51190168 0.62864241]
# [ 0.14463001 0.80273208 0.5559258 0.55629762 0.78814652] <-
# [ 0.11283279 0.28180632 0.28365286 0.51190168 0.62864241]]
Run Code Online (Sandbox Code Playgroud)
你可以看到最多8个线程的组同时分叉同一个种子,给我相同的随机序列(我用箭头标记了第一组).
np.random.seed()在子进程内调用会强制线程本地RNG实例从/dev/urandom挂钟再次播种自身,这将(可能)阻止您查看来自多个子进程的相同输出.最佳实践是将不同的种子(或numpy.random.RandomState实例)显式传递给每个子进程,例如:
def Foo_np(seed=None):
local_state = np.random.RandomState(seed)
print local_state.uniform(0, 1, 5)
pool.map(Foo_np, range(20))
Run Code Online (Sandbox Code Playgroud)
我不完全确定在这方面random和之间存在差异的基础numpy.random(也许它与选择自我种子的随机性来源的规则略有不同numpy.random?).我仍然建议将种子或random.Random实例显式传递给每个子进程以保证安全.您还可以使用其.jumpahead()方法random.Random设计用于改组Random多线程程序中的实例状态.
| 归档时间: |
|
| 查看次数: |
5057 次 |
| 最近记录: |