Parallel processing Julia-文件(main)中包含函数的辅助进程上的LoadError

Parallel processing Julia-文件(main)中包含函数的辅助进程上的LoadError,parallel-processing,julia,multicore,Parallel Processing,Julia,Multicore,我开始尝试使用Julia进行并行处理 在本例中,我使用了@spawn宏,但在使用remotecall\u fetch函数时出现了相同的错误 代码如下: function count_proteins(fpath::String) cnt::Int = 0 if !isfile(fpath) write(Base.stderr, "FASTA not found!") else reader = open(FASTA.Reader, fpat

我开始尝试使用Julia进行并行处理

在本例中,我使用了
@spawn
宏,但在使用
remotecall\u fetch
函数时出现了相同的错误

代码如下:

function count_proteins(fpath::String)
    cnt::Int = 0
    if !isfile(fpath)
        write(Base.stderr, "FASTA not found!")
    else
        reader = open(FASTA.Reader, fpath)
        for record in reader
            cnt += 1
        end
    end
    # return the count
    cnt
end


"""Count sequences in parallel."""
function parallel_count_proteins(fPaths::Array{String, 1}, threads::Int16=4)    
    # initialize workers
    addprocs(threads)

    fut = Dict{Int, Future}()

    # launch the jobs
    for (i, fastaPath) in enumerate(fPaths)
        r = @spawn count_proteins(fastaPath)
        fut[i] = r
    end

    for (i, res) in fut
        s = fetch(res)
    end
end

### MAIN ###
flist = ["f1", "f2", "f3", "f4"]
threads = Int16(2)
parallel_count_proteins(flist, threads)
当我尝试使用
fetch()
获取结果时,会发生错误:

错误:加载错误:在辅助进程3上

…这是stacktrace:

Stacktrace:
 [1] #remotecall_fetch#149(::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, ::Function, ::Function, ::Distributed.Worker, ::Distributed.RRID) at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.1/Distributed/src/remotecall.jl:379
 [2] remotecall_fetch(::Function, ::Distributed.Worker, ::Distributed.RRID, ::Vararg{Any,N} where N) at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.1/Distributed/src/remotecall.jl:371
 [3] #remotecall_fetch#152 at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.1/Distributed/src/remotecall.jl:406 [inlined]
 [4] remotecall_fetch at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.1/Distributed/src/remotecall.jl:406 [inlined]
 [5] call_on_owner at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.1/Distributed/src/remotecall.jl:479 [inlined]
 [6] fetch(::Future) at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.1/Distributed/src/remotecall.jl:511
 [7] parallel_count_proteins(::Array{String,1}, ::Int16) at /Users/salvocos/Google_Drive/julia_programming/mcl_graph_to_label.jl:150
 [8] top-level scope at none:0
 [9] include at ./boot.jl:326 [inlined]
 [10] include_relative(::Module, ::String) at ./loading.jl:1038
 [11] include(::Module, ::String) at ./sysimg.jl:29
 [12] exec_options(::Base.JLOptions) at ./client.jl:267
 [13] _start() at ./client.jl:436

我知道需要让所有的工作人员都知道功能的存在,但是我不确定如何做。

正如你所说,你需要让所有的工作人员进程都可以使用
计数蛋白质

可以在函数定义之前使用宏,使所有工作人员都可以使用它们
@everywhere
对所有辅助对象执行给定的表达式

另一种方法是将工作人员可以使用的函数放在另一个
.jl
文件和
@everywhere include(“my_helper_functions.jl”)
中,或者将函数定义放在
开始…结束
块中,并在
开始
之前放置一个
@everywhere
,然后运行该块。您需要在创建工作进程之后执行此操作。将这些函数放在模块/包中,并使用MyModule在任何地方运行
@也应该可以

对于您的代码,解决方案是

# addprocs here before @everywhere definitions
addprocs(2)

@everywhere function count_proteins(fpath::String)
    cnt::Int = 0
    if !isfile(fpath)
        write(Base.stderr, "FASTA not found!")
    else
        reader = open(FASTA.Reader, fpath)
        for record in reader
            cnt += 1
        end
    end
    # return the count
    cnt
end


"""Count sequences in parallel."""
function parallel_count_proteins(fPaths::Array{String, 1})
    fut = Dict{Int, Future}()

    # launch the jobs
    for (i, fastaPath) in enumerate(fPaths)
        r = @spawn count_proteins(fastaPath)
        fut[i] = r
    end

    for (i, res) in fut
        s = fetch(res)
    end
end

### MAIN ###
flist = ["f1", "f2", "f3", "f4"]
parallel_count_proteins(flist)
作为旁注,如果我理解您正试图正确地执行的操作,您可以简单地使用此处,它将一个接一个地将任务发送到进程,从而有效地平衡负载


您可能会发现阅读并行计算中的代码和数据可用性以及整个并行计算部分很有用。对于数据可用性部分,还有一个名为的包,如果您需要的话,它可以使在进程之间移动数据变得更加容易。

正如@hckr在上面很好地解释的那样,在使用
@everywhere
宏之前,应该部署工人(使用addprocs(线程))

@everywhere可以在程序的不同部分以不同的方式调用和使用。 在我的例子中,我正在加载我想从一个模块并行运行的函数

要从主界面并行使用此函数,我正在使用
@everywhere include(“myModule.jl”)

以下是MyModule的代码:

module MyModule    
using Distributed
using Printf: @printf
using Base

"""Count sequences in the input FASTA"""
function count_proteins(fpath::String)::Int
    cnt::Int = 0
    #@show fpath
    if !isfile(fpath)
        write(Base.stderr, "\nInput FASTA not found!")
    else
        open(fpath, "r") do ifd
            for ln in eachline(ifd)
                if ln[1] == '>'
                    #println(ln)
                    cnt += 1
                end
            end
        end
    end
    # return the count
    @printf("%s\t%d\n", fpath, cnt)
    cnt
end

"""Count sequences in parallel."""
function parallel_count_proteins(fPaths::Array{String, 1})

    # spawn the jobs
    for (i, fastaPath) in enumerate(fPaths)
        r = @spawn count_proteins(fastaPath)
        # @show r
        s = fetch(r)
    end    
end
下面是使用
MyModule
中的函数
parallel\u count\u proteins
main.jl

### main.jl ###
using Base
using Distributed
using Printf: @printf

# add path to the modules directory
push!(LOAD_PATH, dirname(@__FILE__)) # MyModule is in the same directory as main.jl

#### MAIN START ####
# deploy the workers
addprocs(4)
# load modules with multi-core functions
@everywhere include(joinpath(dirname(@__FILE__), "MyModule.jl"))

# paths with 4 input files (all in same dir as main.jl)
flist = ["tv1", "tv2", "tv3", "tv4"]

# count proteins
MyModule.parallel_count_proteins(flist)

你好,hckr,非常感谢您的帮助。不幸的是,我一直有同样的错误。。。我按以下顺序尝试了以下操作:1)@everywhere funtion蛋白质计数2)将主代码放入模块中,并从调用并行蛋白质的main.jl脚本调用它。上述试验没有解决问题。在发布此问题之前,我已经阅读了手册…但我仍然不清楚如何使其工作。为了澄清,我正在尝试做的是并行处理文件列表。你能发布一个你做类似事情的工作实例吗?例如,应该并行运行的函数位于模块MyModule中,该函数在main.jl文件中调用。那对我真的很有帮助。关于数据传递,我只想获取并行执行的函数返回的变量/对象(基本上是remotecall_fetch将返回的)。非常感谢您的帮助。我也尝试过使用pmap,并得到了一个错误,我认为这与同一问题有关。错误:LoadError:UndevarError:count\u不是defined@SalvatoreCosentino确实在创建工作进程后执行了
@everywhere count\u proteins…definition…end
addprocs(threads)
应在
@everywhere
定义之前调用。因为
@everywhere
在可用进程上执行代码。您的代码在调用
parallel\u count\u proteins
后执行此操作。你不应该把它放在平行计数蛋白质里面。只需在
Main
中运行它一次,然后再执行其他操作,或者完全忽略它,然后使用
julia-p2运行julia,使用2个工作进程启动julia。我刚刚编辑了我的答案,这次我们不要使用模块或其他东西
addprocs
位于代码段的开头,如果启动
julia-p2
可以省略该行。