1

I want to optimize some examples by omitting an unnecessary loop but I don't know how. Here are the examples:

%Subtract 7 from all elements on the matrix diagonal
    A=rand(100,100)*10;
    for i=1:100
        A(i,i)=A(i,i)-7;
    end
---
%Count the number of elements of matrix A which are bigger than the adequate elements of matrix B
    A=rand(100,100)*10;
    B=rand(100,100)*10;
    a_bigger=0;
    for i=1:100
       for j=1:100
          if A(i,j)>B(i,j)
             a_bigger=a_bigger+1;
          end
       end
    end
---
    %Create vector with sums of 100 natural numbers (so-called cumulative ``sum):
B=[1, 1+2, 1+2+3... 1+2+3+...+n]
    A=1:100;
    B=zeros(1,100);
    for i=1:100
       for j=1:i
          B(i)=B(i)+A(j);
       end
    end

I tried to solve the first one with

n=100;
A=rand(n,n)*10;
x=ones(1,n)*7;
diag(x);
A=A-x;

However, it was worse than as it is. It required more time to run the code. Why is this? Is there a faster way to implement this?

I was looking at the vectorization page and I tried to use the find function to solve the second one. But when i wrote the code

A=rand(100,100)*10;
B=rand(100,100)*10;
a_bigger=0;
find(A);
find(B);
if find(A)>find(B)
    a_bigger = a_bigger + 1;
end
a_bigger

it gives me 0 as a result. What am I doing wrong?

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
overflush
  • 25
  • 1
  • 7
  • @CrisLuengo i tried to solve the problems but i couldnt. I tried n=100; A=rand(n,n)*10; x=ones(1,n)*7; diag(x); A=A-x; this for the first one but it was even worse than as it is. It is also a homework but a small part of homework. I thought that if i can understand them i can do the rest – overflush Jan 13 '18 at 15:21
  • 1
    What is wrong with that answer? Produces the same result and has no loops. I think your question is quite different from what you posted. You do know how to do it, but wonder why do it? Read about vectorization here: https://www.mathworks.com/help/matlab/matlab_prog/vectorization.html – Cris Luengo Jan 13 '18 at 15:40
  • @CrisLuengo it also has to be optimized as i pointed out in the title. So my code gives the same result without loop but it is not effective. I spent my all day in vectorization page but there are only simple examples so i couldnt solve the problems. That's why i wrote my samples here – overflush Jan 13 '18 at 15:45
  • 1
    And what I's saying is that you need to rephrase your question to not sound like "do my homework for me" but reads more like "I want to understand why I'm being asked to turn this into a vectorized form if that is not more efficient". Show your timing tests. Show you've been working on the problem. It'll be a more interesting question to answer. Go ahead and edit your question, I'll change my downvote to an upvote. – Cris Luengo Jan 13 '18 at 15:52
  • @CrisLuengo is it okay now? – overflush Jan 13 '18 at 16:13
  • Yes, now it's a much more interesting question. I took the liberty to make the questions explicit. – Cris Luengo Jan 13 '18 at 16:19

1 Answers1

0

Regarding your first question: MATLAB uses to be a lot slower in loops than it is nowadays. However, if you increase n to 1e5 or 1e6, you might see the vectorized code is more efficient.

A relevant recent post: https://stackoverflow.com/a/48220174/7328782

Instead of

x=ones(1,n)*7;

you could do

x=repmat(7,1,n);

to prevent n unnecessary multiplications.

Regarding your second question: that is not how find or if work. But you don't need to use either:

I = A>B;

returns a logical matrix that is true (1) where A is larger. You want to count the number of ones in there, you can do that in two ways:

a_bigger = sum(I(:));

or

a_bigger = sum(sum(I));

The former is faster. It reshapes the matrix as a column vector, then adds up all the elements. The second form adds up all the elements per column, then adds up all the sums.

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120