parfor
是在几个"工人"之间分配密集计算的独立迭代的便捷方式.一个有意义的限制是parfor
-loops不能嵌套,并且总是,这就是那里和那里类似问题的答案.
为什么跨越循环边界的并行化是如此理想
考虑以下代码,其中迭代在允许4个工作者的机器上占用大量可变时间.两个循环迭代超过6个值,显然难以在4个中共享.
for row = 1:6 parfor col = 1:6 somefun(row, col); end end
选择内部循环似乎是一个好主意,parfor
因为单个调用somefun
比外部循环的迭代更可变.但是如果每个调用的运行时间somefun
非常相似怎么办?如果运行时有趋势并且我们有三个嵌套循环怎么办?这些问题经常出现,人们走向极端.
组合循环所需的模式
理想情况下,somefun
运行所有对row
和col
,并且工人应该忙,不管哪个迭代正在变化.解决方案应该是这样的
parfor p = allpairs(1:6, 1:6) somefun(p(1), p(2)); end
不幸的是,即使我知道它的内置函数创建一个矩阵的所有组合row
和col
,MATLAB将与错误抱怨一个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已经指出如何线性化嵌套循环.这是线性化嵌套循环的一般解决方案.
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
.
你应该可以这样做bsxfun
.我相信这bsxfun
将尽可能并行化代码(有关更多信息,请参见此处),在这种情况下,您应该能够执行以下操作:
bsxfun(@somefun,(1:6)',1:6);
你可能想要对此进行基准测试.
或者,您可以执行以下操作:
function parfor_allpairs(fun, num_rows, num_cols) parfor i=1:(num_rows*num_cols) fun(mod(i-1,num_rows)+1,floor(i/num_cols)+1); end
然后打电话:
parfor_allpairs(@somefun,6,6);