简体   繁体   English

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

[英]parfor error “Index exceeds matrix dimensions”

The following code works, but if I change for into parfor , it gave an error 以下代码有效,但如果我更改for parfor ,则会出错

Index exceeds matrix dimensions

This is my code 这是我的代码

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

How can I get this code working without the error? 如何在没有错误的情况下使用此代码?

You are seeing the error because you are misusing parfor in your code. 您看到错误是因为您在代码中滥用parfor You haven't read the relevant documentation enough, and you seem to believe that parfor is magic fairy dust that makes your computation faster, regardless of computation. 您还没有充分阅读相关文档,并且您似乎相信parfor是神奇的仙尘,无论计算如何,您的计算速度都会更快。 Well, I have bad news. 好吧,我有坏消息。

Let's take a closer look at your example: 让我们仔细看看你的例子:

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

The output: 输出:

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".

As you can see, in the latter case there are no prints inside the parfor , so it doesn't even get run. 正如您所看到的,在后一种情况下, parfor中没有打印,因此它甚至无法运行。 See also the warning about the type of variables. 另请参阅有关变量类型的警告。 The variable a is being misidentified by the execution engine because what you are doing to it doesn't make any sense. 变量a被执行引擎误识别,因为你对它做的事没有任何意义。

So what to do instead? 那又怎么办呢? You need to formulate your problem in a way that is compatible with parfor . 您需要以与parfor兼容的方式制定问题。 This will, alas, depend on what exactly you're doing to your matrix. 唉,这将取决于你对矩阵的确切做法。 For your specific case of incrementing random elements, I suggest that you gather the increments separately in the loop, and sum them up afterwards: 对于递增随机元素的特定情况,我建议您在循环中单独收集增量,然后将它们相加:

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)

Output: 输出:

     2
     0
     2

     2
     2
     0


     4
     2
     2

Note the lack of warnings and the presence of a meaningful answer. 请注意缺少警告和存在有意义的答案。 Refactoring the loop this way transparently signals MATLAB what the variables are doing, and that increments is being filled up by independent iterations of the parfor loop. 以这种方式重构循环透明地向MATLAB发送变量正在发生的信号,并且这些increments正由parfor循环的独立迭代填充。 This is the way in which parfor can "speed up calculations", a very specific and controlled way that implies restrictions on the logistics used inside the loop. 就是parfor可以“加速计算”的方式, 是一种非常具体和受控的方式,意味着对循环内部使用的物流的限制。

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

The above gets the randsample out of the loop, which is probably the issue here. 以上是randsample的循环,这可能是这里的问题。 Note that randsample does not support direct 3D matrix creation, so I initialised that in a loop. 请注意, randsample不支持直接创建3D矩阵,因此我在循环中初始化了它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM