extremely inefficient piece of code ... bug?
이전 댓글 표시
I have two codes that implement exactly the same task:
idx(idx<=0) = 1;
idx(idx>=n) = n-1;
and
if idx <= 0
idx = 1;
elseif idx >= n
idx = n-1;
end
where idx and n are a scalar integer values.
This piece of code is evaluating multiple times (N = 1e6, for example). During profiling of the code, I found very strange inefficiency of the first code, which is about ~ 100-1000x slower than the 2nd one. I use the 1st type of code to get more readable code by avoiding if-else construct, but the overall performance is on R2023a really terrible. See attached test code (test.m).
Is this behavior normal, or is it a BUG?
Please, could you verify this code on other (older) MATLAB releases to see, if the problem is only R2023a related or not?
댓글 수: 24
Bruno Luong
2023년 8월 31일
편집: Bruno Luong
2023년 8월 31일
Why it's a bug? The first code is not efficient since it calls array comparison + logical array + array indexing + array sub assigment. each function have to create intermediate MATLAB array result, decide which branch code it goesn, and perhaps doing some deep duplication of data (?), garbage collector, etc...
Whereas the second code the JIT just do the work as simple as possible.
It is not a mistery or unusual that the first code is inefficient.
To me the first code doesn't look readable at all, it is very missleading for scalar input.
Bruno Luong
2023년 8월 31일
편집: Bruno Luong
2023년 8월 31일
BTW you repeat the uppercase BUG in two places.
Yes idx <= 0 if expressed inside the idexing would call function le that accepts arrays and returns a logical array, even though you have a scalar 1x1 array. It is NOT inside the if conditional test staement. Function le supposes to work on array so doing all kind of fancy stuffs that you don't see behind MATLAB compact syntax.
Michal
2023년 8월 31일
John D'Errico
2023년 8월 31일
편집: John D'Errico
2023년 8월 31일
So only after I wrote my answer explaining why the two are different, do I learn that idx is a scalar. I give up. I cannot read your mind. I've deleted my answer, since it presumed you were using vectors, as the indexing lines only made sense if idx was a vector.
This is not a bug. You are using indexing to do something that is designed to be efficient for vectors, but no vectors were involved.
On a scalar, the simple if test will of course be more efficient. It does not even perform the second test and branch at all if the first branch is executed. AND it has always been that way, although the if test has become more efficient over the years, since they have improved the speed of the parser to write better code internally. Those changes in the parser for efficiency were made mainly almost certainly long before you ever learned MATLAB though.
Bruno Luong
2023년 8월 31일
편집: Bruno Luong
2023년 8월 31일
When I'm lazy I do this
idx = max(min(idx,n-1),1);
or
idx = min(max(idx,1),n-1);
rather than if-else. Never cross my mind to do array logical indexing for scalar.
Strictly speaking this is NOT equivalent to either since your methods let NaN untouched, not mine (and in this case the two above min/max methods return different results for NaN).
When I need efficient code, I use if/else.
Michal
2023년 8월 31일
I was going to suggest something like Bruno posted (but was interupted before I hit submit).
The only thing to watch out for is that this code may not work in edge cases (like NaN, but also with non-integers).
idx=0.5;n=0;
Bruno(idx,n),Michal(idx,n)
idx=1;n=1;
Bruno(idx,n),Michal(idx,n)
function Bruno(idx,n)
idx = max(min(idx,n-1),1);
disp(idx)
end
function Michal(idx,n)
if idx <= 0
idx(true) = 1;
elseif idx >= n
idx(true) = n-1;
else
error('undefined') % always include an else branch
end
disp(idx)
end
Bruno Luong
2023년 8월 31일
This is not a bug it's a feature.
Rik
2023년 8월 31일
Why do you insist on the word bug? A bug is unexpected/undefined/undocumented behavior. Perfomance isn't a bug unless the difference is catastrophic. If the indexing-style took 5 seconds to complete (instead of miliseconds), that would be a bug. Right now it is just behavior you did not expect.
I think the most valuable lesson here is this: write code the way Mathworks engineers expect you to. That way the improvements in the JIT (or Execution Engine, same difference) will benefit your code as well. Your coding style may or may not be intrinsically better or clearer. If you care about optimal performance on a broad range of releases, use the style Matlab expects.
Bruno Luong
2023년 8월 31일
편집: Bruno Luong
2023년 8월 31일
To get it straight the time needed for
idx(idx<=0) = 1;
idx(idx>=n) = n-1;
is about 0.5 microsecond.
Michal
2023년 8월 31일
Bruno Luong
2023년 8월 31일
편집: Bruno Luong
2023년 8월 31일
I don't want to make any point beside giving a more precise timing for those who read with Rik statement 'If the indexing-style took 5 seconds to complete (instead of miliseconds)". It's submicrosecond range.
Michal
2023년 8월 31일
Rik
2023년 8월 31일
For the purposes of my comment microsecond and nanoseconds are the same. My point was that both methods are so fast that it doesn't matter. For one to be slow enough to be classified as a bug, they would have to be unexpectedly slow.
There are actually some recommended methods gathered in some places. There are cheat-sheet pdfs (although I can never find them, nor do I need them anymore) provided by Mathworks.
More interestingly: besides the scattered (and sometimes contradictory) advice in the documentation, there is this thread.
I don't know where in the documentation I would mention that indexing of a scalar is not recommend. Where would you do so?
Bruno Luong
2023년 8월 31일
편집: Bruno Luong
2023년 8월 31일
Don't tell me that you mainly do scalar clipping on your montecarlo simulation.
Rik
2023년 8월 31일
To put into other words what Bruno (probably) meant: this smells like a situation where you should work with arrays and do logical indexing.
Bruno Luong
2023년 8월 31일
Noise interpolation has no sense to start with....
Michal
2023년 8월 31일
Bruno Luong
2023년 8월 31일
Cheese: For the record: My timing figure is directed to Rik's comment, then you continue to draw me in with your justification about your montecarlo simulation, that I initially never ask for. I'm not really interested in knowing the topic to be honest. That's your work not mine. You don't need to attck me with "Especially if you don't know anything about the topic at hand."
채택된 답변
추가 답변 (0개)
카테고리
도움말 센터 및 File Exchange에서 Logical에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!