【问题标题】:Parallel operations over arrays in JuliaJulia 中数组的并行操作
【发布时间】:2019-10-25 18:28:33
【问题描述】:

此代码在 Julia 中的并行(跨多个 CPU)版本是什么?

V = zeros(3)
for i = 1:100000
    cc = rand(1:3)
    V[cc] += 1
end

【问题讨论】:

  • 我不确定循环实际上是线程安全的 - 因为两个进程可以获取相同的索引并尝试同时更新它。您可能会发现手册中的this section 及其有用的部分。
  • CPU 是指核心还是机器?
  • @OscarSmith 我的意思是核心。
  • @kevbonham 这可能不安全,但其他语言对此有规定,例如原子操作,或为每个进程复制变量,然后安全地减少它们。

标签: julia


【解决方案1】:

这是对循环的直接重写,它是线程安全的,并且避免了错误共享:

using Random
using Base.Threads

V = let
    mt = Tuple([MersenneTwister() for _ in 1:nthreads()])
    Vv = Tuple([zeros(3) for _ in 1:nthreads()])
    @threads for i = 1:100000
        @inbounds cc = rand(mt[threadid()], 1:3)
        @inbounds Vv[threadid()][cc] += 1
    end
    reduce(+, Vv)
end

但是,一般来说,对于这么小的工作,使用线程可能不会给您带来太多好处。此外,如果您确实需要性能,则可能应该对代码进行一些重组,例如像这样:

function worker(iters, rng)
    v = zeros(3)
    for i = 1:iters
        cc = rand(rng, 1:3)
        v[cc] += 1
    end
    v
end

V = let
    mt = Tuple([MersenneTwister() for _ in 1:nthreads()])
    Vv = [zeros(3) for _ in 1:nthreads()]
    jobs_per_thread = fill(div(100000, nthreads()),nthreads())
    for i in 1:100000-sum(jobs_per_thread)
        jobs_per_thread[i] += 1
    end
    @assert sum(jobs_per_thread) == 100000
    @threads for i = 1:nthreads()
        Vv[threadid()] = worker(jobs_per_thread[threadid()], mt[threadid()])
    end
    reduce(+, Vv)
end

同样在 Julia 1.3 下,您不必手动管理 MersenneTwister,因为 Julia 将为每个线程创建单独的 PRNG。

【讨论】:

  • 谢谢!第一个版本有效。第二个版本返回ERROR: LoadError: BoundsError: attempt to access 1-element Array{Int64,1} at index [0] Stacktrace: [1] getindex(::Array{Int64,1}, ::Int64) at ./array.jl:728 错误。实际代码比较复杂我只是想通过一个非常简单的例子弄清楚这些事情是如何完成的。
  • 另外,这会自动使用所有可用的 CPU 内核吗?
  • 在第二个代码中,请确保您在刷新页面后准确复制粘贴我通过的内容(它适用于我的机器),并让我知道它是否适合您。该代码将使用您告诉 Julia 使用的内核数。您可以通过设置JULIA_NUM_THREADS 环境变量来设置线程数。在这里你有一个参考docs.julialang.org/en/latest/manual/parallel-computing/#Setup-1
  • 谢谢@BogumiłKamiński。 Vv = Tuple([zeros(3) for _ in 1:nthreads()]) 而不是 Vv = Tuple([zeros(3) for _ in 1:nthreads()]) 的原因是什么?
  • 你能澄清一下吗?您已经粘贴了两次相同的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多