0

I have to traverse a 2D-array and perform some operations on them, depending on the results of an if-statement. I have made a small example of the loop here:

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

I want to parallelize this for-loop. I have read the MathWorks-page on parfor, and the way I would parallelize it is just by making the outer-loop into a parfor.

Is this the best speed-up I can get, or should I structure my loop differently?


Here is a more detailed version of my loop:

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
2
  • Changing directly for loops into par-for loops is good when, you want to repeat the same process again and again (for instance when gathering statistical information). Otherwise you need to manage the resource assignment to each different worker. Commented Aug 24, 2015 at 13:16
  • a minimal reproducible example of your "detailed version" with inputs and outputs would help others help you Commented Aug 24, 2015 at 14:59

2 Answers 2

3

I think you can reduce the code (replace the two for-loops and the if statement) into something like this:

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

first you calculate the condition abs(A,B) and then apply the comparison to all the elements of the matrix.

Sign up to request clarification or add additional context in comments.

2 Comments

thanks, but my example in my OP was very artificial, I'm not actually taking the square root of anything, it was just a simple example to show the overall structure...
I posted a more detailed version of my loop, it is possible to vectorize/optimize it?
2

If you want a speed-up you may be interested in the vectorized form:

[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;

You can place that piece of code instead of the for loop

1 Comment

I posted a more detailed version of my loop, it is possible to vectorize/optimize it?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.