This repository contains experimental code in preparation for some of the topics are a part of the ECE2010 Intro to ECE course at WPI.
MATLAB is very convenient to test ideas as it is makes a lot of the menial tasks in writing code very simple to do by providing outstanding support for a lot of different domains. What is being traded off for convienece is the pure performace of the code that you write, from say, languages like C or C , which are much more difficult to work with than MATLAB but much faster. However, MATLAB is still highly efficient for any kind of matrix operations. All the built-in functions that are in use like A .* B, or A \ B run on efficiently written code in the background which utilises a concept call vectorisation. What it means that any operation where vectors are involved, it runs very quick in MATLAB. So if you have a logic that you want to implement in MATLAB and you can think about it in forms of any kind of vector operation, you can gain huge performance. However, if you have a complicated code that has a lot of for loops running, your performance will be quite slow, because you have line which are being executed sequentially, and there is no way to vectorise what you want to achieve.
In situations like these, compiled languages such as C and C are quite fast and can turn out to outperform MATLAB scripts quite significantly. To help with this, MATLAB actually allows you to run C code directly inside MATLAB. So let's say you have a particular task that has a lot of for loops and is turning out to be a bottleneck in the performance of your code, you can write the same functions in C, and have it run directly from your MATLAB scripts.
You can do this my creating whats called a MEX file. A MEX file is a compiled version of you C source code which is specially compiled such that it can be called directly from inside MATLAB, as a simple function. In order to successfully compile your source code as a MEX file, you have to take special care in your C code to address the variables in a way that is expected by MATLAB.
This tutorial is an introduction to how you can create your own MEX files.
for_looop_example.m
shows a simple for loop which increments a variable's value for a total of 1000 x 16000000 times.- For one set of calculations, we calculate the time it took for our computer to execute it as one of the elements in the vector
time
. - We repeat this experiment 10 times and calculate the average execution times over the repititions. Note the execution time.
- Now we have the same operations, but this time written in C in the file
for_loop.c
- Compile this on your computer using the following command
gcc -O for_loop.c -o for_loop
. Run this file using./for_loop
and see the execution time.
- You can't directly use any C source code in MATLAB. There are a few things that you have to change to make you C source code compatible with what MATLAB expects.
- Look at the
for_loop_mex.c
file to see what the compatible version of the previous C code looks like. Look for things that have changed, and what has remained the same. - The
int main()
function is replaced with avoid mexFunction()
function which has 4 parameters. These parameters handle the exchange of variable between MATLAB and C. The specifics are explained below:nlhs
: Number of terms on the left hand side of the command in MATLAB.plhs
: All the left hand side variables.nrhs
: Number of terms on the right hand side.prhs
: All the variable on the right hand side of the equation.
- You use the left hand side mxArray to output what you computes and the right hand side mxArray to get the MATLAB variable that you want to receive has arguments for the function.
- For this example, there are no inputs, so we will just leave that for now.
- Now we want to return the mean time that we calculated. We do this by using the
mxCreateDoubleScalar()
function from themex.h
library that was imported earlier. - Look at line 32. We are assigning the first variable on the left hand side(
plhs[0]
) the value ofmean_sec
. - That's it. This is enough for us to compile this as MEX file.
- Compile this source code using the following command
mex for_loop_mex.c
. You should now see something similar to for_loop_mex.mexa64 (the extension depends on your operating system). - You now have your first MEX file ready. Open your MATLAB window and write
mean_time = for_loop_mex()
in the command window. Check your execution time now.
- Let's move on to a more involved function where were are replicating the elementwise multiplication for two vectors. What is interesting here is that we will be giving 'MATLAB variables' as arguments to the function, converting them into 'C variables', and then converting the results in 'C variables' to 'MATLAB variables' again.
- Open the
multiplication_example.m
and see whats going there. We are defining two really long vectors, and multiplying them in three different ways.- Using the in built operator
.*
which makes use the vectorisation approach we talked about earlier. - Defining a MATLAB function doing the same thing, using only for loops.
- Writing C source code for and making use of a MEX function.
- Using the in built operator
- Take a look at the
multiply_matlab.m
function to see how you can do this using for loops in MATLAB. - Now take a look at the
multiply_c.c
file to see what a C code doing the same thing might look like. - Open the
multiply_mex.c
side by side to see the differences that these two codes have. - As you could probably guess, we again replace the
main()
routine by themexFunction()
function. Try to recall what the 4 arguments here are. - To assign the first input vector from the MATLAB arguments, we take the first value in the right hand side array(
prhs
) and use themxGetPr()
function to properly 'convert' the MATLAB variable into a C array,vector_1
. We repeat this for the second array. - Now returning the
output
array after multiplication is not really straightforward. - Since
plhs
directly supplies whatever is assigned to it to MATLAB, we can't really defineplhs[0]
as a C array. We have to usemex.h
functions to create an array that is understood by MATLAB. We do this by creating a 1 x N matrix using themxCreateDoubleMatrix(1, N, mxREAL)
function. - Now the problem is that what we have an
output
array which is an array of doubles as C knows it, but we can't assign that directly usingplhs[0] = output
because the variables on the either side are different data types. - This issue is addressed by using the
memcpy
function from thestring.h
library which copiesN*sizeof(double)
amount of values stored in memory, starting from the memory location of the first element ofoutput
array, to the first memory location of theplhs[0]
which we get from themxGetPr
function. - In order to copy the
output
values, we have to temporarily store all of its values in whats called the heap memory which we then have to 'release' using thefree(output)
command. - Now the source code is ready to be compiled as a MEX file. Again use
mex multiply_mex.c
in your command line to get a mex file. - Once you have the MEX file compiled according to your operating system, you can run the
multiplication_example.m
file to see the performance differences between the three different approaches.
- Write sample code to compare performance of C and MATLAB, prove that MATLAB is in fact slower for for loops.
- Create MATLAB sample function for elementwise operations.
- Create C sample function for elementwise operations.
- Write the details of making a function compatible for use as MEX file.
- Convert the C sample to a MEX file to be used in MATALB.