以下代码有效,但如果我将for
更改为parfor
,则会出错:
Index exceeds matrix dimensions
这是我的代码
a=zeros(3,1);
for t=1:2
ind=randsample(3,2)
a=pf(a,ind)
end
function a=pf(a,ind)
a(ind)=a(ind)+2;
end
如何在没有错误的情况下使用此代码?
答案 0 :(得分:2)
您看到错误是因为您在代码中滥用了parfor
。您还没有充分阅读相关文档,而且您似乎相信parfor
是神奇的尘埃,无论计算如何,您的计算速度都会更快。好吧,我有坏消息。
让我们仔细看看你的例子:
a = zeros(3,1);
% usual for
disp('before for')
for t=1:2
ind = randsample(3,2);
a = pf(a,ind);
disp(a); % add printing line
end
% parfor
disp('before parfor')
parfor t=1:2
ind = randsample(3,2);
a = pf(a,ind);
disp(a); % add printing line
end
输出:
before for
2
2
0
2
4
2
before parfor
Error: The variable a is perhaps intended as a reduction variable, but is actually an uninitialized temporary.
See Parallel for Loops in MATLAB, "Temporary Variables Intended as Reduction Variables".
正如您所看到的,在后一种情况下parfor
内没有打印,因此它甚至无法运行。另请参阅有关变量类型的警告。变量a
被执行引擎误识别,因为你对它做的事情没有任何意义。
那又该做什么呢?您需要以与parfor
兼容的方式制定问题。唉,这将取决于你对你的矩阵究竟做了什么。对于递增随机元素的特定情况,我建议您在循环中单独收集增量,然后将它们相加:
a = zeros(3,1); % only needed for size; assumed that it exists already
numiters = 2;
increments = zeros([size(a), numiters]); % compatible with a proper 2d array too
parfor t=1:numiters
ind = randsample(3,2);
% create an auxiliary increment array so that we can use a full slice of 'increments'
new_contrib = zeros(size(a));
new_contrib(ind) = 2;
increments(:,t) = new_contrib;
disp(increments(:,t)); % add printing line
end
% collect increments along last axis
a = sum(increments,ndims(increments));
disp(a)
输出:
2
0
2
2
2
0
4
2
2
请注意缺少警告和存在有意义的答案。以这种方式重构循环transparently向MATLAB发出变量正在发生的信号,并且increments
循环的独立迭代正在填充parfor
。 这个是parfor
可以加快计算速度的方式,这是一种非常具体和受控制的方式,意味着对循环内部使用的物流进行限制。
答案 1 :(得分:1)
n = 2;
a=zeros(3,1);
ind=zeros(3,2,n);
for ii = 1:n
ind(:,:,ii) = randsample(3,2);
end
for t=1:n
a=pf(a,ind(:,:,t));
end
function a=pf(a,ind)
a(ind)=a(ind)+2;
end
上面的问题得到了randsample
,这可能就是问题所在。请注意randsample
不支持直接创建3D矩阵,所以我在循环中初始化它。