[초보적 해결] Distributed Arlays의 분산 병렬 포장을 사용한 추적 및 계산이 느림

Juria의 분산 병렬 패키지 Distributed Arays 느림의 속편.
Distributed Arrays를 사용하는 계산은 느리지만 한 가지 문제가 해결돼 한 걸음 더 나아갔다고 한다.하지만 또 문제가 있다.2병렬이면 병렬시보다 200배가량 느리다.

컨디션

Julia Version 1.6.0
Commit f9720dc2eb (2021-03-24 12:55 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin19.6.0)
  CPU: Intel(R) Core(TM) i7-8700B CPU @ 3.20GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-11.0.1 (ORCJIT, skylake)

코드


다음 코드를 보십시오.
paratr.jl

using Distributed
using BenchmarkTools
@everywhere using DistributedArrays

@everywhere function loop_tr(A,NC,NV)
    i_local = localindices(A)
    s = 0
    for i = 1:(i_local[3][end]-i_local[3][1]+1)
        for k=1:NC
            s += A.localpart[k,k,i]
        end
    end
    return s
end

function partial_tr(A::DArray,NC,NV)
    s = 0
    for id in workers()
        s += remotecall_fetch(loop_tr,id,A,NC,NV)
    end
    return s
end

function partial_tr(A::Array{T,3},NC,NV) where {T <: Number} 
    s = 0
    for i=1:NV
        for k=1:NC
            s += A[k,k,i]
        end
    end
    return s
end

function test()
    NC = 3
    NV = 256
    A_normal = rand(ComplexF64,NC,NC,NV)
    num_workers = nworkers()
    println("workers: ", num_workers)
    A_dist = distribute(A_normal,procs= workers(),dist= [1,1,num_workers])


    @btime tr_normal = partial_tr($A_normal,$NC,$NV)
    tr_normal = partial_tr(A_normal,NC,NV)
    println("normal: $tr_normal")

    @btime tr_dist = partial_tr($A_dist,$NC,$NV)
    tr_dist = partial_tr(A_dist,NC,NV)
    println("DArray: $tr_dist")

end
test()
하면, 만약, 만약...
>julia paratr.jl  
workers: 1
  1.127 μs (0 allocations: 0 bytes)
normal: 383.7897468470404 + 387.62678654165785im
  3.780 μs (11 allocations: 384 bytes)
DArray: 383.7897468470404 + 387.62678654165785im
.(3,3256) 치수의 3차원 배열을 만들어 (3,3)의 행렬로 256개를 배열하고 추적 행렬을 통해 합을 계산한다.Distributed Arreays는 3배 느리지만,remotecall을 사용하여 쓸데없는 계산을 하고 있는지 고려하면 됩니다.
문제는 다음과 같습니다.Distributed Arrays를 사용하려고 했던 것은 병렬 계산을 하기 때문에 병렬 추적 계산을 하려고 했다.그래서
julia -p 2 paratr.jl
workers: 2
  1.116 μs (0 allocations: 0 bytes)
normal: 376.1643269152916 + 386.4124089637121im
  214.621 μs (136 allocations: 4.73 KiB)
DArray: 376.16432691529167 + 386.4124089637116im
해봤어.이 경우 워커의 수는 2이기 때문에 2개가 병렬로 돼 있고 계산 결과는 같기 때문에 잘 계산할 수 있겠지만 계산 시간은 200배 늦어진다.
추적 계산에서 256개의 3x3 행렬의 추적을 더할 때 256개를 128개와 128개 과정으로 나누어 각각 추적의 합을 취하고 마지막에 두 개를 더한다.가격이 같기 때문에 계산 자체가 이동해야 하는데 매우 느리다.remotecall_fetch,remotecall,spawnat도 해 보았지만 지각은 변하지 않았다.
function partial_tr(A::DArray,NC,NV)
    s = 0
    f = []
    for id in workers()
        fi = @spawnat id loop_tr(A,NC,NV)
        #fi = remotecall(loop_tr,id,A,NC,NV)
        push!(f,fi)
    end

    for fi in f
        wait(fi)
        s += fetch(fi)
    end
    return s
end
원인 불명.
솔루션 모집.이 문제를 해결할 수 있다면 격자 양자 색역학 시뮬레이션 포장LatticeQCD.jl을 병행화할 수 있어 도움이 되지만 아직 해결되지 않았다.LatticeQCD.jl에서 추적을 제외하고는 3x3 행렬인 줄 알고 두 개의 적을 계산하는데 이것도 너무 느리다.

추기


얼마나 늦었는지 확인하기 위해서 나는 도표를 하나 그렸다.2는 파란색, 4는 빨간색, 보통 아리는 초록색.세로축은 시간이고 가로축은 수조의 3차원 사이즈이다.

보면 무슨 비용이 있는지 알 수 있다. 그것은 단지 몇 분만 병렬하면 된다.지출이 있어도 되지만 병렬 몇 분은 너무 느리다.이것은remotecal-fetch의 영향이야, 뭔지 알지?또 기울기 각도로 보면 빨간색과 파란색은 비슷한 느낌을 주지만 녹색의 기울기는 작다.
이 결과라면 병행화하려면 시간을 계산해야 한다.잘 못 쓰나?

추기


@antimon2선생님의 평론에 의하면
function partial_tr(A::DArray{T},NC,NV) where {T}
    s = zero(T)
    fs = [remotecall(loop_tr, id, A, NC, NV) for id in workers()]
    for f in fs
        s += fetch(f)
    end
    return s
end
따라서 병렬 동작을 할 수 있다.
remotecall_fetch를 하면 병행화의 은혜를 전혀 받지 못한다.4 시험해 본 결과를 나란히 실은 도표.세로축은 시간이고 가로축은 수조의 3차원 사이즈이다.

4 병렬의 속도가 더 빨라서 병렬화 효과가 있는 것 같다.그러나 지출을 수백 마이크로초 줄여도 4분의 1도 안 된다.DistributedArays에서 처리하는 문제가 적합하지 않을 수 있습니다.MPI.나도 jl 사용을 고려하고 싶다.

좋은 웹페이지 즐겨찾기