Julia中@distributed宏下的变量作用域规则相关疑问
问题核心原因
该现象由@distributed宏的变量捕获规则与@everywhere的执行逻辑共同导致,具体原理如下:
@everywhere x = myid()执行阶段确实会在所有进程(主进程+全部工作进程)上完成赋值:每个进程的全局变量x都等于自身的进程ID,主进程x=1、工作进程2的x=2、工作进程3的x=3,以此类推,这一步执行没有问题。- 问题出在
@distributed for的解析逻辑:该宏会默认将循环体内出现的、不属于循环参数的全局自由变量,从主进程拷贝序列化后发送给所有工作进程使用,而非直接读取工作进程本地的同名全局变量。你第二段代码中循环体内的x被该宏判定为需要从主进程捕获的自由变量,直接将主进程的x=1发送给了所有工作进程,因此所有工作进程调用k(x)时传入的都是1,最终求和结果为4*1=4。 - 第一段代码中直接在循环体内调用
myid()属于函数调用,@distributed宏不会捕获函数对象,函数会在工作进程本地执行,因此拿到的是各工作进程自身的ID,输出符合预期。
修复方案
如果需要让循环体读取工作进程本地的全局变量x,可以通过两种方式实现:
- 循环体内显式声明使用全局变量
sumk += @distributed (+) for i in 2:nprocs() global x k(x) end
添加global x声明后,@distributed宏不会再捕获主进程的x变量,会直接读取工作进程本地的全局变量,输出结果与第一段代码一致。
2. 显式指定从Main模块读取变量
Julia进程的顶层作用域归属Main模块,循环体内写为k(Main.x)也可以强制读取工作进程本地的全局变量,避免主进程变量被捕获。
内容的提问来源于stack exchange,提问作者singularity
相关产品推荐
相关产品推荐

