I am going to talk about arrays today. I know most of you know all about this, but keep reading. The beginning is for beginners but in the end I will talk about some advanced optimization you can do when using Arrays.
One of the first thing you will do in Matlab is to create an array. One can type in :
X=[1 2 3 4 5]
This will create a line or a ROW element.
You can also create a COLUMN of elements this way :
Now, even if X and Y are 1D elements, they can be accessed through their 2D coordinates, because X is a ROW and Y is a COLUMN.
In 2D matrices, to access elements, you just need to type in X(1,2) where 1 is the ROW number and 2 the COLUMN number.
This is why X(1,2) will work whereas X(2,1) will kick you out. Similarly Y(2,1) will work and Y(1,2) not.
Let’s now suppose we have a real full 2D matrix like :
Z=[1 3 5;2 34 9;4 90 1]
Z is a 3 by 3 matrix so you can access, for instance, 4 using Z(3,1). If you remember my crash course on Matlab, lesson 1, you know that you can access a complete row using the colon, like so :
To get a column, just do :
So far, so good. There are some important things to know about 2D Matrix (or higher dimensions). The rows and columns are NOT equivalent stricly speaking. Indeed when you create a 2D array in C, you need to reference each element to its memory address. As a result, for a 2D array, you need to allocate MxN elements in memory (where M is the number of rows and N of columns). Since memory is a linear object, you need to choose how you organize these elements. You have two options “Row major order” or “Column major order”. Matlab, as a faithfull son of Fortran, chose the Column major order option.
You can actually see this in action by doing :
Here you are asking matlab to spit out all the elements of Z in their native order. Matlab should tell you :
>> Z(:) ans = 1 2 4 3 34 90 5 9 1
First, please note that we have a column here. Expected, I told you Matlab was a Column major. Then you will notice for sure that, Matlab has ordered all the elements along the columns first. This means that if you were to draw the real object number, you would write this way :
1 4 7
2 5 8
3 6 9
In effect, this means that Z(3,1) is contiguous to Z(1,2) in memory exactly as Z(2,1) is contiguous to Z(1,1).
The first thing to remember from this is that this can be quite handy to vectorize your code. All arrays can be seen as a single column of numbers.
But what happen with 3D matrix?
Let’s find it out.
>> R=rand(2,2,2) R(:,:,1) = 0.1190 0.9597 0.4984 0.3404 R(:,:,2) = 0.5853 0.7513 0.2238 0.2551 >> R(:) ans = 0.1190 0.4984 0.9597 0.3404 0.5853 0.2238 0.7513 0.2551
rand is a convenient function that create a random matrix. rand(2,2,2) is a 2x2x2 3d matrix.
As you can see, Matlab first go along the column, then along the row and then go to the third dimension. I am sure you can generalize to higher dimensions yourself.
Now that we know how arrays are organized in memory, I just need to tell you one last thing but an important one. It is actually faster to successively access elements that are contiguous in memory. In other words, this :
X=rand(100,100,2000); for i=1:100 for j=1:100 X(i,j,:)=10*X(i,j,:); end end
is much slower than this :
X=rand(100,100,2000); for j=1:100 for i=1:100 X(i,j,:)=10*X(i,j,:); end end
I will let you all try it out with the profiler. But it is 2 times faster on my machine. Why is this useful instead of just vectorizing your code?
Sometimes, you can’t vectorize. And when dealing this movies, for instance, this technique can be worth the try.