Is calling length() as needed slower than storing the value just once in a separate variable?

4 次查看(过去 30 天)
The question really is: are the dimensions of an array stored somewhere on the stack, or does the length() function perform some calculation everytime it is called? I can obviously store the length of some array dimension in a separate variable, and thus, only call length() once, and then just reference the variable wherever I need this integer value. But, sometimes, the code just looks cleaner and clearer when I call length() everytime I need this value.
I am in a position where I am reinitializing a nested for loop for every outer for loop iteration, and I am using length() to define the nested loop's boundaries. But if length() is a function that takes some time everytime its called, it would obviously be more efficient to call length() just once and store its value.
  4 个评论
Stephen23
Stephen23 2020-4-13
编辑:Stephen23 2020-4-13
"I'm wondering if matlab sort of stores this value somewhere in a similar way, or if it actually tries to compute this value by some means."
Both.... Search this forum for "JIT" and be prepared to do a lot of reading.

请先登录,再进行评论。

采纳的回答

dpb
dpb 2020-4-13
编辑:dpb 2020-4-13
Any computation has a finite speed...even memory access alone.
Builtin data types contain a knowledge of the dimensions allocated, yes (else't there would be no error that you just exceeded array bounds in indexing expressions).
I suspect whether the JIT compiler can cache the result of a length() call is minimal at best since one can always redimension silently in MATLAB it would be only verifiably static cases where could be possible and that's (I'm guessing) probably more expensive than the cost.
So, while this is conjecture (I looked a little on Yair's site to see if he had any background info on subject but couldn't find quickly), I think one can be assured that as David says, when you call length it is executed. functions are cached, I suspect the largest overhead with length is the determination of which method to call...try
which -all length
to see how many instantiations there are on your system--this is a fairly plain vanilla install with a limited number of toolboxen and there are 20-some associated with those few toolboxes besides the 10 or so built-in versions.
However, I would still suspect it is unlikely to be the bottleneck in any code of any real complexity unless you've truly got a million of 'em scattered around.
Like always, it's also premature to try to peephole optimize until you have profiled the code to find out where the peformance bottleneck(s) is/(are). You could eliminate 100% of a particular calculation but if that's only a small fraction of the total, you've still gained virtually nothing.
Write clearest code you can first, only if it is shown to be unsatisfactory in performance, then profile and work on those areas. Don't try to outguess...
  3 个评论
Christopher Wong
Christopher Wong 2020-4-13
Thank you, gentlemen. I agree, it is probably, even if only infinitesimally, faster to obtain the array dimension before the loop.
@dpb this is great coding advice in general. I'm always subconsciously trying to balance friendly scripting and performance optimization whilst I write code, but perhaps the performance trade-off of this particular issue is too insignifcant. Or perhaps it isn't, which is where your advice has shone some new light on me - most performance improvements can be made with your gut, without taking any measurements. But this one I am truly unsure, and so, you're right, I shouldn't try to overguess this one, and just write the cleaner script in this case.
Very doubtful that I would notice any peformance decrease if I just called length as needed. Still, the information you guys provided is helpful as rules-of-thumb. In the future, if I find myself in a situation where I need to call length() dozens of times over, I should just call it once and store the value. Maybe it saves me 0.01s and it really isn't all that messy ;)
dpb
dpb 2020-4-14
"I'm always subconsciously trying to balance friendly scripting and performance optimization whilst I write code"
Besides the TMW links Stephen provided, Yair has many hints and much to learn at <tips-for-accelerating-matlab-performance>

请先登录,再进行评论。

更多回答(1 个)

Walter Roberson
Walter Roberson 2020-4-13
function test_speed
foo = zeros(randi(255),randi(255),randi(255));
f1 = @() length(foo);
Lfoo = length(foo);
f2 = @() Lfoo;
N = 256;
t1 = zeros(N,1);
t2 = zeros(N,1);
t3 = zeros(N,1);
t4 = zeros(N,1);
ws = warning('off','MATLAB:timeit:HighOverhead');
cleanme = onCleanup(@() warning(ws));
fprintf('testing length first time\n');
for K = 1 : N; t1(K) = timeit(f1,0); end
fprintf('testing stored length first time\n');
for K = 1 : N; t2(K) = timeit(f2,0); end
fprintf('testing length second time\n');
for K = 1 : N; t3(K) = timeit(f1,0); end
fprintf('testing stored length second time\n');
for K = 1 : N; t4(K) = timeit(f2,0); end
plot([t1,t2,t3,t4])
legend({'length', 'stored', 'length again', 'stored again'})
fprintf('mean length = %g %g\n', mean(t1), mean(t3));
fprintf('mean stored = %g %g\n', mean(t2), mean(t4));
end
You will not get the same results for a script! JIT for functions is different than JIT for a script!
You will not necessarily see the same results for the second run as for the first run! Historically, the first run of any timing test has been notably slower than the second run of the timing test, and that has been on a per line basis, not just a first-time overhead for the very first run. Historically, t3 and t4 would have been notably faster than t1 and t2, even though they invoke exactly the same code.
With time differences as small as these, you have to be very careful about exactly what you are timing.

类别

Help CenterFile Exchange 中查找有关 Loops and Conditional Statements 的更多信息

产品


版本

R2019b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by