我在Matlab中有以下代码(当然是简化的,但这显示了问题的根源),之前使用过for
;我想将其更改为使用parfor
代替:
isForeground = ones(1, size(In, 1));
% this used to be a simple for
parfor i=1:X
data = output_of_some_expensive_function();
% do some other stuff with data here
% the part below is the problem; isForeground basically keeps track of all the places where data was never a zero
isForeground(data == 0) = 0;
end
Matlab抱怨说Valid indices for 'isForeground' are restricted in PARFOR loops
。有办法解决这个问题吗?我想过只保存所有data
输出,然后运行一个单独的传统for
循环,我将执行isForeground
部分,但问题是X
非常大而且保存所有数据输出将是非常耗费内存的。
还有另一种方法吗?
答案 0 :(得分:1)
结果中1的密度是多少?如果它们是稀疏的(即大部分为0),find()
可以将逻辑掩码缩小到数字索引列表。如果您需要进一步压缩,根据X的大小,您可以将存储的掩码转换为uint32
或uint16
,这将占用double
空间的1/2或1/4
然后将结果存储在仍然由循环索引切片的临时变量中,然后将它们组合在parfor
循环之外,就像你说的那样。
masks = cell(1, X);
parfor i=1:X
data = output_of_some_expensive_function();
% do some other stuff with data here
% stash the loop results in a non-combining manner
masks{i} = uint32(find(data == 0));
end
% Combine in regular for loop
for i=1:X
isForeground(double(masks{i})) = 0;
end
如果这还不够,也许您可以将每个结果掩码写入常见的驱动器空间或其他持久对象存储上的.mat文件中的磁盘。如果parfor
的工作人员在本地计算机上,则任何驱动器都可以正常工作,并且应该很快,因为您可能只是通过操作系统的磁盘缓存。
您还可以尝试将输出掩码转换为可压缩格式。例如。在其上运行diff()
并将结果压缩到byte[]
“blob”,然后在常规for
循环中应用掩码之前执行反向右移。根据面具的结构,这可能会节省更多空间。
注意:逻辑占用的存储空间比您想象的要多;即使每个元素只有一位有意义的信息,它需要一整个字节的内存,因为这是最小的可寻址内存单元。
答案 1 :(得分:-1)
此代码现在使用struct从parfor传递数据:
In = eye(3); % some input
X = size(In, 1);
isForeground = ones(1, X);
isForeground_struct = repmat(struct('data', ones(1, X)), [1, X]);
% is used to be a simple for
parfor i=1:X
data = ones(1, X);
data(randi(X)) = 0; % a random operator just to make an example for data
isForeground_struct(i).data = data;
end
isForeground = prod(cat(1, isForeground_struct.data)); % assuming you want AND combination