在Julia中使用@sync @async的简单并行性

fej*_*kso 1 parallel-processing asynchronous async-await julia

我有一个问题,我希望并行执行多个彼此独立的语句.

我已经阅读了大量示例,表明这个玩具示例应该有效:

function f1(x,y,z)
  @sync @async begin
    # these two statements can be computed independently
    v1 = x+y; 
    v2 = y+z;
  end
  return v1*v2
end
Run Code Online (Sandbox Code Playgroud)

但是,似乎@sync部分没有等待结果完成,因为我收到以下错误:

y1 = f1(1,2,3);
ERROR: LoadError: UndefVarError: v1 not defined
Run Code Online (Sandbox Code Playgroud)

我成功地让它像这样工作:

function f2(x,y,z)
  v1 = @async x+y;
  v2 = @async y+z;
  return wait(v1)*wait(v2)
end
Run Code Online (Sandbox Code Playgroud)

但是,在我看到的许多示例中,如果使用@sync块,则wait语句似乎是不必要的.

我正在使用Julia 0.6.2.

任何帮助将受到高度赞赏.

Bog*_*ski 7

原因是@async在传递给它的表达式周围创建一个闭包.您可以通过运行来查看它:

julia> @macroexpand @async begin
       v1 = x+y;
       v2 = y+z;
       end
:((Base.async_run_thunk)((()->begin  # task.jl, line 335:
                begin  # REPL[22], line 2:
                    v1 = x + y # REPL[22], line 3:
                    v2 = y + z
                end
            end)))
Run Code Online (Sandbox Code Playgroud)

这有寓意v1v2,除非它们存在于它的函数范围内的变量不会关闭外部可见.

要修复此问题,您可以local v1, v2在以下位置添加语句f1:

julia> function f1(x,y,z)
           local v1, v2
           @sync @async begin
               v1 = x+y;
               v2 = y+z;
           end
           return v1*v2
       end
f1 (generic function with 1 method)

julia> f1(1,2,3)
15
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,所有工作都按预期工作.

此外,如果您的封闭范围不是函数而是全局范围,则必须使用global关键字来获得所需内容:

julia> x,y,z = 1,2,3
(1, 2, 3)

julia> @sync @async begin
          global v1 = x+y;
          global v2 = y+z;
       end
Task (done) @0x0000000018be30f0

julia> v1*v2
15
Run Code Online (Sandbox Code Playgroud)