繁体   English   中英

我们如何在 Julia 中并行生成随机数?

[英]How can we generate random numbers in parallel in Julia?

我正在为蒙特卡罗模拟编写并行化的 julia 代码。 这需要我在不同的内核上并行生成随机数。 在我的工作站上的一个简单测试代码中,我尝试在 4 个内核上生成随机数并得到以下结果:

julia -p 4

julia> @everywhere using Random

julia> @everywhere x = randn(1)

julia> remotecall_fetch(println,1,x[1])
-1.9348951407543997

julia> remotecall_fetch(println,2,x[1])
      From worker 2:    -1.9348951407543997

julia> remotecall_fetch(println,3,x[1])
      From worker 3:    -1.9348951407543997

julia> remotecall_fetch(println,4,x[1])
      From worker 4:    -1.9348951407543997

我不明白为什么从不同进程中获取的数字会给出完全相同的结果。 我不确定是什么错误。 我的理解是,使用 @everywhere 宏可以让您在所有进程上并行运行相同的代码。 我目前在我的电脑上是 julia 1.6.0。 谢谢你。

更新:感谢您的回复。 基本上,我正在寻找的是一个像 x = y 这样的赋值语句,其中 x 和 y 都是工作进程的本地。 我试过这样的事情:

julia -p 4

@sync @distributed for i = 1:2
       x = randn(1)
       println(x)
       end
      From worker 3:    [0.4451131733445428]
      From worker 2:    [-0.4875627629008678]
Task (done) @0x00007f1d92037340

julia> remotecall_fetch(println,2,x)
ERROR: UndefVarError: x not defined
Stacktrace:
 [1] top-level scope
   @ REPL[23]:1

这似乎在每个进程上独立生成随机数。 但是,我不知道如何访问变量x了。 我尝试了remotecall_fetch(println, 2,x)但变量x似乎没有在工作进程上定义。 这非常令人困惑。

我希望有很好的流程图或好的文档来解释并行计算期间 Julia 中变量和表达式的 scope。

remotecall_fetch从您的本地进程(具有 id 1)发送x[1]进行评估。 您可以通过运行以下代码来检查它:

# julia -p 4

julia> @everywhere x = myid() # make sure x holds a worker number

julia> remotecall_fetch(println, 4, x) # x passed from worker 1 (local machine) to println
      From worker 4:    1

julia> @sync @everywhere println(x) # x is evaluated on worker
1
      From worker 3:    3
      From worker 2:    2
      From worker 4:    4
      From worker 5:    5

julia> @sync @everywhere println($x) # x interpolated from local machine
1
      From worker 4:    1
      From worker 5:    1
      From worker 3:    1
      From worker 2:    1

关于远程机器上的随机数生成,您应该确保在每台机器上创建独立的随机数流。 对于大多数情况来说,最简单的方法就是使用Random.seed! function 在不同的工人身上使用不同的种子。 如果您想格外小心,请使用Future.randjump确保工作进程上的随机数生成器没有重叠。

最好的方法是拥有一个随机的 state 并将其切片,每个工人都有一个。 这可以这样做:

using Distributed
addprocs(4)
@everywhere import Future, Random
@everywhere const rng = Future.randjump(Random.MersenneTwister(0), myid()*big(10)^20)

现在,每个工人都有一个本地工人,但 Julia 感知全局rng变量。

在这个例子中,我使用了0和随机数种子。 手册中建议使用big(10)^20randjump大小,因为在 Julia 中,此步骤已经预先计算了值。

要使用这样的 rng,您可以定义一个 function,例如:

@everywhere getr(rng=rng) = rand(rng, 5)

这可以称为

fetch(@spawnat 2 getr())

基本上rng因为它是global ,所以它应该作为最外层的参数传递给您在远程工作人员上调用的任何内容或定义为注释中提到的const

你在你的问题之上说“在不同的核心上”。 这是我用于涉及使用Threads.@thread宏在基于线程的并行性上生成随机数的函数的解决方案。 它的优点是我可以根据运行代码时的需要来选择我需要的随机性级别:

using Random, Test, Statistics

FIXEDRNG = MersenneTwister(123)

println("** Testing generateParallelRngs()...")
x = rand(copy(FIXEDRNG),100)

function innerExpensiveFunction(bootstrappedx; rng=Random.GLOBAL_RNG)
     sum(bootstrappedx .* rand(rng) ./ 0.5)
end
function outerFunction(x;rng = Random.GLOBAL_RNG)
    masterSeed = rand(rng,100:9999999999999) 
    rngs       = [deepcopy(rng) for i in 1:Threads.nthreads()]  # make new copy instances
    results    = Array{Float64,1}(undef,30)
    Threads.@threads for i in 1:30
        tsrng         = rngs[Threads.threadid()]    # Thread safe random number generator: one RNG per thread
        Random.seed!(tsrng,masterSeed+i*10)         # But the seeding depends on the i of the loop not the thread: we get same results indipendently of the number of threads
        toSample      = rand(tsrng, 1:100,100)
        bootstrappedx = x[toSample]
        innerResult   = innerExpensiveFunction(bootstrappedx, rng=tsrng)
        results[i]    = innerResult
    end
    overallResult = mean(results)
    return overallResult
end


# Different sequences..
@test outerFunction(x) != outerFunction(x)

# Different values, but same sequence
mainRng = copy(FIXEDRNG)
a = outerFunction(x, rng=mainRng)
b = outerFunction(x, rng=mainRng)

mainRng = copy(FIXEDRNG)
A = outerFunction(x, rng=mainRng)
B = outerFunction(x, rng=mainRng)
@test a != b && a == A && b == B


# Same value at each call
a = outerFunction(x,rng=copy(FIXEDRNG))
b = outerFunction(x,rng=copy(FIXEDRNG))
@test a == b

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM