{"id":33,"date":"2006-04-12T10:39:37","date_gmt":"2006-04-12T15:39:37","guid":{"rendered":"https:\/\/blogs.mathworks.com\/loren\/?p=33"},"modified":"2018-01-08T16:11:48","modified_gmt":"2018-01-08T21:11:48","slug":"matlab-programming-practices","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/loren\/2006\/04\/12\/matlab-programming-practices\/","title":{"rendered":"MATLAB Programming Practices"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <introduction>\r\n      <p>I'm feeling pensive today as I participate in development activities at MathWorks for Release 2006b.  We are following a <a href=\"https:\/\/www.mathworks.com\/products\/new_products\/release_model.html\">6-month release schedule<\/a> and the naming convention for the twice yearly releases is year followed by first \"a\" and then \"b\".  This schedule requires\r\n         discipline on many fronts, including for developers.  Over the years, we have encountered some truisms for us regarding code\r\n         we ship; they are are not all novel in the industry and have served us and our users well.\r\n      <\/p>\r\n   <\/introduction>\r\n   <h3>Contents<\/h3>\r\n   <div>\r\n      <ul>\r\n         <li><a href=\"#1\">Good Programming Practices, Some Specific to MATLAB<\/a><\/li>\r\n         <li><a href=\"#2\">MATLAB Trade-Offs<\/a><\/li>\r\n         <li><a href=\"#4\">Use the MATLAB Profiler to Find Bottlenecks<\/a><\/li>\r\n         <li><a href=\"#5\">What Coding Principles Matter to You?<\/a><\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <h3>Good Programming Practices, Some Specific to MATLAB<a name=\"1\"><\/a><\/h3>\r\n   <p>People develop their own best practices over time, ranging from cosmetic issues to ones affecting the behavior or viability\r\n      of a program.  Tools such as <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/mlint.html\"><tt>mlint<\/tt><\/a>, which I wrote about <a href=\"https:\/\/blogs.mathworks.com\/loren\/2006\/03\/15\/m-lint-in-r2006a\/\">here<\/a>, provide one way to audit code.  You can see more examples of code metrics used on MATLAB Central's <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/\">File Exchange<\/a>.\r\n   <\/p>\r\n   <p>At MathWorks, we have several, sometimes competing, goals with respect to our code, and especially to M-files that we ship.\r\n      Here's a list of some ideas that work well for us.\r\n   <\/p>\r\n   <div>\r\n      <ul>\r\n         <li>Minimize the amount of code you write.<\/li>\r\n         <li>Minimize the complexity of the code you write.<\/li>\r\n         <li>Avoid speculative generality.<\/li>\r\n         <li>Avoid premature optimization.<\/li>\r\n         <li>Use components as they were designed to be used.<\/li>\r\n         <li>Create functions instead of scripts.<\/li>\r\n         <li>Make the code general and document ranges and exceptions.<\/li>\r\n         <li>Write and run tests.<\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <h3>MATLAB Trade-Offs<a name=\"2\"><\/a><\/h3>\r\n   <p>A classic trade-off in MATLAB is time versus memory. You can often vectorize code, but in doing so, you add an additional\r\n      memory burden.\r\n   <\/p>\r\n   <p>On the MATLAB <a>newsgroup<\/a>, we've seen discussions about avoiding <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/repmat.html\"><tt>repmat<\/tt><\/a> and we also had similar discussions in these two blog articles: <a href=\"https:\/\/blogs.mathworks.com\/loren\/2006\/02\/22\/scalar-expansion-and-more-take-2\/\">Scalar Expansion and More<\/a> and <a href=\"https:\/\/blogs.mathworks.com\/loren\/2006\/03\/01\/more-on-expansion-arrayfun\/\">More on expansion: arrayfun<\/a>.  What's the reason?  It's because, in order to fully vectorize the code, potentially really large intermediate arrays are\r\n      created, used, and tossed away.\r\n   <\/p>\r\n   <p>When <a href=\"https:\/\/blogs.mathworks.com\/images\/eddins.jpg\">Steve Eddins<\/a>, author of <a href=\"https:\/\/blogs.mathworks.com\/steve\/\">Steve on Image Processing<\/a>, worked on the function <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/inpolygon.html\"><tt>inpolygon<\/tt><\/a>, he found that he could fully vectorize the code.  If he did so, though, there were plenty of realistic cases using it that\r\n      caused MATLAB to run out of memory.  To avoid this, Steve chunked up the code, and you can see this comment:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">dbtype <span style=\"color: #A020F0\">inpolygon<\/span> <span style=\"color: #A020F0\">51:52<\/span><\/pre><pre style=\"font-style:oblique\">\r\n51    % Choose block_length to keep memory usage of vec_inpolygon around\r\n52    % 10 Megabytes.\r\n\r\n<\/pre><p>Within the 10Mb memory limits, the code <b>is<\/b> vectorized (see lines 53:83, from which the subfunction <kbd>vec_inpolygon<\/kbd> is called).\r\n   <\/p>\r\n   <h3>Use the MATLAB Profiler to Find Bottlenecks<a name=\"4\"><\/a><\/h3>\r\n   <p>I remember another case from 1988 or 1989, near the time when we introduce <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/mex.html\">MEX-files<\/a>. It illustrates well for me why I should not rely on my intuition, but I should instead use tools to help me measure the\r\n      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.\r\n   <\/p>\r\n   <p>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.\r\n       Using only the MEX-function for the equations also bought us a factor of 2.  Can you guess what using both MEX-files simultaneously\r\n      bought for us?  You might guess a factor of 4.  That's not what we found.  We found a factor of 15 instead.\r\n   <\/p>\r\n   <p>MATLAB has changed a lot since version 3, so what was true then with\r\nrespect to performance is not, in detail, relevant today.\r\n   <\/p>\r\n   <h3>What Coding Principles Matter to You?<a name=\"5\"><\/a><\/h3>\r\n   <p>I've barely scratched the surface of what characteristics of your code might be the most important in various situations.\r\n      What's important to you?  Let me know.\r\n   <\/p>\r\n   <p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br>\r\n      Published with MATLAB&reg; 7.2<br><\/p>\r\n<\/div>\r\n<!--\r\n##### SOURCE BEGIN #####\r\n%% MATLAB Programming Practices\r\n% I'm feeling pensive today as I participate in development activities at\r\n% MathWorks for Release 2006b.  We are following a \r\n% <https:\/\/www.mathworks.com\/products\/new_products\/release_model.html 6-month release schedule>\r\n% and the naming convention for the twice yearly releases is year followed\r\n% by first \"a\" and then \"b\".  This schedule requires discipline on many\r\n% fronts, including for developers.  Over the years, we have encountered\r\n% some truisms for us regarding code we ship; they are are not all novel in\r\n% the industry and have served us and our users well. \r\n\r\n%% Good Programming Practices, Some Specific to MATLAB\r\n% People develop their own best practices over time, ranging from cosmetic\r\n% issues to ones affecting the behavior or viability of a program.  Tools\r\n% such as\r\n% <https:\/\/www.mathworks.com\/help\/matlab\/ref\/mlint.html |mlint|>,\r\n% which I wrote about <http:?p=24 here>,\r\n% provide one way to audit code.  You can see more examples of code metrics\r\n% used on MATLAB Central's <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/ File Exchange>.\r\n%\r\n% At MathWorks, we have several, sometimes competing, goals with respect to\r\n% our code, and especially to M-files that we ship.  \r\n% Here's a list of some ideas that work well for us.\r\n%\r\n% * Minimize the amount of code you write.\r\n% * Minimize the complexity of the code you write.\r\n% * Avoid speculative generality.\r\n% * Avoid premature optimization.\r\n% * Use components as they were designed to be used.\r\n% * Create functions instead of scripts.\r\n% * Make the code general and document ranges and exceptions.\r\n% * Write and run tests.\r\n%\r\n%% MATLAB Trade-Offs\r\n% A classis trade-off in MATLAB is time versus memory. You can often\r\n% vectorize code, but in doing so, you add an additional memory\r\n% burden.  \r\n%\r\n% On the MATLAB\r\n% <http:\/\/.shtml newsgroup>,\r\n% we've seen discussions about avoiding \r\n% <https:\/\/www.mathworks.com\/help\/matlab\/ref\/repmat.html |repmat|>\r\n% and we also had similar discussions in these two blog articles:\r\n% <http:?p=23 Scalar Expansion and More> and\r\n% <http:?p=25 More on expansion: arrayfun>.  What's the reason?  It's\r\n% because, in order to fully vectorize the code, potentially really large\r\n% intermediate arrays are created, used, and tossed away.\r\n%\r\n% When <https:\/\/blogs.mathworks.com\/images\/eddins.jpg Steve Eddins>, author\r\n% of <https:\/\/blogs.mathworks.com\/steve\/ Steve on Image Processing>, worked\r\n% on the function\r\n% <https:\/\/www.mathworks.com\/help\/matlab\/ref\/inpolygon.html |inpolygon|>,\r\n% he found that he could fully vectorize the code.  If he did so, though,\r\n% there were plenty of realistic cases using it that caused MATLAB to run\r\n% out of memory.  To avoid this, Steve chunked up the code, and you can see\r\n% this comment:\r\ndbtype inpolygon 51:52\r\n%%\r\n% Within the 10Mb memory limitation, the code *is* vectorized.\r\n%% Use the MATLAB Profiler to Find Bottlenecks\r\n% I remember another case from 1988 or 1989, near the time\r\n% when we introduce <https:\/\/www.mathworks.com\/help\/matlab\/ref\/mex.html MEX-files>. \r\n% It illustrates well for me why I should not rely on my intuition, but I\r\n% should instead use tools to help me measure the actual effects I am\r\n% hoping to influence.\r\n%\r\n% We were trying to speed up\r\n% <https:\/\/www.mathworks.com\/access\/helpdesk\/help\/techdoc\/math\/funfun.html#941444 function functions>,\r\n% without the benefit of the MATLAB\r\n% <https:\/\/www.mathworks.com\/access\/helpdesk\/help\/techdoc\/matlab_env\/tuning13.html#17018 profiler>.\r\n% So we did experiments, first converting one of the\r\n% <https:\/\/www.mathworks.com\/access\/helpdesk\/help\/techdoc\/math\/diffeq.html ode solvers>\r\n% to C, and then turning the actual equations into C.  Using only the\r\n% MEX-function for the solver bought us a factor of 2.  Using only the\r\n% MEX-function for the equations also bought us a factor of 2.  Can you\r\n% guess what using both MEX-files simultaneously bought for us?  You might\r\n% guess a factor of 4.  That's not what we found!  We found a factor of 15\r\n% instead.\r\n%\r\n% MATLAB has changed a lot since version 3, so what was true then for those\r\n% versions of functions is likely not true at all now.\r\n%% What Coding Principles Matter to You?\r\n% I've barely scratched the surface of what characteristics of your code\r\n% might be the most important in various situations. What's important to\r\n% you?  Tell me <http:?p=33#Respond here>.\r\n\r\n\r\n\r\n\r\n##### SOURCE END #####\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   \r\n      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... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/loren\/2006\/04\/12\/matlab-programming-practices\/\">read more >><\/a><\/p>","protected":false},"author":39,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[16],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/33"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/users\/39"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/comments?post=33"}],"version-history":[{"count":5,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/33\/revisions"}],"predecessor-version":[{"id":2604,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/33\/revisions\/2604"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/media?parent=33"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/categories?post=33"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/tags?post=33"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}