Automatically Converting MATLAB Code to C Code
Attend this presentation to learn how to automatically generate readable and portable C code from your MATLAB® algorithms. With MATLAB Coder™, you can reduce development time by smoothly transitioning from algorithm to implementation using automatic C code generation. This C code does not require any further MATLAB libraries and can be freely distributed.
This presentation shows how you can use a command-line approach or the graphical project management tool to:
- Introduce implementation requirements, such as data types and sizes, static/dynamic memory allocation, and code in-lining, into your MATLAB algorithm
- Generate readable source code, an executable, or a library
- Generate MEX functions to verify the behaviour of the generated code in MATLAB
- Generate MEX functions to accelerate your MATLAB code
Recorded: 19 Aug 2014
Hello, my name is Daryl Ning, and today we'll be talking about how you can automatically convert your MATLAB to C code using MATLAB Coder. To begin with, let's start with an example using a Euclidean distance measure, and I'll show how you can take a MATLAB function, and using MATLAB Coder, generate generic NCC code. So let's jump back out to MATLAB. So here in MATLAB, you can see our original function, and the function is called Euclidean. Euclidean takes some input vector, x, and then compares this vector to a code book of vectors and returns the vector with the minimum distance. You can see that we make a call out to another function called norm.
We've got a for loop, and we have an if statement. But it's just a fairly basic little MATLAB function. Now, when we run this through MATLAB coder, what we'll get is this C code. So if you take a look at this C code, you'll see that we've got this helper function called norm, and there's the C code, and I'll scroll a little further down. You'll see here's our main entry point function called Euclidean and again the C code. So hopefully from this, you can see that the C code we generate is first of all generic, and it's readable. Here is a customer that has already been successful using MATLAB Coder. iSonea developed mobile app and service software for wheeze detection and asthma management. Using MATLAB Coder, they were able to reduce their manual coding effort, they accelerated their algorithm development iterations, and on top of all this, their code maintenance overhead was reduced.
You can see in the quote here that they said that there is no other environment or programming language that they could have used to produce similar results in the same amount of time. So let's take a look at the agenda. First of all, we'll talk about the motivation for MATLAB to C-code generation. Then, we'll talk about the three-step workflow for generating C code. We'll then take a look at some use cases and quickly summarize. So why do engineers translate MATLAB to C? Well, there are a number of reasons. First of all, they may need to implement C code onto processes or hand off this code to software engineers, so here they need the raw NCC code. Alternatively, they may need to integrate their MATLAB algorithms with an existing C environment, so they want to take the source code and create some sort of static or dynamic library.
Another reason they may want to do this is because they want to prototype their MATLAB algorithms on desktops as standalone executables. Finally, some people just want C code from MATLAB to accelerate their user written MATLAB algorithms, basically for faster simulation. So if we think about this from a technical computing workflow point of view where we have our access data stage, our explore and discover stage, as well as our sharing stage, what we'll be showing is how you can move from an algorithm development to deployment, where the deployment is standalone NCC code. But more importantly, how we can move back and forth between these stages very, very quickly. So if we think about what we're doing here and what we're starting off with, we're starting off in the MATLAB environment. And in the MATLAB environment, you can do a lot of things. So you can visualize your data, you can develop your algorithms, you can even develop user interfaces that wrap around your algorithms like apps.
Now, if you want to take all of that, you want to take the visualization, the algorithms, and the user interface and deploy that to some target, the solution we have for that is something called MATLAB Compiler. Now, MATLAB Compiler can create standalone executables and C shared libraries from your MATLAB algorithms, including the visualization and any user interface you wrap around that. The downside of this is that this application will require something called the MATLAB Compiler Runtime, so there is some overhead. There is an engine that needs to be running in the background. MATLAB Compiler does not turn your MATLAB algorithms into C code. If, however, you just want to take the algorithm and create standalone NCC code, this is where MATLAB Coder comes in. So MATLAB Coder is able to generate C code for most MATLAB algorithms and give you that standalone readable C code like you saw on the initial example. You can then take this C code and do what you want with it, whether you want to create an executable or a library.
So this path is what we'll be talking about for the remainder of this presentation, but I will briefly touch on the use cases for MATLAB Compiler towards the end. So let's just start with an introductory demo, and I'll show you how you can use the MATLAB Coder app to help you in the code generation process. So let me jump back out to MATLAB. All right, and what we're going to be looking at here is just a simple matrix multiply. So you can see here that I've got a basic function, which simply multiplies two inputs called mymult. Now, if I want to generate C code from this function, what I'm going to do is go to my apps tab in MATLAB, and I'm going to open up my MATLAB Coder app. So if I scroll down here to my code generation apps, I'm going to click on MATLAB Coder. The first thing is it asked me to give a name for my project, so I'm going to call this mymult.
Now, when the project opens I first need to add the entry point file. So to do that, I can simply click on Add Files and click on mymult. Now, because we're generating C code, I now need to define the input sizes and their types. So to do that, I can click here to define them. So for the input a, let's just keep this simple to start with, and I'll say that input is a double and it's a scalar. Likewise for b, it's a double and it's a scalar. Once I've done that, I can click on my build tab, I can change my output type to a C static library, and just to start with I'm just going to generate the C code. I won't compile it. And then I can click on build. When I click on build, MATLAB Coder will now go ahead and generate the C code from my MATLAB function. If there are any errors or any troubles that it runs into, it will give me some warnings here. But it was successful, and then I can click on View Report. And what you'll see here is that here is my main entry point function, so I've got returns a double and simply multiplies a and b.
Now, I'll talk about all these functions or these C and header files that it generates later in the presentation, but let's go back to this function now and see how we can actually change the input definitions and generate different code. So if I go back to my overview tab here, I can actually change the input definitions here to generate a different multiply. Alternatively, I can also auto define these sizes and types using some sort of test bench. So if I go back to MATLAB, you'll see I've already created a test bench here which calls mymult. And you can see in this test bench that it multiplies a double input of size three by four with a double input of size four by five, and it just creates some random matrices to do this. I can use this test bench to auto define my types in the MATLAB Coder project. So if I go back here, what I can do is click on Auto Define Types, and all I need to do is specify that test bench, my test bench. If I run that, what MATLAB Coder will do is actually run that test bench and from that test bench, it will figure out what the actual input data types and sizes are.
I can click on Use These Types, and you can see that MATLAB Coder has automatically updated my input definitions. Now, when I click on Build, I can generate a matrix multiply as opposed to a scalar multiply. If I click on View Report, here you'll see now my main entry point function has a nested four loops, which executes my matrix multiply as defined in my test bench. What are some of the challenges when you manually translate MATLAB to C? Because this is typically what most people will do without MATLAB Coder. So they'll have somebody who is doing the algorithm design in MATLAB, and then they'll recode it into C or C++ for deployment, whether they want the raw C code or some library or an executable. But here, however, normally you need to verify that that C code behaves the same way as the MATLAB code, because normally your MATLAB code is your golden reference, and you want to ensure that that manual implementation behaves the same as the original MATLAB algorithm.
So there is this verification step involved here. Not only that, but typically what happens is the algorithm will change. This may be to improve the algorithm, or maybe the requirements for the design have changed. But inevitably, the algorithm will change which means you then have to make the appropriate changes in the manually written C code. And this iteration can happen many, many times in any design cycle. So the problem we have here is that we've actually got a separate functional and implementation specification. We need to manage both the MATLAB code and the C code. So it makes it very difficult to modify requirements during development, because it means any requirement changes will result in more iterations. And it's very difficult to keep the reference MATLAB code in sync with the C code. On top of this, everyone is human and so you'll probably also introduce some manual coding errors that you need to debug and fix.
So the whole process or this whole manual process can be very time consuming and expensive. When doing this, there are implementation considerations. For example, remember our original function, which was a simple multiplication. Here, we've written the function as a equals foo of b and c where a is equal to b times c. How do you implement that? It could be an element by element multiply, it could be a dot product, it could be a matrix multiply. Alternatively, the data types could be different. They could be logicals, they could be integers, they could be anything. So when implementing this in a C, It's not just a simple matter of saying return b times c. This simple multiplication could be something completely different depending on how the original algorithm designer intended it to be integrated into some larger code base. So that's an example of polymorphism. You've also got to think about how you want to deal with memory allocation.
MATLAB is very easy to use, because it will just simply dynamically allocate memory when you need it. But when you implement the C code, you need to make decisions as to whether you want to use static memory allocation or dynamic memory allocation or a combination of both. Related to polymorphism, are you processing matrices or arrays, because that's going to affect the implementation. Are you using fixed point data types in your MATLAB code, and how do you convert that over to integer types in C? So the end result is that a basic MATLAB function like this which is for a Kalman filter could be five lines of MATLAB code, because it's basically a lot of matrix operations. This could turn into hundreds of lines of C code. When we're using automatic translation of MATLAB to C, the idea is you have the algorithm design and the code generation all done in MATLAB. So our original algorithm designer can simply generate a MEX fall. Now, if you're not familiar with what a MEX file is, a MEX file is basically compiled C code. So it's like a library that can be called directly from MATLAB.
A MEX file does have a wrapper around the C code which allows you to pass MATLAB data types to and from C, and the idea of creating a MEX file when you were generating C code from MATLAB is so that we can verify that the C code that is generated behaves the same as MATLAB. Once we've verified that this C code behaved the same as MATLAB, we can go ahead and create the libraries or the executable. Alternatively, we can continue iterating on the algorithm. But because there's no manual translation involved now, the whole process is much more streamlined. So with MATLAB Coder, you can basically maintain one design in MATLAB and get to C much, much faster. The advantage of getting to C faster is that you can actually perform more testing on your original algorithms and spend time improving the algorithm in MATLAB instead of implementing something which may not be actually for implementation simply due to time constraints.
So let's take a look at the three-step workflow for generating C code from MATLAB. So here it is here. And you can see the first step is that you need to prepare your MATLAB algorithm for code generation. So when you're preparing your MATLAB algorithm, you need to decide on what implementation choices you're going to make, but also make sure that your MATLAB algorithm uses the supported language features. So when generating C code from MATLAB, we don't support all the MATLAB language, but we do support most of the MATLAB language. And I'll talk about this a bit later. So once you've prepared your code, you then need to test that your MATLAB code is compliant. You need to validate that the MATLAB code you have can actually generate your code, and then you can perform iterations on this code for optimizations, and finally, you can generate the MEX file to verify the C-code implementation against your original test bench. Once you've done this verification, you can then take the raw C code, the NCC code, and implement it as a source or a library or as an executable. Depends on how you want to use it.
So to give you an example of this workflow of taking a MATLAB algorithm and converting it to C, I'm going to run through a more extensive example now using a Newton-Raphson algorithm. So let's jump out to MATLAB again. And let's close some of this down. And let's open up my Newton-Raphson algorithm. OK, so what this is going to do is use a Newton search technique to find the nth root of a number. So before I look at the code, let me just give you an example of what I mean by this. Here is my test bench. So my NRT function in this case is going to take the fourth root of 10. OK, so I want the fourth root of 10, and I'm going to specify some tolerance value. And this is used because the algorithm is iterative, so I want to tell it when to stop. So if I was to execute this, you'll see that the fourth root of 10 using this algorithm is about 1.7783. So let's take a look at the algorithm itself.
You can see it returns the nth root. It also returns the number of iterations and also the history of values that it calculated in each of those iterations. And it has a variable number of inputs. If I scroll down—it should let me just make maximize this—we can see in the algorithm itself if the input specifies a value less than zero, we are simply going to return zero. Alternatively, if the user specifies a value greater than zero, then we'll execute this Newton search algorithm. So if we take a look at that, the Newton search algorithm as you can see here is basically a while loop, so it'll loop through and iterate to find that nth root. One thing you'll notice is that it will automatically stop after 50 iterations. Further down, you'll see a sub function in here, and this sub function is used to calculate a derivative. So we've got a main function. We've got a sub function.
This will return the nth root as well as the history, and if we go back out to the main calling function, when we've got the history we can also calculate the number of iterations that were required to reach our final value. So that's what this function does. So let's use MATLAB Coder to generate C code from this function. But the first thing I'm going to do is use something called the Code Readiness Tool. Because maybe what I want to do is initially get a feel for how long it will take me to make this code generation ready. So what I can do is I can select the function that I want to generate code for. I will right click on it, and you can see down here I'll have an option which says, Check Code Generation Readiness. And when I select that, this will give me an indication of how difficult it will be to generate C code from this function. And you can see here that the code generation readiness score is five, so MATLAB thinks it will probably take minimal changes to get this MATLAB code to generate C code.
It even breaks it down by code structure, so you can see how difficult it will be for the internal functions to generate C code. And in its current state, it looks pretty good. So let's just open up our Coder app again. And this time, I'll call our project NRT. We'll do the same as we did last time. We will add our entry point file, which is NRT.m. And then rather than specify what the inputs are, I will auto define the types using my test bench. So there's my test bench. Let's run that, and the Coder app can figure out what the input data types are. And in this case, it's pretty simple. They're just three scalar doubles. So the first thing I need to do then when I generate C code if you remember our three-step workflow is to check that it actually can generate C code. And we can do this by trying to create a MEX function. So if I just try to create a MEX function to start with, if I click on build, this will try to generate C code and then turn it into a MEX function for verification.
Now, if it runs into errors, it will let me know. And you can see here it's actually run into errors. So I'm just going to open up my Error Report, and you can see the list of errors that it has run into here. And if I just select the first one, you see it's highlighted the line. And it says when I hover my mouse over here, there's an undefined functional variable, h. The first assignment to a local variable will determine its class. So what it's telling me here is that when I first assign a local variable in this function, this will define as class. And here by saying this, I've actually defined it as a scalar. The problem is if you see this other little red underline here—this is inside a loop, and what we're actually doing is we're increasing the size of h inside this loop. So that's why we're getting this error message. But I know that the number of iterations will have a maximum of 50, so what I can actually do is pre-allocate the memory to this value, h, which is a history, and hopefully that will sort our problem out.
So if I go back out to MATLAB and go into the Newton search algorithm, this is where we had our problem. Let me just add a line here and say, h equals zeros of a 50 element vector. So we're pre-allocating the memory first, and then we just save that. And let's see if this helps us out. So if I go to my code generation app again and try to build it again—OK, now code generation is successful. I won't look at the report, because it's actually a MEX function. We could look at it, but it's got a lot of wrapper code which makes it look a little bit messy. In any case, the MEX function is only generated for verification. So what we can do is we can use that MEX function to verify that the C code that was generated behaves the same as the original MATLAB algorithm. And to do that, we've got this verification section down here. You can see we'll use our original test file test bench.
But the important thing is this checkbox here. It says it will redirect the entry point calls to the MEX function. What this means is when we run our test bench which is here, rather than call NRT which is our MATLAB function, what it will call is our MEX function which is the compiled C code. So our MEX function is actually called here, NRT underscore MEX. So all that this will do is redirect any call to NRT to NRT underscore MEX. So if I click on Run, it will run the test bench, but when it runs a test bench, it actually runs it calling our MEX function. And if you look at the command window, you see that we get the same answer. And that's our verification that the C code that we generated behaves the same as the MATLAB code. Now, obviously you could probably build up a much more complex test bench here, but this is just a simplification for this example. So now that we've actually verified that the C code behaves the same as MATLAB, what we'll do is we'll now just generate the raw C code without the MEX wrapper. So let me just change our output time to C static library, and we'll just generate the code and click on Build.
So now, this will create just the raw NCC code for this function. So we can take a look at the report. So we take a look at the report. We can see first of all we've got this little helper function up here. OK, it looks like it's dealing with some infinite numbers, some non-finite numbers here. If I scroll further down, you'll see here's my main entry point function for NRT and then all of the C code that it generated to implement that particular function. So we've got about 175 lines of C code here. I think one other thing I should point out is that if you go back to the MATLAB code, in the MATLAB code it also gives you a report of the original MATLAB code. When you hover your mouse over some of these variables, you can see it gives you information about the size and the class and the complexity. And this can sometimes be useful when you're trying to debug your code. I just thought I'd point that out.
But if we go back to the C code, the first thing you'll notice is that there are a lot of functions that we generated. So why have we generated a lot of functions? Well, the first things we see are the initialize and terminate functions. Now, whenever we generate C code, we will always generate an initialize and a terminate function. And it's good practice to call the initialize. OK, here it is here, the initialize function. And before you call your main entry point function when you integrate it into your target code, and then following that to call the terminate function. So obviously in the initialize function, that will initialize things like states. Maybe you've got some persistent memory in there. It's important to do that before calling the main entry point function. Terminate may be used. If you've opened up maybe some file pointers, it will close down some file pointers. Things like that. But the important thing to remember is always call the initialize function first before calling the entry point function, and then call the terminate to finish if required. Now, there may not always be something inside the initialize functions and the terminate functions, but it's a good practice to simply keep them in your target code because if you happen to change your algorithm and we do generate some code which happens to be put inside that initialize function, after you've generated the code there is no need to change the code in your target environment.
You can just leave it as is, because it already calls initialize, it will call your entry point, it will call your terminate. The other functions we have in here are these get imf C, get nans—this is all code that handles non-finite numbers. We do that because MATLAB can handle non-finite numbers, and if you happen to generate code which needs to handle that, well then you're ready to go. But if you don't need that support, you can also turn it off. So to do that, what we'll do is I'll go to my More Settings, and in my More Settings I've got some options here. One of the options is Speed, and you can see I can actually turn off support for non-finite numbers. If I do that and hit Close and then rebuild it, MATLAB will rebuild the code without that non-finite number support. Now, if it turns out that your code does require support for non-finite numbers, it will throw an error here and tell you that you need to check that box again. However, in this case we don't need it. So when I look at the report, you can see that now we have less C and header files, and if we scroll down now, you'll notice that that original helper file that we had above the entry point function is no longer there.
So it looked like that helper function was simply to handle non-finite numbers. And if we scroll further down, this is all our code. We're now down from 175 lines of code down to about 115 lines of code simply by removing that non-finite number support. Another thing I sort of want to point you to here is you'll see that there are actually comments in here. So you can see there's a comment here, after 50 iterations stop, and a comment here, determine iterations. Now, those comments come directly from the MATLAB code, and the comments from the MATLAB code will help you trace the MATLAB code to the C code. It won't always work, because there are optimizations that are performed when generating the C code. We don't just do a line for line translation. Otherwise, it would be extremely inefficient. However, it will help you sort of trace where the original MATLAB code was in reference to the generated C code.
But one thing I want to point out here is after this determine iterations, we can see again a bunch of C code which looks like it's performing a while loop to do checking something. And if we go back to the MATLAB code here, you'll see that here is our determine iterations, but after that we've simply got one line of MATLAB code. So we've got one line of MATLAB code, yet that generated multiple lines of C code. So why is that? Well, if we look at this MATLAB line of code, what it's trying to do is determine how many iterations were required to calculate the nth root. And although it's only one line of MATLAB code and it does the job, it's an extremely inefficient way of finding how many iterations there were. And this is where I guess if you put garbage into MATLAB Coder, you will likely get garbage out. So you do need to be smarter yourself in actually constructing your algorithm such that it will generate nice C code.
So here, this line of code isn't necessary. We could probably replace this line of code with something like iterations equals sum of history not equal to zero. I mean, that might be another way of actually calculating the number of iterations based on that logical vector that's returned by history not equal to zero. So if I save this and then go back out and regenerate the C code and view the report, I'll scroll back down to that area of the code, and you can see here we've now collapsed a lot of that code. It was about 115 lines before. Now, we're down to about 92 simply by making a very subtle change to the MATLAB code which makes the algorithm more efficient. You could even go a step further. Let's just say you wanted to be more verbose about how you wanted to calculate the number of iterations and write it even a bit like C code. So here I could say something like iterations equals zero and then do a for loop and actually loop through for JJ equals one to length of history. We can say iterations equals iterations plus one. Else, we will break.
I need to do a check here. If history of JJ is not equal to zero, then we'll actually increase the number of iterations. So that's more of a C stall way of doing the same thing. So if I save that and go back to my app and rebuild the code and take a look at the report, now we're down to about 90 lines of code. And I guess one thing I want to point out here is even though in my MATLAB code where I wrote a for loop with an if statement inside, MATLAB Coder was smart enough to look at that and say, well, rather than do the for loop with the if statement, let's just change that to a while loop with a couple of conditions. So that's an example of one of the optimizations that MATLAB Coder might do for you. OK, so now we're down to about 90 lines of code here. The other thing I want to look at here is this entry point function.
So when we look at the entry point function, we've got all our inputs. Then we've got our outputs, which is the nth root, the number of iterations. But if we take a look here, the history looks a little strange. The output history. I would have expected a 50 element vector that outputs our history of values, but instead what I see is this history data variable and a history size. And whenever you see these two, I guess these two variables like this, arguments like this, that indicates that you've got some variable sizing in your code. OK, so what MATLAB has done is it's returning some data, and it's also returning where you are inside that sort of pre-allocated memory, because it doesn't always know because it can vary in size. Now, if we go back to our code, we can figure out why that's happening. And it happens in this main function NRT. So although Newton's search algorithm here will return a 50 element vector for history, because remember in our Newton search algorithm, we pre-allocate that to 50 elements, the problem is that this NRT function when it's called with a value of less than zero, it will assign a value of zero to history which means MATLAB Coder will look at this and say, well, history can either be a scalar or it can be a 50 element vector.
That's where this variable sizing comes in. So to get around that given the history zero, we can just define this to be a vector of zeros instead. And that means history will always be a 50 element vector. So let's save that and go back to MATLAB Coder app and rebuild it. And when we rebuild it, we can take a look at the report. And what you'll see here is this is more of what we expect. Our output is just simply a vector of 50 elements, and that's cleaned up a bit more of the body of the code as well. So now we're down to about 82 lines of code, so we started off at about 170 lines of code and now we're at 82 lines of code with just a few little modifications. Another thing you'll notice about this is that the Newton search algorithm has actually been inlined into this entry point function.
So in the main NRT in MATLAB, where we have this else statement if the input is greater than zero, we make a call to the Newton search algorithm. But in the actual C code, you'll see that that Newton search algorithm—here's the else statement here—the Newton search algorithm has been inlined into the code. Now, let's just say you didn't want that inline. Now, Coder will inline it if it thinks that there's only a few lines of code and it makes it more efficient. But you can force that to be off if you like. And the way we can do that is in my Newton search algorithm is at the top here, I can just say, look, coderdotinline never. Never ever inline this code. And if I do that, I can go back to the code generation, rebuild it, and when I rebuild this now you'll see in this report that in my entry point function here after my else statement, I now actually make a call to Newton search algorithm. If I click on that, you can see that this is actually a separate bit of C code with its own header file.
OK, let's close this down. So hopefully that gave you a better idea of how you can use this workflow to generate C code from your MATLAB code. Now, I mentioned before that MATLAB Coder supports only a subset of the MATLAB language. We can't generate C code for all the MATLAB language. This little Venn diagram sort of gives you an indication of what we do support. So everything inside this light blue is supported, so we support variable-sized data, we support fixed point persistence classes, globals, structs, but you'll notice on the outside here some of the things that we don't support. So visualization is something we don't support. We won't generate C code for a plot or a surf or anything like that. We won't generate C code if you make native Java calls, if you use cell arrays, we don't support them yet. So there are a few things that we don't support, but this is all fully documented. In terms of features and functions, you can see here here, here's a table.
Most of the MATLAB features and functions are supported. All your different matrices and arrays, most data types are supported as well as programming constructs. In terms of functions, we support most of MATLAB's base functions. We support a lot from the signal processing tool box, communication systems tool box, and computer vision system tool box, and also some function from the statistics tool box. But again, this is all fully documented. So now that I've shown you how to generate C code, let's take a look at some use cases. So I mentioned that the use cases were firstly to integrate algorithms with custom software, to accelerate MATLAB algorithms, to prototype algorithms on PCs as well as to implement on embedded processes. So let's take a look at a code integration example. And here I'm going to generate some code for a zooming algorithm and then integrate that into a Visual Studio parent project.
So we jump back out to MATLAB. I'll close some of this down. Let me open up the algorithm I'm going to talk about. So to show you what it does just to start with, let me just run this little simulation. So on the left hand side, we've got some image that's being stabilized. Now, I've got a zoom factor up here. What I want to do is zoom into the stabilized image. You can see as I move the slider bar, I can zoom it. Likewise, I can make it smaller. Now, I'm not generating code for this entire application. It's just for the algorithm which does the zoom. So if I stop this, we'll take a look with this algorithm. The algorithm is called image process. It takes an input image as well as some factor. Obviously, if the factor is greater than one it will magnify, if the factor is less than one it will shrink it. So you can think if you're magnifying an image—let's just say you've made an image twice as big—you'd need to somehow interpolate between each of the pixels to make that image bigger.
And that's what this algorithm does. Now, I guess it's not important what this algorithm does. We just want to show that we can integrate it into another system. So let me just open up an existing project just to save some time. Now, one interesting thing you'll see here is that the input image I've defined as a type double and colon infinity mult by colon infinity. What this means is that the input dimensions are anything up to infinity by anything up to infinity, which means I've got no idea how big the input images is, which means I have to use dynamic memory allocation for this. If I click on build, under More Settings you'll see where I can set that up under memory here. You can see that I can enable variable sizing support, and that's actually on by default, and then also enable dynamic memory allocation. So you can control that here. If you wanted to use static memory allocation, you could obviously deselect that but then we wouldn't be able to generate code for this project.
So let me just click on Build. And what this is going to do is generate the C code required to implement that algorithm. But because we're using dynamic memory allocation, it will also include some other functions. So you can see that if we take a look at the entry point function for image process, you'll see that the input image is of this type EMX array underscore real underscore t. Now, this is because the input is unknown, and what MATLAB Coder needs to do is create its own sort of data structure to handle dynamic memory allocation. Now, because we're creating our own data structure, we also create an API to allow you to work with these custom data structures. So if I look at this image process underscore EMX API.CPP, this is where you'll see these functions to help you deal with this custom data structure. And I guess one thing here you'll see is the EMX create real, so this is how you can create something of this data structure. And you can see it's basically appointed to some data as well as appointed to what size.
Likewise, because we're creating our own data structures, we've also got a utility function here to destroy that once you've finished with it. So now that we generated the code, let's integrate that into another project. So again, let me just open up an existing project. Let's open up this solution here. So this will open up in Visual Studio. Sorry, let me open up this outside MATLAB. So the idea here is we've just created some generic NCC code, and we want to integrate that into another environment which is written in C or C++. So I'm opening up an existing solution here, and what this solution actually does is it takes an input stream from a web cam, and then the data we get from the webcam will feed into our zoom algorithm and then display it. So here are my files. And let's take a look at the original main.CPP file here we've got in this parent project.
We're going to be using some open CV utilities just to talk to the webcam and also to display it on our PC. But if you scroll through this main file, the main thing to look at is here is where we've used that utility function, this EMX create underscore real underscore t, so we're creating that custom data structure which we need to use. Here is where we run the initialize function, and here is where we create the output image because we've got some unknown size input image with some unknown size output image. If I scroll a bit further down, there's a for loop here which just populates that data from the webcam data, and here is the call to the code generator by MATLAB Coder. There's my image process function. Once we've processed it, we populate the output array. So let me just build the solution. OK, now that is built. I'll just close it down, and I'll go into my Release Directory.
And you can see, here is my video webcam dot EXE which I just built, and what I'm going to do is call that from MATLAB. So I'll use my Bang Operator video webcam, and I'll give it a magnification of 1.5. Now, what you'll see here is I've got a webcam hooked up to my laptop, so I'm just moving it around. I'm at a desk at the moment. There's a chair, and you can see here is the magnified image magnified by 1.5. So this is just showing you that the C code we generated from MATLAB Coder running in some other parent Visual Studio project. OK, another thing we can do is we can integrate existing C code into the code generation process. So this is useful if you have some existing C code which you want to use instead of MATLAB Coder generated C code, and it may be because you have some optimized implementation for the function that you're currently using.
There are a number of ways to do this, and I'm just going to show you a simple way using something called Coder.target and Coder.CUL. So let's jump back out to MATLAB, and let's take a look at this custom convolution function, which I'll integrate. So all I'm doing here is I'm doing a convolution. Here is my test bench. I can just run this. It's got two input vectors, and then I can do a convolution. That's all it's doing. But in the actual function itself, here it's called a custom com underscore ceval. This is the function here. And the way I've structured this allows me to call external C code. So by the way, the actual C code I'm going to use is here. It's called custom underscore com dot c. It takes the input signal as well as the signal length, the input kernel as well as the kernel length, and then returns the output And then what we've got here is just some C code for a convolution. So in the MATLAB code itself, when I call this MATLAB function it branches off into two separate paths depending on what MATLAB is doing.
So when I use coder.target, I can say, well, if I am executing in MATLAB and if I give it this input, this will test if it's running in MATLAB. So if this function is running in MATLAB, I will call MATLAB's native convolution function, because I need to because I need it to run in MATLAB for simulation purposes. Else, if I'm not running in MATLAB I'm generating code. So if I'm generating code, what I want to do is make a call to an external C function called custom conv. And when I make a call to this external C function, I'm going to pass in my input x, but I'm going to pass it by read only reference. I'm going to pass in the length of x. I'm also going to pass in the kernel, read only pass by reference read only as well as a length, and then I'm going to return the output as y. So this handles the sort of data type conversions when you're calling the C function. So when I generate C code for this function here, it's not going to use this path. It's going to use this path here and integrate some external C code.
So let's show that. We'll just go back to MATLAB—oh, I'm already in MATLAB but I'm going to open up an existing project, OK, here I've got my entry point function. Now, the only real thing I'm going to do here is in More Settings when I generate my C code, you can see here in custom code, I'm going to tab for that, I can just specify where that custom C code resides as well as the include directory so that once I've specified that, I can build it. And when I build it, you'll notice when you look at the C code it doesn't generate C code from the com function. Instead, what it does is it makes a direct call out to that custom underscore com c function which I showed you earlier. If I click on that, there it is here. So again, what we've done here is we've been able to integrate some external C code into the code generation process, and this is useful when you've got optimized routines. So what if you want to accelerate MATLAB algorithms?
Well, the first thing I would always say is rather than look at C code generation, always first look at better algorithms. For example, if you're doing a matrix inverse, maybe you can look at different approaches to solving the same problem. Look at different more efficient implementation using optimized libraries. Alternatively, look at using additional computational resources through—MATLAB has access to additional processes and GPUs through a parallel computing tool box. So there are a number of other options you can look at before looking at C code generation. So when it comes to accelerating algorithms, the first thing you should always do is look at optimizing your MATLAB code. Investigate parallel computing options. If you're dealing with DSP systems and communications, take a look at system objects. Try implementing your own custom code using MEX, but if you don't want to write your own C code, well then that's where you can try out MATLAB C code generation.
So the example I'm going to use here is just running that Newton-Raphson algorithm again and comparing the MEX files that we generate to the original MATLAB code. So if I go back out to MATLAB, what I've done is I've written a little script here. I'm going to run 1,000 iterations. Now, the first thing I'm going to do is time the MATLAB code, and you can see in this MATLAB code all I'm doing is calling that NRT algorithm, and I'm wrapping it with a tick and talk to time the execution. And let's just run that a few times in MATLAB. So in MATLAB, it takes about 0.003 seconds on average. Now, let's time the MEX code. So what I've done previously is I've already converted that NRT algorithm into a MEX file, and I did that using the final iteration of the example that I showed earlier in this presentation. So I'm going to do the same thing, but I'm going to run the MEX fall 1,000 times and look at the average time. All right, so when I run that a few times I see it varies a bit. I mean, we're looking at small numbers here, but we're looking at about 2.7, 2.8 by 10 to the negative five seconds to run the same algorithm.
If I take a look at the speed up factor—so in this particular case, we're looking at a speed up factor of about 11, but that is not indicative of what you'll get. It will really depend on the MATLAB code that you've written, but you can get speed up. The speed up factor is going to vary, and I guess where you may see speed up is often when you're dealing with communications and signal processing, pretty much always when you're dealing with fixed point algorithms, and also when your original MATLAB code has a lot of for loops with state, where you haven't been able to vectorize your algorithms. That's where you'll often see speed up. Where you won't see speed up or you might not see speed up is when you're doing a lot of linear algebra like matrix computations, because in MATLAB they're already very fast because they make calls to IPP and BLAS libraries, and they're already multi-threaded computations. So you won't see much of a speed up when you try to MEX that type of computation.
They're already optimized in MATLAB. If you have the parallel computing tool box, we also support multicore for MEX functions. So if you're using a parfor loop, for example, when you generate the MEX function it will also run multicore using open mp technology. But that does require that you have a compiler that supports open mp. Likewise, if you just generate standalone C code, not a MEX file, it will also use this open mp. But again, you do need a compiler that supports open mp. I guess another thing that people may want to do is actually prototype algorithms on a PC. And so this is where you can use the generated code and also provide a main dot C file as an entry point and get MATLAB to not only generate the standalone C code but then compile it to an XE. So let's take a look at one of those examples. I'm going to run this video stabilization demo again. So similar to the one you saw before when you saw the zoom.
This uses a whole bunch of computer vision system tool box system objects. So if I run this rather than looking at the code, what you'll see is this video stabilization. Now, I mentioned earlier that MATLAB Coder doesn't support portable C code generation for visualization. Now, this particular computer vision system tool box system object is an exception. We do support visualization here. We will support code generation for this window, and that's mainly because it's not really a standalone C. It's actually a C library, which will include-- and it will be platform dependent. But let's see what we can do with this. If I go back to my folder and open up the project for this, let me just click on build. Now, I've got the output type here specified as c executable. I had to specify a main function.
If I take a look at the main function, this is what it looks like. I have to include the header files. And then in the main function, it's very simple. All I do is I call the initialize, I call the entry point function, and then I call the terminate, and that's all I do. So let's go back out to the project and build. So when I click on build, this will actually generate C code from the MATLAB code, and then once it's done that it will compile that main.C file. And when it's done that, it will give me an executable in my current directory which I can run. It is also necessary to specify the location of that main.C file just in this more settings tab under the same custom code section I showed you earlier. So the code generation is done. If I go back out here to my current folder, you will see a video stabilize.EXC. Let me open that outside MATLAB. And there you have that same little stabilization application. If you want to work with Simulink, what we have is a MATLAB function block in Simulink. So in Simulink, we've got this MATLAB function block.
You can incorporate MATLAB code, and when Simulink runs, Simulink will actually convert this MATLAB code to C code and turn it into a library so it actually runs faster in the Simulink world. So remember when we had these two options—I showed you these two options at the start, and what we were talking about was MATLAB Coder. Well, let me just briefly discuss the MATLAB Compiler now. So basically, MATLAB Compiler also allows you to share applications and allows you to create EXEs, DLLs, you can also create things like Excel ad-ins, and Java classes. And the nice thing about MATLAB Compiler is that it actually supports pretty much all of the MATLAB language, most of the MATLAB language and toolboxes. That means you don't have to make that many changes at all. But as I said before, the downside is that it also requires a MATLAB Compiler runtime engine, and while this is a royalty free deployment, it does mean that these compiled applications will only run on platforms that can run MATLAB, because MATLAB Compiler does not give you generic NCC code.
What it does is it basically writes a wrapper around your code and compiles it into a form that can be called from the MCR. So if you're thinking about what option you should take, you've got to think about what your requirements are. So for MATLAB coder, it will give you portable and readable C source code. MATLAB Compiler will just give you the executable or some shared library. MATLAB Coder only supports a subset of the MATLAB language and some toolboxes. MATLAB Compiler, on the other hand, pretty much supports the majority of MATLAB's functionality and language. MATLAB Coder doesn't require a runtime. It's just generic C code which you can take away and compile, whereas MATLAB executables and software libraries created for MATLAB Compiler will require that MATLAB Compilor runtime. But both solutions are royalty free.
Once you've generated the code or once you've generated the libraries, you can do whatever you want with them. I didn't give you an example of a fixed point or an embedded application using MATLAB Coder, but I do have a user story. So this is from VivaQuant, who have developed and validated their embedded devices for ECG sensing. They've used MATLAB as well as our fixed point tools and MATLAB Coder to implement their algorithm onto an arm cortex M-Series processor. And you can see the results here that they actually accelerated the development by 300%. They were able to actually minimize their power and memory and perform much more rigorous testing using this work flow. So let's quickly summarize now. What we showed you here was how you can move from algorithm development to generic NCC code but also how you can rapidly move back and forth between the two and make changes to your algorithm and automatically generate the C code. So in doing so, this really does accelerate your development.
If you think about your traditional workflow here, typically you develop your algorithm, you test it, you convert it to C manually, and then you do much more testing and iterations, and this process in here, that becomes very, very time consuming. When you use automatic C code generation, you get huge time savings, and those time savings can be spent on improving your algorithm and testing your algorithm to make sure that what you deploy is of production quality. So the key takeaways from here-- MATLAB provides a direct path to C code from both floating point and fixed point MATLAB code. It's suitable for applications where you need the source code and a small memory footprint is required, so you can't afford to have a MATLAB Compiler runtime running in the background. And automatic generation helps you accelerate your design iterations and also reduce your verification effort. For more information, you can visit our product page at mathworks.com/products/matlab coder. From here, you can request a trial license. Alternatively, you can speak to your Mathworks account manager to request a trial, or you can contact us directly at this following email address or phone number.
Sélectionner un site web
Choisissez un site web pour accéder au contenu traduit dans votre langue (lorsqu'il est disponible) et voir les événements et les offres locales. D’après votre position, nous vous recommandons de sélectionner la région suivante : .
Vous pouvez également sélectionner un site web dans la liste suivante :
Comment optimiser les performances du site
Pour optimiser les performances du site, sélectionnez la région Chine (en chinois ou en anglais). Les sites de MathWorks pour les autres pays ne sont pas optimisés pour les visites provenant de votre région.