如何嵌套多个parfor循环

 zgshenxz_474 发布于 2023-02-13 18:10

parfor是在几个"工人"之间分配密集计算的独立迭代的便捷方式.一个有意义的限制是parfor-loops不能嵌套,并且总是,这就是那里和那里类似问题的答案.

为什么跨越循环边界的并行化是如此理想

考虑以下代码,其中迭代在允许4个工作者的机器上占用大量可变时间.两个循环迭代超过6个值,显然难以在4个中共享.

for row = 1:6
    parfor col = 1:6
        somefun(row, col);
    end
end

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

组合循环所需的模式

理想情况下,somefun运行所有对rowcol,并且工人应该忙,不管哪个迭代正在变化.解决方案应该是这样的

parfor p = allpairs(1:6, 1:6)
    somefun(p(1), p(2));
end

不幸的是,即使我知道它的内置函数创建一个矩阵的所有组合rowcol,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我正在寻找的东西?有人提出了一个方便的惯用模式吗?

2 个回答
  • 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.

    2023-02-13 18:13 回答
  • 你应该可以这样做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);
    

    2023-02-13 18:13 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有