Юлия Параллелизм: @distributed (+) медленнее серийного? - PullRequest
0 голосов
/ 22 октября 2018

Увидев в Интернете несколько учебников по параллелизму Джулии, я решил реализовать небольшой параллельный фрагмент кода для вычисления ряда гармоник.

Серийный код:

harmonic = function (n::Int64)
    x = 0
    for i in n:-1:1 # summing backwards to avoid rounding errors
        x +=1/i
    end
    x
end

И ясделал 2 параллельные версии, одну с использованием макроса @distributed, а другую с использованием макроса @everywhere (julia -p 2 btw):

@everywhere harmonic_ever = function (n::Int64)
    x = 0
    for i in n:-1:1
        x +=1/i
    end
    x
end

harmonic_distr = function (n::Int64)
    x = @distributed (+) for i in n:-1:1
        x = 1/i
    end
    x
end

Однако, когда я запускаю приведенный выше код и @time it, яне получайте никакого ускорения - на самом деле, версия @distributed работает значительно медленнее!

@time harmonic(10^10)
>>> 53.960678 seconds (29.10 k allocations: 1.553 MiB) 23.60306659488827
job = @spawn harmonic_ever(10^10)
@time fetch(job)
>>> 46.729251 seconds (309.01 k allocations: 15.737 MiB) 23.60306659488827
@time harmonic_distr(10^10)
>>> 143.105701 seconds (1.25 M allocations: 63.564 MiB, 0.04% gc time) 23.603066594889185

То, что полностью и абсолютно сбивает с толку, это "0.04% gc time".Я явно что-то упускаю, а также примеры, которые я видел, не для версии 1.0.1 (например, используется @parallel).

1 Ответ

0 голосов
/ 22 октября 2018

Ваша распределенная версия должна быть

function harmonic_distr2(n::Int64)
    x = @distributed (+) for i in n:-1:1
        1/i # no x assignment here
    end
    x
end

Цикл @distributed будет накапливать значения 1/i на каждом работнике и, наконец, на главном процессе.

Обратите внимание, чтотакже обычно лучше использовать BenchmarkTools * @btime макрос вместо @time для сравнения:

julia> using Distributed; addprocs(4);

julia> @btime harmonic(1_000_000_000); # serial
  1.601 s (1 allocation: 16 bytes)

julia> @btime harmonic_distr2(1_000_000_000); # parallel
  754.058 ms (399 allocations: 36.63 KiB)

julia> @btime harmonic_distr(1_000_000_000); # your old parallel version
  4.289 s (411 allocations: 37.13 KiB)

Параллельная версия, конечно, медленнее, если работать только наодин процесс:

julia> rmprocs(workers())
Task (done) @0x0000000006fb73d0

julia> nprocs()
1

julia> @btime harmonic_distr2(1_000_000_000); # (not really) parallel
  1.879 s (34 allocations: 2.00 KiB)
...