parfor
是一种在多个“工作人员”之间分配密集计算的独立迭代的便捷方式。一个有意义的限制是 parfor
-loops 不能嵌套,并且总是,这是类似问题的答案,如 there和 there .
为什么跨循环边界的并行化如此可取
考虑以下代码段,其中迭代在允许 4 个工作人员的机器上花费的时间变化很大。两个循环都迭代了 6 个值,显然很难在 4 个值之间共享。
for row = 1:6
parfor col = 1:6
somefun(row, col);
end
end
为 parfor
选择内部循环似乎是个好主意,因为对 somefun
的单独调用比外部循环的迭代更具可变性。但是,如果每次调用 somefun
的运行时间都非常相似怎么办?如果运行时有趋势并且我们有三个嵌套循环怎么办?这些问题经常出现,人们会去 extremes .
组合循环所需的模式
理想情况下,somefun
会针对所有的row
和col
对运行,工作人员应该忙碌起来,而不管哪个 iterand 正在发生变化。解决方案应该看起来像
parfor p = allpairs(1:6, 1:6)
somefun(p(1), p(2));
end
不幸的是,即使我知道哪个内置函数创建了一个包含 row
和 col
的所有组合的矩阵,MATLAB 也会报错 The range of a parfor 语句必须是一个行向量。 然而,for
不会提示并且很好地迭代列。一个简单的解决方法是创建该矩阵,然后使用 parfor
对其进行索引:
p = allpairs(1:6, 1:6);
parfor k = 1:size(pairs, 2)
row = p(k, 1);
col = p(k, 2);
somefun(row, col);
end
代替我正在寻找的 allpairs
的内置函数是什么?有没有人想出一个方便的惯用模式?
最佳答案
MrAzzman 已经指出了如何线性化嵌套循环。这是线性化 n 个嵌套循环的通用解决方案。
1) 假设您有一个像这样的简单嵌套循环结构:
%dummy function for demonstration purposes
f=@(a,b,c)([a,b,c]);
%three loops
X=cell(4,5,6);
for a=1:size(X,1);
for b=1:size(X,2);
for c=1:size(X,3);
X{a,b,c}=f(a,b,c);
end
end
end
2) 使用 for 循环的基本线性化:
%linearized conventional loop
X=cell(4,5,6);
iterations=size(X);
for ix=1:prod(iterations)
[a,b,c]=ind2sub(iterations,ix);
X{a,b,c}=f(a,b,c);
end
3) 使用 parfor 循环进行线性化。
%linearized parfor loop
X=cell(4,5,6);
iterations=size(X);
parfor ix=1:prod(iterations)
[a,b,c]=ind2sub(iterations,ix);
X{ix}=f(a,b,c);
end
4) 使用带有常规 for 循环的第二个版本,迭代的执行顺序发生了变化。如果有任何依赖于此,您必须颠倒索引的顺序。
%linearized conventional loop
X=cell(4,5,6);
iterations=fliplr(size(X));
for ix=1:prod(iterations)
[c,b,a]=ind2sub(iterations,ix);
X{a,b,c}=f(a,b,c);
end
在使用 parfor
循环时颠倒顺序是无关紧要的。您根本不能依赖执行顺序。如果您认为它有所作为,则可以不使用 parfor
。
关于matlab - 如何嵌套多个 parfor 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20295579/