Unexpected slowdown using () indexing
古いコメントを表示
format long g
NULL = 0; counter = 0; start = tic; while toc(start) < 10; NULL; counter = counter + 1; end; counter/10
NULL = @()0; counter = 0; start = tic; while toc(start) < 10; NULL(); counter = counter + 1; end; counter/10
NULL = 0; counter = 0; start = tic; while toc(start) < 10; NULL(); counter = counter + 1; end; counter/10
NULL = 0; counter = 0; start = tic; while toc(start) < 10; NULL(1); counter = counter + 1; end; counter/10
Observe that referring to a variable in a loop can iterate millions of time per second, and executing an anonymous function to retrieve a value is (fewer) millions of times per second -- but that taking a plain scalar and using empty () to dereference it slows down to the hundreds-of-thousands range (roughly a factor of 7). But we can see that using (1) indexing is slightly slower than just using the variable with no () but is still comparable to no indexing in speed.
So there is something about using the empty index on a scalar that invokes much worse performance.
7 件のコメント
Bruno Luong
2023 年 1 月 30 日
編集済み: Bruno Luong
2023 年 1 月 30 日
I didn't know this indexing (empty reference) should return
NULL = 0; NULL();
Is there any doc that describes it? obviously NULL() returns the same as NULL. What is the use case of empty indexing (beside slowing down MATLAB)?
Walter Roberson
2023 年 1 月 30 日
Walter Roberson
2023 年 1 月 30 日
Walter Roberson
2023 年 1 月 30 日
Bruno Luong
2023 年 1 月 31 日
編集済み: Bruno Luong
2023 年 1 月 31 日
I think the only justification existing of this strange empty indexing is when using with comma list that reduces to an empty cell
A=magic(2);
c=cell(0);
Aemptyidexing = A(c{:}) % equal to A() i.e. to A
%
But to me the value of A() == A is just an arbitrary design choice. I don't see any logical pattern with what come when the comma list is not empty.
To me this "feature" can be ignored; for good reason.
Personally I would prefer an error is thrown when empty indexing is encountered.
回答 (1 件)
James Lebak
2023 年 2 月 1 日
3 投票
Paren-reference in many cases creates a copy. This is expected behavior.
NULL(1) is nearly as fast as NULL on a scalar because it's been specially optimized. NULL() is indexing with no indices (empty paren-reference). We allow this syntax because when NULL is a function handle, NULL() means to call the function with no arguments. But we don't consider it common usage, and we haven't optimized it. As you observed, it therefore creates an expensive copy. We could consider optimizing it in a future release. If you have a need for this operation to be performant we'd be interested to hear of it.
5 件のコメント
Bruno Luong
2023 年 2 月 1 日
"We could consider optimizing it in a future release. If you have a need for this operation to be performant we'd be interested to hear of it."
Nah you have better thing to do IMO.
James Lebak
2023 年 2 月 2 日
Regarding end: what's special-cased is the scalar indexing into a scalar. Any of 1:n, 1:end, 1:1 are treated as a vector index into a scalar which takes the path through the most general but overall slowest code. NULL(end) is faster than NULL(1:end) because after end resolves it's a scalar index.
I was surprised at the difference between referencing a scalar variable in a script versus a function. More optimizations are enabled in functions than in scripts and so our expectation, as you said, is that functions are faster. It turns out that the case of assigning a whole variable to another variable is faster in a script because it reduces to a trivial pointer copy. I still think the guidance that functions are faster is generally correct, because these kind of operations should not be a high percentage of the overall execution time for most functions.
[You may ask, wait, what's being assigned? In this case, because there's no right-hand side, there's an implicit assign to ans, in both a script and a function. But I tried it with an explicit assignment to a left-hand side variable too, and it was faster in the script in that case as well.]
Walter Roberson
2023 年 2 月 2 日
James Lebak
2023 年 2 月 2 日
Among other things, in functions we're handling an uninitialized LHS differently than we do in scripts. We may be able to do it faster than we are now. Like the empy paren-reference case, I don't think this is a very high priority case though.
カテゴリ
ヘルプ センター および File Exchange で Performance and Memory についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!