为什么我不能parfor
在这段代码中使用?
parfor i=1:r
for j=1:N/r
xr(j + (N/r) * (i-1)) = x(i + r * (j-1));
end
end
Run Code Online (Sandbox Code Playgroud)
这是错误:
错误:parfor中的变量xr无法分类.请参见MATLAB中的并行循环,"概述".
abc*_*bcd 12
这里的问题是切片阵列的索引不正确.parfor
循环以异步方式运行,这意味着每次迭代的执行顺序是随机的.从文档:
MATLAB工作人员不按特定顺序评估迭代,并且彼此独立.因为每次迭代都是独立的,所以不能保证迭代以任何方式同步,也不需要这样做.
您可以通过在命令行中键入以下内容来轻松验证上述语句:
parfor i=1:100
i
end
Run Code Online (Sandbox Code Playgroud)
你会看到排序是任意的.因此,如果您在不同的工作者之间拆分并行作业,则一个工作人员无法确定是否已完成不同的迭代.因此,您的变量索引不能依赖于迭代器的过去/未来值.
让我用一个简单的例子来证明这一点.考虑斐波那契系列1,1,2,3,5,8,...
.您可以轻松地(在一个天真的for
循环中)生成该系列的前10个术语:
f=zeros(1,10);
f(1:2)=1;
for i=3:10
f(i)=f(i-1)+f(i-2);
end
Run Code Online (Sandbox Code Playgroud)
现在让我们用parfor
循环来做同样的事情.
f=zeros(1,10);
f(1:2)=1;
parfor i=3:10
f(i)=f(i-1)+f(i-2);
end
Run Code Online (Sandbox Code Playgroud)
??? 错误:parfor中的变量f无法分类.请参见MATLAB中的并行循环,"概述"
但为什么会出错呢?
我已经证明迭代是以任意顺序执行的.所以我们假设一个worker获取循环索引i=7
和表达式f(i)=f(i-1)+f(i-2);
.现在应该执行表达式并将结果返回给主节点.迭代i=6
完成了吗?值是否f(6)
可靠存储?怎么样f(5)
?你看到我得到了什么吗?假设f(5)
并且f(6)
没有完成,那么你将错误地计算出Fibonnaci系列中的第7项为0!
由于MATLAB无法确定您的计算是否可以保证正确运行并且每次都重现相同的结果,因此明确禁止这种模糊分配.