Threads.@spawn和Threads.@threads有什么区别?

7

我是一名对Julia语言感兴趣的初学者。文档(https://docs.julialang.org/en/v1/base/multi-threading/)中提到Threads.@threads用于“for”循环,而threads.@spawn则将给定任务放置在任何可用线程上。我的理解是Threads.@threads具有固有的同步性,而threads.@spawn方法是异步的,需要更多的计划来实现(即使用fetch()方法)。

在我找到的在线代码中,我似乎看到这两个方法可以互换使用(从我的角度来看)。对于初学者来说,这两种方法的概念上有什么区别,我们应该在何时实现每种方法?此外,它们是否可以相互补充?

1个回答

6

请考虑:

function withthreads()
    arr = zeros(Int, 10)
    Threads.@threads for i in 1:10
       sleep(3 * rand())
       arr[i] = i
    end
    println("with @threads: $arr")
end


function withspawn()
    arr = zeros(Int, 10)
    for i in 1:10
        Threads.@spawn begin
            sleep(3 * rand())
            arr[i] = i
        end
    end
    println("with @spawn: $arr")
end

function withsync()
    arr = zeros(Int, 10)
    @sync begin
        for i in 1:10
           Threads.@spawn begin
               sleep(3 * rand())
               arr[i] = i
           end
        end
    end
    println("with @sync: $arr")
end

withthreads()
withspawn()
withsync()

输出:

with @threads: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
with @spawn: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
with @sync: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

@threads 管理着Julia分配的线程池,并为for循环中的每次迭代生成最多一个线程(如果迭代次数超过线程数,则可能使用同一线程多次进行迭代,按顺序在每个线程完成其指定迭代后),还同步了线程。当所有线程完成时,才退出for块。@spawn 仅会生成一个任务线程并立即返回到主任务,因此可以在所有任务被生成之前就退出该块,甚至在它们完成工作之前(所以数组arr中的零仍然保持不变)。


一个小提示@threads会生成和启动Julia时设置的线程数一样多的线程。特别地,它会将迭代任务均匀地分配给各个线程。 - Bogumił Kamiński
这就是第一个和第三个例子之间的区别,我同意。 - Bill
我刚才提到了你回答中的“@threads为for循环的每次迭代生成一个线程”的部分。如果我们同意的话,最好在那里澄清一下。谢谢! - Bogumił Kamiński
只是添加一个小注释。线程对迭代的分配是静态的(在任何计算之前通过分割迭代空间确定)。 - Bogumił Kamiński

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接