错误 "Index exceeds matrix dimensions"
parfor error "Index exceeds matrix dimensions"
下面的代码可以工作,但是如果我把 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
我怎样才能让这段代码正常工作而不出错?
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 矩阵,因此我在循环中对其进行了初始化。
您看到错误是因为您在代码中误用了 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
可以"speed up calculations"的方式,一种非常具体和可控的方式,意味着对循环内使用的物流进行限制。
下面的代码可以工作,但是如果我把 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
我怎样才能让这段代码正常工作而不出错?
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 矩阵,因此我在循环中对其进行了初始化。
您看到错误是因为您在代码中误用了 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
可以"speed up calculations"的方式,一种非常具体和可控的方式,意味着对循环内使用的物流进行限制。