首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何嵌套多个parfor循环

如何嵌套多个parfor循环
EN

Stack Overflow用户
提问于 2013-11-30 01:43:27
回答 3查看 7.7K关注 0票数 8

parfor是在多个“工作人员”之间分发密集计算的独立迭代的一种方便方法。一个有意义的限制是,parfor-loops不能嵌套,这是对那里那里等类似问题的回答。

为什么跨循环边界的并行化是如此可取的

考虑下面的代码,迭代在一台允许4名工作人员的机器上花费的时间变化很大。这两个循环迭代超过6个值,显然很难在4个之间共享。

代码语言:javascript
复制
for row = 1:6
    parfor col = 1:6
        somefun(row, col);
    end
end

选择parfor的内环似乎是个好主意,因为对somefun的单个调用比外部循环的迭代更易变。但是,如果每次调用somefun的运行时间非常相似,怎么办?如果有运行时的趋势,我们有三个嵌套循环呢?这些问题经常出现,人们会去极端

组合循环所需的模式

理想情况下,somefun是针对所有对rowcol运行的,并且工作人员应该不需要分别忙于迭代和正在变化的迭代。解决方案应该看起来像

代码语言:javascript
复制
parfor p = allpairs(1:6, 1:6)
    somefun(p(1), p(2));
end

不幸的是,即使我知道哪个内置函数用rowcol的所有组合创建了一个矩阵,MATLAB也会错误地抱怨parfor语句的范围必须是行向量。然而,for不会抱怨并很好地迭代列。一个简单的解决方法是创建该矩阵,然后用parfor进行索引。

代码语言:javascript
复制
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的内置函数是什么?有人想出了一种方便的习语模式吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-11-30 02:05:56

MrAzzman已经指出了如何线性化嵌套循环。这里是n个嵌套循环线性化的一般解。

1)假设您有这样一个简单的嵌套循环结构:

代码语言:javascript
复制
%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循环的基本线性化:

代码语言:javascript
复制
%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循环进行线性化。

代码语言:javascript
复制
%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循环的第二个版本,改变迭代的执行顺序。如果有任何事情依赖于此,则必须反转索引的顺序。

代码语言:javascript
复制
%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

票数 10
EN

Stack Overflow用户

发布于 2013-11-30 01:49:10

您应该能够在bsxfun中做到这一点。我相信bsxfun会在可能的情况下并行化代码(更多信息请参见这里 ),在这种情况下,您应该能够执行以下操作:

代码语言:javascript
复制
bsxfun(@somefun,(1:6)',1:6);

不过,您可能希望对此进行基准测试。

或者,您可以执行如下操作:

代码语言:javascript
复制
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

然后打电话给:

代码语言:javascript
复制
parfor_allpairs(@somefun,6,6);
票数 5
EN

Stack Overflow用户

发布于 2013-12-01 23:00:12

基于@DanielR和@MrAzzaman的回答,我发布了两个函数,iterliniterget代替prodind2sub,如果这些函数不是从一个函数开始,也允许在范围内迭代。模式的一个示例变成

代码语言:javascript
复制
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列,而不会有任何工人闲置,而更多的井正在等待处理。为了希望这对某人有所帮助,我把iterliniterget存入了MATLAB文件交换

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20295579

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档