Julia 1.x使用pmap触发BoundsError的问题求助
我来帮你拆解这个问题——你遇到的BoundsError本质上是多worker环境下,SharedArray没有在各个进程中正确关联到共享内存段,导致worker端的数组变成了空的0×0×0×0数组,自然访问索引时会报错。
问题根源分析
- 不必要的deepcopy破坏了共享性:你在
initialisearray!里创建SharedArray后,用deepcopy(zerofield)赋值给data["field"]。deepcopy会生成一个全新的普通数组,完全丢失了SharedArray的共享内存特性。 - 跨进程传递的序列化问题:当你把包含这个“伪共享数组”的
data字典通过pmap传递给worker时,Julia的序列化机制无法将主进程的SharedArray正确映射到worker的共享内存,反而在worker端生成了一个空数组,这就是为什么访问data["field"][a,b,c,d]会触发索引越界。
SharedArray的核心是让多个进程共享同一块内存,但前提是每个worker进程都持有这个共享内存的正确句柄——你的写法并没有做到这一点。
修正后的代码示例
主文件 pmapdemo.jl
using Distributed addprocs(length(Sys.cpu_info())) # 现在可以正常启用多worker了 @everywhere include(joinpath(@__DIR__, "pmapdemo2.jl")) function main() # 获取源数据 source = Dict{String, Any}("t"=>zeros(5), "x"=>zeros(5,6), "y"=>zeros(5,3), "z"=>zeros(5,3)) # 定义迭代点集 iterset = Dict{String, Any}("t"=>source["t"], "x"=>source["x"], "y"=>fill(2, size(source["t"])[1], 1), "z"=>fill(2, size(source["t"])[1], 1)) data = Dict{String, Any}() # 初始化待计算数组 MyMod.initialisearray!(data, iterset) # 计算每个数组点 MyMod.calcarray!(data["field"], iterset, source) @show data end main()
功能文件 pmapdemo2.jl
module MyMod using Distributed @everywhere using SharedArrays # 初始化数据数组:创建跨所有worker的SharedArray function initialisearray!(data, fieldset) # 指定workers参数,让所有worker都能访问这个共享内存 zerofield = SharedArray{Float64, 4}( size(fieldset["t"])[1], size(fieldset["x"])[2], size(fieldset["y"])[2], size(fieldset["z"])[2]; workers=workers() ) data["field"] = zerofield # 直接赋值,不要deepcopy end # 根据源数据计算数组元素值:直接接收SharedArray而非整个Dict function calcpoint!((field, source, a, b, c, d)) field[a,b,c,d] = rand() end # 设置数组值:传递SharedArray给pmap,避免传递大字典 function calcarray!(field, iterset, source) for a in eachindex(iterset["t"]) # [此处保留你的额外功能f(a)] b_range = eachindex(iterset["x"][a,:]) c_range = eachindex(iterset["y"][a,:]) d_range = eachindex(iterset["z"][a,:]) # 构造迭代参数:传递共享数组、源数据和索引 iter = Iterators.product( Iterators.repeated(field, 1), Iterators.repeated(source, 1), Iterators.repeated(a, 1), b_range, c_range, d_range ) pmap(calcpoint!, iter) end end end
关键修正点说明
- 创建SharedArray时指定
workers=workers():确保所有worker进程都能关联到同一块共享内存,而不是只有主进程能访问。 - 移除
deepcopy:直接将SharedArray赋值给data["field"],保留其共享特性。 - pmap传递SharedArray而非整个Dict:减少不必要的序列化开销,同时确保worker端拿到的是有效的共享数组句柄。
- 调整
calcpoint!的参数:直接接收SharedArray,避免通过Dict间接访问,逻辑更清晰且避免序列化问题。
这样修改后,多worker环境下就能正常访问SharedArray的元素,不会再触发BoundsError了。
内容的提问来源于stack exchange,提问作者DocDave
相关产品推荐
相关产品推荐

