MATLAB Answers

0

Maximizing code interpretability while minimizing computational cost.

Asked by D. Plotnick on 18 Jun 2018
Latest activity Commented on by Jan
on 23 Jun 2018
Hello, I have a question about whether there is a current method to maximize code readability while minimizing computational complexity.
For example, the code:
Th = atan(x./y);
is slower than
x = atan(x./y);
Provided that you do not need to retain the variable x, this method is faster ( due to memory access issues as far as I understand ). In addition, if the memory footprint of variables is a concern, this will simply overwrite the values of x rather than creating a new variable to occupy memory.
However, the latter method reduces code interpretability by obscuring the fact that, in this example, I am clearly changing to an angle using the tangent function. So, how do I balance these two apparently competing issues?
So far I have come up with four options:
For the generic operation
newVar = myFun(oldVar)
where newVar operates in the same way as oldVar = myFun(oldVar), but with a new name
(1) Rename the variable using intermediaries. Maybe using oldVar = myFun(oldVar); newVar = oldVar; clear oldVar; However, this lacks a certain amount of elligence and just does not sit well with me. Maybe it is the only way.
(2) Rename the variable directly. I think this gets me in hot water with the 'no dynamic variable names' credo, if it's even possible, but there is a 'rename variable' option within the workspace pane. However, even if there is a mechanism to rename the variable, similarly to the above idea it also does not necessarily increase code interpretability/compactness.
(3) Create a custom class so that the variables are handles referencing the same object in memory. oldVar and newVar point to the same object in the same way that newVar = oldVar does not create a new copy in memory until newVar is modified. Drawback: I think that will ruin a lot of codes that utilize class requirements, such as requiring inputs be 'double'. I also do not know if this will actually reduce memory loading, as I am still a novice at handle objects vs. data objects.
(4) Implement a 'description' for each variable. This does not currently exist, afaik, but would be useful more generically. If there is an initial description of 'x' that is 'distance' and then after x=atan(x) you can change the description to 'angle', that would extremely helpful for many applications. This could also be used for storing units (distance in feet vs. distance in meters). I could see creating custom classes that include descriptions in their properties, but again I think this would break class requirements for many standard functions. Maybe make them a child of the class 'double'?
(5) Suck it up and do it all with code comments.
(6) Magic, or programming tricks significantly advanced as to be indistinguishable from magic.
========TLDR=======
How do I maximize code interpretability while minimizing memory/computational cost for operations of the form x = fun(x) VS. y = fun(x).
Cheers, Dan
PS. Below is a code that lets you see the slight speed advantage to writing to the same variable. Of bigger concern to me is the memory footprint. This is taken from the article linked above and here .
N = 3e3;
x = randn(N);
tic
y = x*1.2;
toc
tic
x = x*1.2;
toc

  0 Comments

Sign in to comment.

1 Answer

Answer by OCDER
on 18 Jun 2018
 Accepted Answer

The debate of code readability vs performance has been going on for a long time. Your #5 is probably the best choice : document these changes with comments to preserve code readability and get that speed boost for in-place calculations.
If performance is an issue, then you'll probably have to use every trick possible to boost it at the price of code readability. On the other hand, if you're speeding things up by only 100 ms, maybe not worth sacrificing code readability for a small speed boost.
There are other ways for better performances: parallel computing and MEX (c++) codes. Use the profiler to find the bottleneck, and then see if you really need to speed things up with MEX/parfor.

  7 Comments

+1. Exhaustive comments are a good idea in every case. Names of variables can and should carry the information about the meaning also, see this bad example:
x = rand(1, 100);
m = std(x);
s = mean(x); % Brrrrr
But if a piece of code is identified as bottleneck, the programmer has to decide, if the loss of meaning in
x = atan(x ./ y);
is worth or not to win a microsecond. With a clear comment, this does not confuse anybody:
% Before: x is distance, After: x is the angle
% x is redefined to save time.
x = atan(x ./ y);
Not perfectly nice, but this is the nature of optimized code. Using a object inherited from the handle class will cause a lot of overhead and the additional information is available at run time only.
So my suggestion is to clarify the meaning by exhaustive comments. When the name of the variable is "x" and not "distanceOfCarBeforePointXIsPassed", changing the meaning should be okay.
Thanks all. Helpful thoughts, and it really does just sound like 'comment comment comment'.
@Jan, I am amused by your 'distanceOfCarBeforePointXIsPassed' variable. My first prototype of any complicated code inevitably turns into something like: d3_modi = exp(d2); dd3_modi2_test = exp(1i*d2ppp), with absolutely no context as I slowly make variables longer and longer. Its only on the later pass that everything goes over to the other extreme: distanceToHanger = exp(distanceFromBecon2); or something like that.
@Daniel: I'm using short prefixes and suffixes as conventions for the names:
  • nXYZ: Integer number, must be ≥ 0
  • iXYZ: integer counter, must be ≥ 0
  • aXYZ: one element copied from an array for faster or nicer access
  • dXYZ: a scalar floating point distance
  • XYZ_tmp: a temporary variable which is used inside the current block of code only. "Current block" means, that it cannot be used, when the auto-indentation is decreased.
  • XYZfid: File identifier
  • XYZ_p: Persistent variable
  • XYZ_L: Local function (function in the same M-file)
  • Starting with a lower-case character: Used inside the current function only. Starting with uppercase letter: Delivered as output also.
  • XyzH: Graphics handle
  • XyzC: Cell array
  • isXYZ: Logical index
Then your code line would be:
dHanger = exp(dBecon2);
This is not clear without knowing the conventions, but if you are familiar with them, the readability is improved.

Sign in to comment.