Why is assignment with RedefinesParen so slow

조회 수: 1 (최근 30일)
LR
LR 2023년 10월 2일
댓글: James Lebak 2023년 10월 3일
I want to make a class that wraps around an array, so I tried matlab.mixin.indexing.RedefinesParen to allow interfacing with the object as if it were an array. I'm finding that assigning to the wrapped array is typically 40-80x slower than regular assignment to an array. Here is a simple test class:
classdef TestCustomParen < matlab.mixin.indexing.RedefinesParen
properties
X
end
methods
function obj = cat(dim,varargin)
obj.X = cat(dim,varargin{:});
end
function sz = size(obj)
sz = size(obj.X);
end
end
methods(Static)
function obj = empty
obj = TestCustomParen;
end
end
methods(Access=protected)
function x = parenReference(obj, indexOp)
x = obj.X(indexOp.Indices{1});
end
function obj = parenAssign(obj,indexOp,varargin)
obj.X(indexOp.Indices{1}) = varargin{1};
end
function n = parenListLength(obj,indexOp,ctx)
n = listLength(obj.X,indexOp(3:end),ctx);
end
function obj = parenDelete(obj,indexOp)
obj.X.(indexOp) = [];
end
end
end
I'm not too concerned with what all the implementations are doing, just focsuing on parenAssign here.
And the timing script:
x = TestCustomParen;
tic
for ind = 1:1e4
x(ind) = rand;
end
toc
y = [];
tic
for ind = 1:1e4
y(ind) = rand;
end
toc
And the result:
Elapsed time is 0.085126 seconds.
Elapsed time is 0.001309 seconds.
(It seems I can't actually run this code in the post)
I also tried a version of this where the arrays are both pre-allocated, and in that case the difference becomes even more dramatic (more than 100x slowdown).
Is this slowdown just due to the overhead of accessing indexOp and opening cells? Is is possible to get this sort of behavior in a performant way? The documentation says overriding subsref is no longer recommended, but would that be faster?

채택된 답변

Matt J
Matt J 2023년 10월 2일
편집: Matt J 2023년 10월 2일
Here is the proper way to time the operations. The difference isn't that big.
x = TestCustomParen;
x.X=rand(500);
y=x.X;
a=rand;
timeit(@()assig(x,a))\timeit(@()assig(y,a)),
ans = 0.8566
timeit(@()Assig(x,a))\timeit(@()Assig(y,a)),
ans = 0.9793
function assig(z,a)
z(1)=a;
end
function Assig(z,a)
z(:)=a;
end
  댓글 수: 12
LR
LR 2023년 10월 2일
편집: LR 2023년 10월 2일
Cool, I'll hit accept on the answer. Thanks both for the info. @James Lebak I'd be grateful if you could indicate if there's been any significant performance improvements to this stuff in 23b. The above tests seem to indicate that going from 23a to 23b and modifying my code from
obj.X(indexOp(1).Indices{1}) = varargin{1};
to
obj.X.(indexOp(1)) = varargin{1};
results in a more than 20x speedup.
James Lebak
James Lebak 2023년 10월 3일
In 23b we made significant improvements to dot-indexing performance. On my machine I see your original code running about 2x faster in 23b versus 23a, and my suspicion is that those improvements are probably the cause.

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

추가 답변 (0개)

카테고리

Help CenterFile Exchange에서 Matrix Indexing에 대해 자세히 알아보기

제품


릴리스

R2023a

Community Treasure Hunt

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

Start Hunting!

Translated by