Skip to Main Content Skip to Search
File Exchange
MATLAB Newsgroup
Link Exchange
  Blogs  
 Contest 
MathWorks.com

Loren on the Art of MATLAB

April 12th, 2006

MATLAB Programming Practices

I'm feeling pensive today as I participate in development activities at MathWorks for Release 2006b. We are following a 6-month release schedule and the naming convention for the twice yearly releases is year followed by first "a" and then "b". This schedule requires discipline on many fronts, including for developers. Over the years, we have encountered some truisms for us regarding code we ship; they are are not all novel in the industry and have served us and our users well.

Contents

Good Programming Practices, Some Specific to MATLAB

People develop their own best practices over time, ranging from cosmetic issues to ones affecting the behavior or viability of a program. Tools such as mlint, which I wrote about here, provide one way to audit code. You can see more examples of code metrics used on MATLAB Central's File Exchange.

At MathWorks, we have several, sometimes competing, goals with respect to our code, and especially to M-files that we ship. Here's a list of some ideas that work well for us.

  • Minimize the amount of code you write.
  • Minimize the complexity of the code you write.
  • Avoid speculative generality.
  • Avoid premature optimization.
  • Use components as they were designed to be used.
  • Create functions instead of scripts.
  • Make the code general and document ranges and exceptions.
  • Write and run tests.

MATLAB Trade-Offs

A classic trade-off in MATLAB is time versus memory. You can often vectorize code, but in doing so, you add an additional memory burden.

On the MATLAB newsgroup, we've seen discussions about avoiding repmat and we also had similar discussions in these two blog articles: Scalar Expansion and More and More on expansion: arrayfun. What's the reason? It's because, in order to fully vectorize the code, potentially really large intermediate arrays are created, used, and tossed away.

When Steve Eddins, author of Steve on Image Processing, worked on the function inpolygon, he found that he could fully vectorize the code. If he did so, though, there were plenty of realistic cases using it that caused MATLAB to run out of memory. To avoid this, Steve chunked up the code, and you can see this comment:

dbtype inpolygon 51:52
51    % Choose block_length to keep memory usage of vec_inpolygon around
52    % 10 Megabytes.

Within the 10Mb memory limits, the code is vectorized (see lines 53:83, from which the subfunction vec_inpolygon is called).

Use the MATLAB Profiler to Find Bottlenecks

I remember another case from 1988 or 1989, near the time when we introduce MEX-files. It illustrates well for me why I should not rely on my intuition, but I should instead use tools to help me measure the actual effects I am hoping to influence. Despite by best efforts to think through problems as thoroughly as I think I can, I often find that, left to my own devices, I focus on the central issues, and it's often the more tangential ones that surprisingly consume the CPU cycles. So, much better if I measure than guess.

We were trying to speed up function functions, without the benefit of the MATLAB profiler. So we did experiments, first converting one of the ode solvers to C, and then turning the actual equations into C. Using only the MEX-function for the solver bought us a factor of 2. Using only the MEX-function for the equations also bought us a factor of 2. Can you guess what using both MEX-files simultaneously bought for us? You might guess a factor of 4. That's not what we found. We found a factor of 15 instead.

MATLAB has changed a lot since version 3, so what was true then with respect to performance is not, in detail, relevant today.

What Coding Principles Matter to You?

I've barely scratched the surface of what characteristics of your code might be the most important in various situations. What's important to you? Tell me here.


Published with MATLAB® 7.2

8 Responses to “MATLAB Programming Practices”

  1. John O'Leary replied on :

    From your principles:

    Avoid speculative generality.

    Make the code general and document ranges and exceptions.

    What is the difference between general code and “speculative generality”? Is there a line between the two?

  2. Loren replied on :

    I think there is sometimes a gray area, actually. But there is a real difference in some cases. Here’s a couple of examples.

    Extend a function that works correctly for “small” input to the rest of the real line. What is “small”? Do you check for it and error if the input doesn’t meet the criteria? If so, you are okay. If you think you might need it later for a different range, it’s best to make that clear with documentation and an error, until you upgrade it. In this case, e.g., bessel functions with large input, I would prefer to make the function work correctly from the start. Then I can always rely on it. To me, this fits more closely into Make the code general and document ranges and exceptions.

    Extend a function that works for real input onto the complex plane. And spend lots of time figuring out how to do the analytic continuation and defining appropriate branch cuts so inputs can be anywhere in the complex plane. Again, either error and document carefully, or implement. Is it worth implementing? Can you imagine using it that way, or is it just cool? If you don’t really see your way clear to a definite use case, even if you won’t need it for that right away, it might not be worth the effort right now. To me, this one fits more closely into Avoid speculative generality.

  3. Felloweskraft replied on :

    This may be obvious, but I’ve always found it easiest to work in dimensionless units for as much of a program as possible.

  4. Brad Phelan replied on :

    Test driven development is one key to good software development. Write tests early and often and less problems arrive later. When coding in C under Linux/LynxOS I use “Check”

    http://check.sourceforge.net.

    When coding under Matlab I found no decent testing framework so I wrote my own.

    One of the things I find about writing tests is not only do they provide regression error protection but they help me understand my own code and designs. I may come back to some obscure corner of an API I have written after a month and forget exactly how I intended it to be used. If I have a test case for it then more often than not it makes clear to me what I was up to.

    http://xtargets.com/cms/Tutorials/Matlab-Programming/MUnit-Matlab-Unit-Testing.html

    which you can download and use. It’s simple to get started with and integrates into the Matlab web browser for report generation and interactive testing.

  5. sana replied on :

    i want some help in numerical analysis,if u can help me out with the Bessel’s central diffrence formula using MATLAB

  6. Loren replied on :

    Please see this message from Steve’s blog: http://blogs.mathworks.com/steve/category/blog-policies/

  7. Oktay replied on :

    Hello!

    I have a function I wrote that is very similiar to FREAD in terms of input arguements:

    A = FREAD(FID,SIZE,PRECISION,SKIP,MACHINEFORMAT)

    Here, SIZE and SKIP arguements are optional that is the function shows an intelligent behaviour when we type

    a = fread(fid,precision,machineformat)

    My function also has these optional arguements depending on the type of inputs. So, can you suggest basic methods/guidelines for distributing the input arguments properly, and a robust error checking inside the m-file?

    Thank you!

    Oktay

  8. Loren replied on :

    Oktay-

    I recommend you look at M-files we ship with MATLAB that seem similar in the idea of the extra inputs and see how the error checking is done there. One way that’s newer is to use an inputParser object for at least part of the work. Another tool is the function assert.

    –Loren

Leave a Reply


Loren Shure works on design of the MATLAB language at The MathWorks. She writes here about once a week on MATLAB programming and related topics.

  • Ulla Vainio: That error bar width adjustment was extremely useful and I would never have figured it out myself....
  • Peter Perkins: Jessee, there is a property that you can use to tag variables with units. For example, >> load...
  • Jessee: I could potentially see myself using dataset for casually looking at data, but from an application standpoint...
  • Loren: Oktay- It very much depends on the details of the calculations you are doing. Vectorization can sometimes...
  • Oktay: Hello, Is there any significant difference between using: - Vectorization inside a subfunction - Benefiting...
  • Loren: Clare- Yes, sum can sum a double vector: x = [.3 .4 pi/3] y = sum(x) x = 0.3 0.4 1.0472 y = 1.7472 You must...
  • Clare J: R2007a - Student Version When I use sum to sum a vector of type double I get this error message: ???...
  • Sarah Zaranek: Hi Jacob, Sorry about the slow response. You are correct that the code would be slower without the...
  • Navaneethan Santhanam: Thanks a lot, Loren! That worked perfectly.
  • Mike N: Should it be OK to use “persistent 221; variables in a deployed application? What if I have two...

These postings are the author's and don't necessarily represent the opinions of The MathWorks.

Related Topics