[多线程] 关于嵌套使用 Threads.@threads

目前 LTS=1.6.4, master=1.8 的建议是:
可以用,不会报错。但内层的多线程会变成单线程,对性能没有帮助。

实际上只有最外层的会并行。

后续的版本可能有新的变化。


参考资料

jeff 的评论

From triage: disable parallelism when nested.

—— jeff#35646

注:triage 指定期的多人电话会议讨论,可以视作开发团队的决定。
What does the “triage” tag on Github mean? - Community - JuliaLang

master (1.8) 的代码

这段代码的意思是,当嵌套多线程宏时,内部的嵌套全部以单线程运行(多了个 onethread=true 的参数)。
threadid() == 1 标志着是最外层的 @threads 宏调用。因为仅有用户所在的线程 id 才为 1.

英文社区的讨论


扩展阅读

Jeff 2021 - Multi-Threading Using Julia for Enterprises - YouTube

This webinar will demonstrate how to take advantage of the ever-increasing core counts in modern CPUs using Julia. The language provides simple loop-based and nested task-based parallelism, making multi-threaded programming easier than ever. Once you try it, you’re sure to want more cores, and for that we will demonstrate JuliaHub, where you can start up to 32 vCPUs in a single node with just a couple clicks.

3 个赞

那篇英文社区的链接帖起始于我以前测试时遇到的性能问题。我对多线程的了解起源于OpenMP,而在OpenMP中经过多年发展像这种线程嵌套相对非常成熟了,切换到Julia中就会发现很多相对的性能问题,比如overhead,thread migration,以及远不如OpenMP灵活的variable scope declaration for avoiding race conditions.

Julia目前的1.7版本一个重大改变是多线程任务可以发生迁移了,而不用绑定在一开始分配的core上面。我还没有很好的测试例子能说明这能带来多大的性能提升。但是根据我的理解,目前的一大瓶颈在于garbage collector并不是多线程的,而是所有线程共享的,所以如果程序的多线程部分有较多的内存开销,仍然会有明显的性能问题。

关于thread launching overhead,目前开发中号称最少代价的包是由LoopVectorization.jl的作者开发的 JuliaSIMD/Polyester.jl: The cheapest threads you can find! (github.com)。但是这个包提供的线程方式是不如Threads.@threads通用的。

目前的一大瓶颈在于garbage collector并不是多线程的,而是所有线程共享的

但是在线程模型里面,内存就是由线程共享的呀,所以在一个线程上 GC 其实就会影响到其他线程呀… 如果想要内存隔离的话,那应该就需要使用多进程的模式了…

你这么一说的确,像OpenMP支持的Fortran, C/C++,都没有使用GC。所以我不知道GC是否天然地和线程犯冲。

说到 GC 那就得学学 JVM 了。

不过 julia 提倡计算密集时,预分配好内存。
所以 GC 相关的改进,没人推进就一直会这样。