我找不到有关@async宏的详细文档。从有关并行性的文档中,我了解到Julia进程内仅使用了一个系统线程,并且借助于yieldto函数进行了显式的任务切换-如果我对此做错了,请纠正我。

对我而言,仅通过查看代码就很难理解这些任务切换的确切时间,并且知道何时发生这些任务至关重要。

据我了解,需要在代码中的某个地方(或代码所调用的某些函数中)添加一个yieldto,以确保系统不会仅停留在一项任务上。

例如,当有一个read操作时,在读取内部可能有一个wait调用,而在wait的实现中可能有一个yieldto调用。我以为如果没有yieldto调用,代码将停留在一项任务中。但是,运行以下示例似乎证明了该假设是错误的。

@async begin # Task A
    while true
        println("A")
    end
end

while true # Task B
  println("B")
end

此代码产生以下输出
BA
BA
BA
...

对我来说,目前尚不清楚任务切换发生在上面代码中的@async宏创建的任务内。

我该如何看待某些代码,以了解发生任务切换的地方?

最佳答案

任务切换发生在对println("A")的调用内,该调用有时称为write(STDOUT, "A".data)。因为isa(STDOUT, Base.AsyncStream)并且没有更专业的方法,所以可以解决:

write{T}(s::AsyncStream,a::Array{T}) at stream.jl:782

如果您查看此方法,您会注意到它在当前任务stream_wait(ct)上调用ct,而该任务又调用wait()

(还要注意,println不是原子的,因为在编写参数和换行符之间存在潜在的wait。)

您当然可以通过查看所有涉及的代码来确定何时发生类似的事情。但是我不明白为什么您需要确切地知道这一点,因为在使用并行性时,您不应该依赖进程,无论如何也不要切换上下文。如果您依赖特定的执行顺序,请进行显式同步。

(您已经在问题中注意到了这一点,但是让我在这里重申一下:根据经验,使用绿色线程时,在执行IO时可以预期潜在的上下文切换,因为阻塞IO是为什么绿色的教科书示例。线程首先很有用。)

10-06 05:21
查看更多