parfor错误“索引超出矩阵维度”

时间:2017-06-25 18:42:24

标签: matlab parfor

以下代码有效,但如果我将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

如何在没有错误的情况下使用此代码?

2 个答案:

答案 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矩阵,所以我在循环中初始化它。