【问题标题】:parallelizing for-loop containing if-statement并行化包含 if 语句的 for 循环
【发布时间】:2015-08-24 13:10:36
【问题描述】:

我必须遍历一个二维数组并对它们执行一些操作,这取决于if-statement 的结果。我在这里做了一个循环的小例子:

N=128;    

A = rand(N,N);
B = rand(N,N);

sqr = @(x) x.^2;

for xi=1:N
    for yi=1:N
        a = A(xi,yi);
        b = B(xi,yi);

        if( abs(a-b)<1 )
            result=2.0;
        else
            result = sqr(a-b);
        end

        res_matrix(xi,yi) = result;
    end
end

我想并行化这个for-loop。我已经阅读了 parfor 上的 MathWorks 页面,我将其并行化的方法是将外循环变成 parfor

这是我能获得的最佳加速,还是我应该以不同的方式构建循环?


这是我的循环的更详细版本:

for xi= 1:N
    for yi= 1:N

        a  = A(:,xi,yi);   %a is a vector
        b  = B(:,xi,yi);   %b is a vector
        D  = a-b;

        if( max(D./a)<1e-3 )
            test_var=2.0;  
        else

            F_min = F(a, b, 0); %F is some function, such as a Newton-Raphson solver etc...
            F_max = F(a, b, 1); %F is some function, such as a Newton-Raphson solver etc...          

            if( F_min*F_max>0.0 )
                test_var=2.0;
            else
                test_var = F(a, b, 2);
            end
        end

        var(1, xi,yi) = test_var;
    end
end

【问题讨论】:

  • 直接将for 循环更改为par-for 循环在您想要一次又一次地重复相同的过程(例如在收集统计信息时)时很好。否则,您需要管理对每个不同工作人员的资源分配。
  • 您的“详细版本”的minimal reproducible example 带有输入和输出将帮助其他人帮助您

标签: matlab parallel-processing parfor


【解决方案1】:

我认为您可以将代码(将两个 for 循环和 if 语句替换)简化为如下所示:

C = abs(A-B);
D = ones(N);
R = sqrt(C);
idxC = bsxfun(@gt,C,D);
R(idxC) = 2.0;

首先计算条件abs(A,B),然后将比较应用到矩阵的所有元素。

【讨论】:

  • 谢谢,但我在我的 OP 中的示例非常人为,我实际上并没有取任何东西的平方根,这只是一个显示整体结构的简单示例......
  • 我发布了一个更详细的循环版本,是否可以对其进行矢量化/优化?
【解决方案2】:

如果您想加快速度,您可能对矢量化形式感兴趣:

[s1, s2, s3] = size(A);     % Size of A and B
C=A-B;                      % Difference between  A and B

%// Upper threshold condition
idx_under_threshold = squeeze(max(C,[],1)<threshold);

%// Functions to compute operations involving function F
fmin = @(idx1, idx2) F(A(:,idx1,idx2),B(:,idx1,idx2),0);
fmax = @(idx1, idx2) F(A(:,idx1,idx2),B(:,idx1,idx2),1);
fvalue = @(idx1, idx2) F(A(:,idx1,idx2),B(:,idx1,idx2),2);

%// Combined indices of A and B
idA = repmat((1:s2)',1,s3);    %'
idB = repmat(1:s3, s2, 1);

%// Computation of fmin, fmax and fvalue over all the elements
Fmin = cell2mat(arrayfun(fmin, idA, idB, 'UniformOutput', false));
Fmax = cell2mat(arrayfun(fmax, idA, idB, 'UniformOutput', false));
Fvalue = cell2mat(arrayfun(fvalue, idA, idB, 'UniformOutput', false));

%// Second condition: ( abs(a-b)<1 )
idx_2 = idx_under_threshold | (Fmin.*Fmax < 5);

%// Inizalization of the result to 'result = sqr(a-b)'
Var = Fvalue;

%// Handling cases where 'result = 2.0'
Var(idx_2) = 2;

您可以放置​​那段代码而不是 for 循环

【讨论】:

  • 我发布了一个更详细的循环版本,是否可以对其进行矢量化/优化?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-02
  • 2013-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多