Evaluate a vector using for loop matlab

by Amir Shahmoradi27 Oct 2017

This lecture explains the concept of for-loops and while-loops in MATLAB and different of types of it in MATLAB.

Lecture Videos

This video is created solely as reference for the attendants of ICP2017F course at UT Austin. If you did not attend this class, then you may not find this video useful.

Loops in MATLAB

Many programming algorithms require iteration, that is, the repetitive execution of a block of program statements. Similar to other programming languages, MATLAB also has built-in tools for iterative tasks in codes.

For-loop

The for-loop is among the most useful MATLAB constructs. The general syntax of for-loop is,

for variable = expression statements end 


Usually, expression is a vector of the form istart:stepSize:iend where fix((iend-istart)/stepSize+1) gives the number of iterations requested by the user, assuming iend>istart . The statements are the set of programming tasks that have to be repeated. For example consider a script named forLoop.m ,

for index = istart:stepSize:iend disp(index); end disp( [ 'number of iterations: ', num2str( fix((iend-istart)/stepSize+1) ) ] ); 
>> istart = -2; iend = 10; stepSize = 3; forLoop -2 1 4 7 10 number of iterations: 5 


You can also iterate in reverse order,

>> istart = 10; iend = -2; stepSize = -3; forLoop 10 7 4 1 -2 number of iterations: 5 

Breaking a for-loop immaturely

You can also use break inside a for-loop to get out of it, even before the for-loop finishes the full number of iterations. This is specially useful when you want to ensure if a condition has happened, and if so, then terminate the for-loop. For example,

for integer = 1:10 disp(integer) if (integer==5) break end end 
 1 2 3 4 5 

Exercise:
suppose you want to find the largest prime number that is smaller than a given input value by the user. Write a function that does so, using for-loop, break , and MATLAB’s intrinsic function isprime() .

Answer:

function integer = getPrime(upper) if (upper<1) disp('input value cannot be less than 1. Goodbye!') return end for integer = upper:-1:1 if isprime(integer) break end end end 

Continue statement within for-loops

To skip the rest of the instructions in a loop and begin the next iteration, you can use a continue statement. For example, the following code prints only integers that are primes,

for integer = 1:10 if ~isprime(integer) continue end disp(['prime detected! ',num2str(integer)]) end 
prime detected! 2 prime detected! 3 prime detected! 5 prime detected! 7 

Iterating over vectors, matrices, and cell using for-loops

Note that the index of for-loop must not necessarily be an integer. Basically you can use the for-loop index to iterate over anything that is iterable in MATLAB. For example, consider the following,

a = [1,0,2,3,7,-1]; for index = a disp(class(index)) disp(index) end 


The output of this script is,

double 1 double 0 double 2 double 3 double 7 double -1 

But, see what happens if we defined a as a matrix,

a = [1, 2, 3; 4, 5, 6; 7, 8, 9]; for index = a disp(class(index)) disp(index) end 
double 1 4 7 double 2 5 8 double 3 6 9 

What is happening here? The answer is that, MATLAB is a column-wise programming language, just like Fortran, and unlike C, C++ and all of their descendants. MATLAB, by default, iterates over elements of row vectors. Therefore, when you use a matrix as the iterator in for-loops, MATLAB considers an entire column as the index of for-loop. The same is also true for other multidimensional arrays in MATLAB, for example cell arrays,

a = ; for index = a disp(class(index)) disp(index) end 
cell [1] [4] [7] cell [2] [5] [8] cell [3] [6] [9] 

Therefore, if you want to iterate over elements of a multidimensional matrix or array, you have to first reshape them using MATLAB’s built-in reshape() function to convert them to vector format, then iterating over them. For example,

a = ; a = reshape(a,[1,9]); for index = a disp(class(index)) disp(index) end 
cell [1] cell [4] cell [7] cell [2] cell [5] cell [8] cell [3] cell [6] cell [9] 

Some general advice on for-loop index

While-loop

There is another iteration construct in MATLAB, called while-loop which has the following general syntax,

while expression statements end 


The statements within the while-loop are executed as long as expression is true. For example,

x = realmax(); while x>0 xmin = x x = log(x) end xmin 
xmin = 1.7977e+308 x = 709.7827 xmin = 709.7827 x = 6.5650 xmin = 6.5650 x = 1.8817 xmin = 1.8817 x = 0.6322 xmin = 0.6322 x = -0.4585 xmin = 0.6322 

Note that, break and continue can be used in while-loops in the same fashion as they are used in for-loops, described above. The condition is evaluated before the body is executed, so it is possible to get zero iterations. It’s often a good idea to limit the number of repetitions to avoid infinite loops (as could happen above if x is infinite). This can be done in a number of ways, but the most common is to use break . For example,

n = 0; while abs(x) > 1 x = x/2; n = n+1; if n > 50, break, end end 


A break immediately jumps execution to the first statement after the loop. It’s good practice to include some diagnostic output or other indication that an abnormal loop exit has occurred once the code reach the break statement.

Exercise:
Write function getFac(n) using while-loop, that calculates the factorial of an input number n . For example,

>> getFac(4) 4! = 24 

1 n = n-1; fac = fac*n; end disp([num2str(nOrg),'! = ' num2str(fac)]) end ```
-->

Some general advice on while-loops

Vectorization in MATLAB

Experienced programmers who are concerned with producing compact and fast code try to avoid for loops wherever possible in their MATLAB codes. There is a reason for this: for-loops and while-loops have significant overhead in interpreted languages such as MATLAB and Python.

There is of course, a remedy for this inefficiency. Since MATLAB is a matrix language, many of the matrix-level operations and functions are carried out internally using compiled C, Fortran, or assembly codes and are therefore executed at near-optimum efficiency. This is true of the arithmetic operators * , + , - , \ , / and of relational and logical operators. However, for loops may be executed relatively slowly—depending on what is inside the loop, MATLAB may or may not be able to optimize the loop. One of the most important tips for producing efficient M-files is to avoid for -loops in favor of vectorized constructs, that is, to convert for-loops into equivalent vector or matrix operations. Vectorization has important benefits beyond simply increasing speed of execution. It can lead to shorter and more readable MATLAB code. Furthermore, it expresses algorithms in terms of high-level constructs that are more appropriate for high-performance computing. For example, consider the process of summation of a random vector in MATLAB,

>> n = 5e7; x = randn(n,1); >> tic, s = 0; for i=1:n, s = s + x(i)^2; end, toc 
Elapsed time is 0.581945 seconds. 

Now doing the same thing, using array notation would yield,

>> tic, s = sum(x.^2); toc 
Elapsed time is 0.200450 seconds. 

Amazing! isn’t it? You get almost 3x speedup in your MATLAB code if you use vectorized computation instead of for-loops. Later on in this course, we will see that MATLAB has inherited these excellent vectorization techniques and syntax for matrix calculations from its high-performance ancestor, Fortran.

Exercise:
How do you vectorize the following code?

i = 0; for t = 0:.01:10 i = i + 1; y(i) = sin(t); end 

Answer:

t = 0:.01:10; y = sin(t); 

Vectorization of array operations

Vectorization of arrays can be done through array operators, which perform the same operation for all elements in the data set. These types of operations are useful for repetitive calculations. For example, suppose you collect the volume (V) of various cones by recording their diameter (D) and height (H). If you collect the information for just one cone, you can calculate the volume for that single cone as,

>> D = 0.2; >> H = 0.04; >> V = 1/12*pi*(D^2)*H V = 4.1888e-04 


Now, suppose we collect information on 10,000 cones. The vectors D and H each contain 10,000 elements, and you want to calculate 10,000 volumes. In most programming languages (except Fortran and R which have similar vectorization capabilities to MATLAB), you need to set up a loop similar to this MATLAB code (here instead of 10000, I am using 7):

>> D = [-0.2 1.0 1.5 3.0 -1.0 4.2 3.14]; >> H = [0.0400 1.0000 2.2500 9.0000 1.0000 17.6400 9.8596]; for n = 1:7 V(n) = 1/12*pi*(D(n)^2)*H(n); end >> V V = 0.0004 0.2618 1.3254 21.2058 0.2618 81.4640 25.4500 


With MATLAB, you can perform the calculation for each element of a vector with similar syntax as the scalar case,

>> V = 1/12*pi*(D.^2).*H; % Vectorized Calculation >> V V = 0.0004 0.2618 1.3254 21.2058 0.2618 81.4640 25.4500 

Placing a period ( . ) before the operators * , / , and ^ , transforms them into array operators.

Logical array operations

MATLAB comparison operators also accept vector inputs and return vector outputs. For example, suppose while collecting data from 10,000 cones, you record several negative values for the diameter. You can determine which values in a vector are valid with the >= operator,

>> D = [-0.2 1.0 1.5 3.0 -1.0 4.2 3.14]; >> D >= 0 ans = 0 1 1 1 0 1 1 >> class(ans) ans = logical 


You can directly exploit the logical indexing power of MATLAB to select the valid cone volumes, Vgood , for which the corresponding elements of D are nonnegative,

>> Vgood = V(D >= 0) % removing all data corresponding to negative diameters Vgood = 0.2618 1.3254 21.2058 81.4640 25.4500 


MATLAB allows you to perform a logical AND or OR on the elements of an entire vector with the functions all and any, respectively. You can throw a warning if all values of D are below zero,

if all(D < 0) % gives no warning because not all values are negative warning('All values of diameter are negative.') end 
>> if (D < 0) warning('Some values of diameter are negative.') end Warning: Some values of diameter are negative. 


MATLAB can also compare two vectors of the same size, allowing you to impose further restrictions. This code finds all the values where V is nonnegative and D is greater than H ,

>> D = [-0.2 1.0 1.5 3.0 -1.0 4.2 3.14]; >> H = [0.0400 1.0000 2.2500 1.5000 1.0000 0.6400 9.8596]; >> V((V >= 0) & (D > H)) ans = 21.2058 81.4640 >> V V = 0.0004 0.2618 1.3254 21.2058 0.2618 81.4640 25.4500 >> (V >= 0) & (D > H) ans = 0 0 0 1 0 1 0 


The resulting vector is the same size as the inputs. To aid comparison, MATLAB contains special values to denote overflow, underflow, and undefined operators, such as inf and nan. Logical operators isinf and isnan exist to help perform logical tests for these special values. For example, it is often useful to exclude NaN values from computations,

>> x = [2 -1 0 3 NaN 2 NaN 11 4 Inf]; >> xvalid = x(~isnan(x)) xvalid = 2 -1 0 3 2 11 4 Inf 

Note that Inf == Inf returns true ; however, NaN == NaN always returns false in MATLAB.

Matrix Operations

Matrix operations act according to the rules of linear algebra. These operations are most useful in vectorization if you are working with multidimensional data. Suppose you want to evaluate a function, $F$, of two variables, $x$ and $y$,

To evaluate this function at every combination of points in the $x$ and $y$, you need to define a grid of values,

>> x = -2:0.2:2; >> y = -1.5:0.2:1.5; >> [X,Y] = meshgrid(x,y); >> F = X.*exp(-X.^2-Y.^2); 


Without meshgrid() , you might need to write two for loops to iterate through vector combinations. The function ndgrid() also creates number grids from vectors, but unlike meshgrid() , it can construct grids beyond three dimensions. meshgrid() can only construct 2-D and 3-D grids.

The following table contains a list of MATLAB functions that are commonly used in vectorized codes,

Table of MATLAB's most-widely used vectorization functions.
Function Description
all Determine if all array elements are nonzero or true
any Determine if any array elements are nonzero
cumsum Cumulative sum
diff Differences and Approximate Derivatives
find Find indices and values of nonzero elements
ind2sub Subscripts from linear index
ipermute Inverse permute dimensions of N-D array
logical Convert numeric values to logicals
meshgrid Rectangular grid in 2-D and 3-D space
ndgrid Rectangular grid in N-D space
permute Rearrange dimensions of N-D array
prod Product of array elements
repmat Repeat copies of array
reshape Reshape array
shiftdim Shift dimensions
sort Sort array elements
squeeze Remove singleton dimensions
sub2ind Convert subscripts to linear indices
sum Sum of array elements

Why is vectorized code faster than for-loops?

The reason for the speedup in vectorized has to sought in the way the memory of computer is built. The figure below represents a schematic diagram of the Central Processing Unit (CPU) of every modern computer in relationship with computer memory.

At the highest level of memory hierarchy, closest to the CPU, we have the CPU register. A processor register is a quickly accessible location available to a computer’s CPU. Registers usually consist of a small amount of fast storage and may be read-only or write-only. The CPU has super fast access to data stored in register. But the problem is that this memory is very small, typically on the orders of bits of information.

At the second level of the hierarchy of memory, we have the CPU cache, typically comprised of three different levels L1, L2, L3, which rank from fastest to slowest respectively, in terms of CPU access. However, the faster the cache memory, the smaller it is. Therefore, L1 is the fastest of the three, but also the smallest of the three levels.

CPU Caching was invented to solve a significant problem. In the early decades of computing, main memory was extremely slow and incredibly expensive — but CPUs weren’t particularly fast, either. Starting in the 1980s, the gap began to widen quickly. Microprocessor clock speeds took off, but memory access times improved far less dramatically. As this gap grew, it became increasingly clear that a new type of fast memory was needed to bridge the gap. See the figure below.

After CPU cache, there the Random Access Memory (RAM) which you hear the most about, when you go to buy a new computer. Typical computers contain 4-32 Gb of RAM. When you open MATLAB and create some variables, all of your data is stored on this memory. However, this memory is the slowest of all in terms of access to CPU.

When you use for-loops in MATLAB to perform some specific calculations on a vector, you are asking MATLAB to go to this memory at each loop iteration to fetch an element of the loop, bring it to the CPU, perform the set of operations requested, and send it back to memory. However, the CPU is much more capable than doing a single calculation at a time. Therefore, if you could somehow tell MATLAB to fetch a bulk of elements from your vector and bring them to CPU to perform the requested operations, your code would become much faster. The way to tell MATLAB to do so, is called vectorization. By vectorizing your code, you tell MATLAB to bring as much information as possible to the highest memory level close to CPU, in order to perform the operations on all of them simultaneously and return the result for all of them back to the memory all together. This results in much faster code, since nowadays, as the figure above shows, the bottleneck in code performance is not the CPU speed, but the memory access.

Measuring the performance of your MATLAB functions and scripts

MATLAB has several built-in methods of timing how long it takes to run a MATLAB function or script. The timeit() function as well as tic and toc , are in particular very useful. Use the timeit() function for a rigorous measurement of your function’s execution time. Use tic and toc to estimate time for smaller portions of code that are not complete functions.

For additional details about the performance of your code, such as function call information and execution time of individual lines of code, MATLAB has more sophisticated tools such as MATLAB® Profiler.

Timing MATLAB functions

To measure the time required to run a function, whether built-in or your own, you can use the timeit() function. The timeit() function calls the user-specified function multiple times, and returns the median of the time measurements. This function takes a handle to the function whose performance is to be measured and returns the typical execution time, in seconds.

For example, suppose that you want to measure the performance of MATLAB’s built-in function, isprime() for a given input value to this function. You can compute the time to execute the function using timeit() like the following,

>> timeit( @()isprime(10^14) ) % pass the function as a handle to timeit() ans = 0.0787 


Note that, this function isprime() will have different performance given different input numbers,

>> timeit( @()isprime(10^4) ) % pass the function as a handle to timeit() ans = 2.0402e-05 

Time Portions of Code

To estimate how long a portion of your program takes to run or to compare the speed of different implementations of portions of your program, you can use MATLAB stopwatch timer functions: tic and toc . Invoking tic starts the timer, and the next toc reads the elapsed time.

tic % The program section to time. toc 


Sometimes programs run too fast for tic and toc to provide useful data. If your code is faster than 1/10 second, consider timing it while running in a loop, and then average the result to find the time for a single run of the loop.

The cputime() function vs. tic/toc and timeit()

There is another MATLAB function that can do timing of your scripts or your functions: The cputime() function measures the total CPU time and sums across all threads (cores) in the CPU. This measurement is different from the wall-clock time that timeit() or tic/toc return, and could be misleading. For example, the CPU time for the pause function is typically small, but the wall-clock time accounts for the actual time that MATLAB execution is paused. Therefore, the wall-clock time might be longer.

If your function uses four processing cores equally, the CPU time could be approximately four times higher than the wall-clock time.

Frequently, your best choice to measure the performance of your code is timeit() or tic and toc . These functions return wall-clock time. Note that, unlike tic and toc , the timeit() function calls your code multiple times, and, therefore, considers the cost of first-time calls to your functions, which are typically more time-consuming than subsequent calls.

Some tips for Measuring Performance