我正试图在MATLAB中的spmd
块中的分布式数组的共分配部分内部循环R2020a:
input = rand([bignum,1],'distributed');
output = zeros([bignum,1],'distributed');
spmd
for idx=1:numel(input)
output(idx) = myFunction(input(idx));
end
end
上面的代码给了我以下错误:
Error detected on workers <all the work numbers>
Caused by:
Error using codistributed/cast>iClass
unsupported data type for conversion: 'codistributed'
如果不是在idx=1:numel(input)
上循环,而是在idx=drange(1:numel(input))
上循环,我的代码可以按预期工作,但这是不希望的,因为drange
假设数组使用默认的分发方案,而事实并非如此。我宁愿有一个片段,即使我用较小的、不一定大小相等的共分配块构建分布式数组,它也能工作。此外,我不知道如何使用drange
索引到一个一维以上的数组中
我的理解是,在spmd
块中,对分布式数组的任何访问实际上都对应于对所述数组的一个共结构片段的访问。因此,例如,如果input
是一个100元素的分布式数组,在每个工作器内被拆分为10个协同分配数组,那么idx=1:numel(input)
应该等价于idx=1:10
(因为input
的工作器本地协同分配片段有10个元素长(,并且output(idx)=myFunction(input(idx))
应该只访问input
和output
的工作器局部协同分配数组成员。
那么,为什么我写的代码示例不起作用呢?
您确定这里的问题不在myFunction
内部吗?以下代码对我来说是正确的:
input = rand(10, 1, 'distributed');
output = zeros(10, 1, 'distributed');
spmd
for idx = 1:numel(input)
% if 'input' and 'output' have the same distribution scheme,
% then no communication is required
output(idx) = input(idx);
end
end
assert(isequal(gather(input), gather(output)))
然而,它的效率并不是很高。当访问codistributed
时,期望您这样做";统称为"-即,所有工作者在同一时间用相同的输入自变量执行相同的方法。这就是这里发生的情况,但在所示的例子中,只有一个worker具有input
或output
的每个元素。换句话说,所有工作者都在执行循环的每次迭代,但不执行任何计算,除非他们是具有值的工作者。
你甚至可以用这种方式进行随机访问索引,但效率较低,因为每个索引调用都是一个通信:
output2 = zeros(10, 1, 'distributed');
spmd
n = numel(input);
for idx = 1:n
% the following line requires an element of 'input'
% to be sent to the worker which has the corresponding
% element of 'output'.
output2(n - idx + 1) = input(idx);
end
end
assert(isequal(gather(input), flip(gather(output2))))
我强烈建议,如果您想在spmd
中使用codistributed
,请从codistributed
数组中提取本地部分,在本地使用该部分(如果需要,可以使用通信(,然后重新组合。