Warm tip: This article is reproduced from serverfault.com, please click

其他-在Julia中以并行方式计算数组

(其他 - Calculate Array in a Parallel Way in Julia)

发布于 2020-11-28 17:53:24

我已经使用Julia了一段时间,但对它的了解仍然很少,尤其是对于并行计算。我想使用现有数据获取一个新数组,因为该数组非常大,我想以并行方式进行操作,并且代码编写如下:

ψ1 = Array{Complex}(undef, D)
ψ = rand(Complex{Float64},D)
Threads.@threads for k = 1:D   
    ψ1[k] = @views sum(ψ[GetBasis(k - 1, N)])  
end

我使用julia -t 4来运行它,但是与非并行代码相比,它的运行速度非常慢,如下所示:

ψ1 = [@views sum(ψ[GetBasis(k - 1, N)]) for k=1:D]

我不知道为什么会这样,GetBasis()只是一个生成数组的函数,即Array {Int64,1}(N)。

我想问一下如何改善第一个代码,或者是否可以通过某种方式修改第二个代码以使其并行运行?由于数组可能非常大,我想找到一种方法来加快它的速度...

非常感谢,期待你的答复!

完整的代码如下

function GetBasis(n, N)
    xxN = collect(0:N-1)
    BI = BitFlip.(n,xxN).+1
end


function BitFlip(n, i)
    n = n ⊻ (1 << i)
end

N=24
D=2^N

ψ1 = Array{Complex}(undef, D)
ψ = rand(Complex{Float64},D)
Threads.@threads for k = 1:D   
    ψ1[k] = @views sum(ψ[GetBasis(k - 1, N)])  
end

ψ2 = [@views sum(ψ[GetBasis(k - 1, N)]) for k=1:D]

Questioner
wangjz87
Viewed
0
Przemyslaw Szufel 2020-11-29 08:07:24

如果所有步骤都正确完成,那么多线程代码确实会更快。

function GetBasis(n, N)
    BI = BitFlip.(n,0:N-1).+1
end

function BitFlip(n, i)
    n = n ⊻ (1 << i)
end

const N=24
const D=2^N

const ψ = rand(Complex{Float64},D)
const ψ1 = Vector{Complex{Float64}}(undef, D)

using BenchmarkTools

Threads.nthreads() # should return 4 or more
                   # set JULIA_NUM_THREADS environment variable

现在测试:

julia> GC.gc()

julia> @btime ψ2 = [@views sum(ψ[GetBasis(k - 1, N)]) for k=1:D];
  5.591 s (16777218 allocations: 4.50 GiB)

julia> GC.gc()

julia> @btime Threads.@threads for k = 1:D
           @inbounds ψ1[k] = @views sum(ψ[GetBasis(k - 1, N)])
       end
  2.293 s (16777237 allocations: 4.25 GiB)

请注意此代码使用的内存量-你需要在运行Benchamrk之前运行垃圾回收器,并且当计算机中的RAM少于16GB时,该测试的意义将减小。