Avoid evaluation in vectorised conditional expressions

조회 수: 1 (최근 30일)
Christian B
Christian B 2023년 1월 31일
댓글: Walter Roberson 2023년 1월 31일
Dear community,
It is well known how to vectorise for-loops that contain if-conditions, see, e.g. https://de.mathworks.com/matlabcentral/answers/17737-how-can-i-vectorize-function-with-if-statement, resulting in functions like (taken from above link):
function result = myfunc(x);
result = zeros(size(x));
idx1 = x>3;
idx2 = (x.^2 + x) > 9;
result(idx1) = 1;
result(idx2) = 2;
result(~(idx1|idx2)) = 3;
This principle works very well. However, in my case, result(idx1) and result(idx2) would be quite lengthy and expensive expressions. The problem is that both expressions are always evaluated for the entire input x, no matter if idx1 or idx2 are true or not. My question is if there is a way to avoid the evaluation of, e.g., the right hand side of result(idx2) if idx2 is false. Just as it would be in an if-elseif-construct.
I'm aware of alternative constructs with arrayfun or a "classical" for-loop with nested if-elseif-construct, but these workarounds are not efficient.
Any help is much appreciated, thank you!

채택된 답변

Torsten
Torsten 2023년 1월 31일
이동: Torsten 2023년 1월 31일
If your right-hand side contains expressions with x, you must replace x by x(idx1) resp. x(idx2).
  댓글 수: 2
Christian B
Christian B 2023년 1월 31일
Thanks for the answer. I should have specified the code in the question. I know about the indexing, as for example in
function result = myfunc(x)
result = zeros(size(x));
idx1 = x==2;
idx2 = x>2;
result(idx1) = sin(x(idx1));
result(idx2) = cos(x(idx2));
end
Due to the Matlab Profiler, each line is always executed. So my misunderstanding was that (here) also sin and cos on the right hand sides are evaluated for the entire input vector x and the false indices are just dropped. However, some further checks showed me that the right hand sides are only evaluated for the respective indices, which is the behaviour I was asking for.
Thanks!
Walter Roberson
Walter Roberson 2023년 1월 31일
For future reference:
There are situations in which the cost of extracting a subset of data, computing with it, and expanding the results back into the appropriate locations, can exceed the savings of not performing the operation on the entire matrix.
sin() is implemented using hardware instructions. Those are potentially slower than a conditional memory move, but since the conditional move is going to need to be a loop at some level (you cannot know the relative offset without having evaluated all previous tests), sometimes it can be faster to just do the instruction and ignore or overwrite the results later. sin applied over a block of consecutive locations and be unrolled into several SIN hardware instructions in a row.

댓글을 달려면 로그인하십시오.

추가 답변 (0개)

Community Treasure Hunt

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

Start Hunting!

Translated by