parallel-processing - 多进程模块加载

标签 parallel-processing multiprocessing julia

我对使用工作进程时 Julia 加载模块的行为感到困惑。

我需要使用相当重的 PyPlot 模块,该模块需要相当长的时间来加载。该程序:

using PyPlot
pygui(true)
println("Loaded")

在我的笔记本电脑上加载大约需要 11 秒:

% time julia test.jl 
INFO: Loading help data...
Loaded
julia test.jl  11,10s user 0,18s system 99% cpu 11,323 total

请注意INFO:正在加载帮助数据... 行。它似乎是由 PyPlot 模块发出的,因为如果我省略 using PyPlot 行,它就不会出现。

但是,当我运行这个程序时:

using PyPlot
pygui(true)
@everywhere println("Loaded")

我得到这些结果:

% time julia -p 4 test.jl 
INFO: Loading help data...
INFO: Loading help data...
INFO: Loading help data...
INFO: Loading help data...
INFO: Loading help data...
Loaded
    From worker 2:  Loaded
    From worker 5:  Loaded
    From worker 3:  Loaded
    From worker 4:  Loaded
julia -p 4 test.jl  88,94s user 1,19s system 266% cpu 33,865 total

它不仅运行了长达 33 秒(三倍长!),而且似乎还在每个工作线程上加载 PyPlot 模块!

但我确信,为了使模块在每个工作人员上可用,它必须是@everywhere!事实上,这个简单的程序崩溃了:

module Example
    export x
    x = 10
end

using Example

@everywhere println("x: $x")

调用:

% julia -p 4 test2.jl
x: 10
exception on 2: exception on exception on exception on 4: 5: 3: ERROR: x not defined
 in eval at /usr/bin/../lib/julia/sys.so
ERROR: x not defined
 in eval at /usr/bin/../lib/julia/sys.so
ERROR: x not defined
 in eval at /usr/bin/../lib/julia/sys.so
ERROR: x not defined
 in eval at /usr/bin/../lib/julia/sys.so

那么为什么即使我没有请求,PyPlot 模块也会加载到所有工作线程上?

更有趣的是,有一个解决方法:

using PyPlot
pygui(true)
addprocs(4)
@everywhere println("Loaded")

当我使用 julia test.jl 运行该程序时,我得到 15 秒:

% time julia test.jl     
INFO: Loading help data...
Loaded
    From worker 2:  Loaded
    From worker 4:  Loaded
    From worker 5:  Loaded
    From worker 3:  Loaded
julia test.jl  21,98s user 0,46s system 143% cpu 15,678 total

这正是我对使用 julia -p 4 test.jl 运行的原始版本所期望的。但我不喜欢这种解决方法,因为它强制我的程序使用 addprocs()

当 Julia 使用 -p X 参数启动时,是否有办法限制模块加载到主进程?

最佳答案

让我们使用 DummyModule.jl 进行测试:

module DummyModule

export MyType, f

type MyType
    a::Int
end

f(x) = x^2+1

println("loaded")

end

由此我们可以看出,实际上有3种可能性。所有这些实验都是从调用为 julia -p 2 的新 julia session 运行的。

在所有进程上使用 DummyModule

julia> @everywhere using DummyModule
loaded
        From worker 3:  loaded
        From worker 2:  loaded

julia> @everywhere println(f(4))
17
        From worker 2:  17
        From worker 3:  17

julia> rr = RemoteRef(2)
RemoteRef(2,1,24)

julia> put!(rr, MyType(7))
RemoteRef(2,1,24)

julia> fetch(rr)
MyType(7)

仅在驱动程序进程上使用 DummyModule

julia> include("DummyModule.jl")
loaded

julia> using DummyModule

julia> @everywhere println(f(4))
exception on 2: 17
exception on 3: ERROR: f not defined
 in eval at /home/tim/src/julia/base/sysimg.jl:7
 in anonymous at multi.jl:1383
 in anonymous at multi.jl:819
 in run_work_thunk at multi.jl:592
 in run_work_thunk at multi.jl:601
 in anonymous at task.jl:6
ERROR: f not defined
 in eval at /home/tim/src/julia/base/sysimg.jl:7
 in anonymous at multi.jl:1383
 in anonymous at multi.jl:819
 in run_work_thunk at multi.jl:592
 in run_work_thunk at multi.jl:601
 in anonymous at task.jl:6

julia> rr = RemoteRef(2)
RemoteRef(2,1,14)

julia> put!(rr, MyType(7))
WARNING: Module DummyModule not defined on process 2
fatal error on 2: ERROR: DummyModule not defined
 in deserialize at serialize.jl:376
 in handle_deserialize at serialize.jl:351
 in deserialize at serialize.jl:505
 in handle_deserialize at serialize.jl:351
 in deserialize at serialize.jl:334
 in anonymous at serialize.jl:354
 in ntuple at tuple.jl:30
 in deserialize_tuple at serialize.jl:354
 in handle_deserialize at serialize.jl:346
 in anonymous at task.jl:824
Worker 2 terminated.ERROR: ProcessExitedException()
 in wait at ./task.jl:284
 in wait at ./task.jl:194
 in wait_full at ./multi.jl:574
 in remotecall_fetch at multi.jl:675
 in remotecall_fetch at multi.jl:680
 in call_on_owner at multi.jl:722
 in put! at multi.jl:743

(请注意,不同消息的打印顺序是不确定的;在 2: 17 的异常 中,异常 ... 部分是由于错误从进程 2 发出,17 来自进程 1 上的打印 f(4)。)

仅在进程1上使用,但在worker之间传递数据

julia> using DummyModule
loaded
        From worker 3:  loaded
        From worker 2:  loaded

julia> @everywhere println(f(4))
exception on 2: 17
exception on 3: ERROR: f not defined
 in eval at /home/tim/src/julia/base/sysimg.jl:7
 in anonymous at multi.jl:1383
 in anonymous at multi.jl:819
 in run_work_thunk at multi.jl:592
 in run_work_thunk at multi.jl:601
 in anonymous at task.jl:6
ERROR: f not defined
 in eval at /home/tim/src/julia/base/sysimg.jl:7
 in anonymous at multi.jl:1383
 in anonymous at multi.jl:819
 in run_work_thunk at multi.jl:592
 in run_work_thunk at multi.jl:601
 in anonymous at task.jl:6

julia> rr = RemoteRef(2)
RemoteRef(2,1,19)

julia> put!(rr, MyType(7))
RemoteRef(2,1,19)

julia> using DummyModule

julia> fetch(rr)
MyType(7)

最后一种情况的区别在于,序列化程序实际上知道如何处理所有进程上的 MyType,从而可以安全地在工作程序之间传递数据。

关于parallel-processing - 多进程模块加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26168943/

相关文章:

parallel-processing - 在 Julia 的函数中使用 addprocs() 和 pmap()

julia - Julia 中使用的函数参数中的美元符号前缀是什么?

performance - Julia 中的并行实现比串行慢

.net - 多线程->多处理趋势

python - 使用 python 的 Multiprocessing 使响应卡在 gunicorn 上

http - 如何在 Julia 中发出启用 SSL 的 HTTP 请求?

c# - Parallel.ForEach 停止为最后几个项目并行

c# - skynet 基准测试中的 TPL 样本并非真正并行?

python-3.x - 当父对象包含大数据时,多处理速度缓慢

python - 如何在 python 中设计弹性和高可用的服务?