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的内置函数是什么?有人想出了一种方便的习语模式吗?
发布于 2013-11-30 02:05:56
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
end2)使用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);
end4)使用常规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。
发布于 2013-11-30 01:49:10
您应该能够在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);发布于 2013-12-01 23:00:12
基于@DanielR和@MrAzzaman的回答,我发布了两个函数,iterlin和iterget代替prod和ind2sub,如果这些函数不是从一个函数开始,也允许在范围内迭代。模式的一个示例变成
rng = [1, 4; 2, 7; 3, 10];
parfor k = iterlin(rng)
[plate, row, col] = iterget(rng, k);
% time-consuming computations here %
end脚本将处理第2行至第7行和板上的第3至第10列,而不会有任何工人闲置,而更多的井正在等待处理。为了希望这对某人有所帮助,我把iterlin和iterget存入了MATLAB文件交换。
https://stackoverflow.com/questions/20295579
复制相似问题