Julia 中的并行实现比串行慢

pan*_*ein 6 parallel-processing performance external-process julia

为什么在下面的 Julia 代码中,并行实现比串行运行慢?

using Distributed

@everywhere function ext(i::Int64)
   callmop = `awk '{ sum += $1 } END { print sum }' infile_$(i)`
   run(callmop)
end

function fpar()
   @sync @distributed for i = 1:10
      ext(i)
   end
end

function fnopar()
   for i = 1:10
      ext(i)
   end
end

val, t_par, bytes, gctime, memallocs = @timed fpar()
val, t_nopar, bytes, gctime, memallocs = @timed fnopar()

println("Parallel: $(t_par) s. Serial: $(t_nopar) s")  
# Parallel: 0.448290379 s. Serial: 0.028704802 s
Run Code Online (Sandbox Code Playgroud)

这些文件infile_$(i)包含一列实数。经过一些研究,我遇到了处理类似问题的这篇文章另一篇文章)。不过,如果考虑到 Julia 的开发速度,它们似乎有点过时了。有没有办法改进这个平行部分?非常感谢您提前。

Prz*_*fel 7

您的代码是正确的,但您错误地衡量了性能。

请注意,对于此用例场景(调用外部进程),您应该可以使用绿色线程 - 根本不需要分配负载!

当 Julia 函数第一次执行时,它正在被编译。当您在多个并行进程上执行它时,所有这些进程都需要编译同一段代码。

最重要的是,第一个@distribution宏运行也需要很长时间来编译。因此,在使用之前,@timed您应该同时调用fparnofpar函数。

最后但并非最不重要的是addprocs,您的代码中没有,但我假设您已使用-pJulia 选项将工作进程添加到您的 Julia 主进程。顺便说一句,您没有提到您拥有多少个工作进程。

我通常这样测试代码:

@time fpar()
@time fpar()
@time fnopar()
@time fnopar()
Run Code Online (Sandbox Code Playgroud)

第一个措施是了解编译时间,第二个措施是了解运行时间。

也值得一看BenchmarkTools包和@btime宏。

关于性能测试@distributed具有显着的通信开销。在某些情况下,这可以通过SharedArrays在其他情况下使用Thread.@threads. 但是,在您的情况下,最快的代码是使用绿色线程的代码:

function ffast()
   @sync for i = 1:10
      @async ext(i)
   end
end
Run Code Online (Sandbox Code Playgroud)

  • 结果:`并行:0.010793981 s。序列号:0.031697373 秒。绿色:0.007791053`。绿色线程是最好的解决方案。多谢 :) (2认同)