How to write an efficient overloaded subsasgn?

1 Ansicht (letzte 30 Tage)
Jan Siegmund
Jan Siegmund am 19 Mai 2020
Kommentiert: James Lebak am 13 Okt. 2021
I want to write a class which defines subsasgn. The class holds a numeric value val and the subsasgn should target val only.
I wrote the following test:
function [] = test()
num = 1000;
a = randi([0 255],[1000 num]);
b = Subsasgntest(randi([0 255],[1000 num]));
c = randi([0 255],[1 num]);
tic;
for i = 1:length(c)
a(2,i) = c(i);
end
toc
tic;
for i = 1:length(c)
b(3,i) = c(i);
end
toc
b = b.setKind(1);
tic;
for i = 1:length(c)
b(4,i) = c(i);
end
toc
end
classdef Subsasgntest
properties
val
kind = 0;
end
methods
function obj = Subsasgntest(in)
obj.val = in;
end
function obj = setKind(obj,kind)
obj.kind = kind;
end
function obj = subsasgn(obj,sub,varargin)
%SUBSASGN Subscripted assignment
if(isequal(sub.type,'()'))
if isequal(obj,[])
error('Not yet implemented!');
end
if(isa(varargin{1},'Subsasgntest'))
switch obj.kind
case 0
obj.val = builtin('subsasgn',obj.val,sub,varargin{1}.val);
case 1
obj.val = subsasgn(obj.val,sub,varargin{1}.val);
end
else
switch obj.kind
case 0
obj.val = builtin('subsasgn',obj.val,sub,varargin{1});
case 1
obj.val = subsasgn(obj.val,sub,varargin{1});
end
end
else
error('This is not supported for this class!');
end
end
end
end
Results are;
Elapsed time is 0.000019 seconds.
Elapsed time is 4.477900 seconds.
Elapsed time is 4.449843 seconds.
I know self-written subsasgn can be slow, but 235680x slower? Is there any way to achieve a similar level of optimization as in matlabs standard subsasgn?
This guide tells how to branch for different input subscripts, but not how to write the subsasgn syntx itself: https://www.mathworks.com/help/matlab/matlab_oop/code-patterns-for-subsref-and-subsasgn-methods.html
  1 Kommentar
Jan Siegmund
Jan Siegmund am 19 Mai 2020
Update: I added a third kind of subsasgn:
...
case 2
obj.val(sub.subs{1},sub.subs{2}) = varargin{1}.val;
...
which does not cover all cases, but works for the little example and is much faster:
Elapsed time is 0.028915 seconds.
I think the key here is making matlab realize, that in this call:
obj.val = subsasgn(obj.val,sub,varargin{1}.val);
the rvalue obj.val is equal the lvalue obj.val, so it does not create a temporary obj.val.
Any ideas how I could do this?

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

Jan Siegmund
Jan Siegmund am 19 Mai 2020
I may have a solution but do not know if this covers all cases:
classdef Subsasgntest
properties
val
end
methods
function obj = Subsasgntest(in)
obj.val = in;
end
function obj = subsasgn(obj,sub,varargin)
%SUBSASGN Subscripted assignment
if(isequal(sub.type,'()'))
if isequal(obj,[])
error('Not yet implemented!');
end
if(isa(varargin{1},'Subsasgntest'))
obj.val(sub.subs{:}) = varargin{1}.val;
else
obj.val(sub.subs{:}) = varargin{1};
end
else
error('This is not supported for this class!');
end
end
end
end
  5 Kommentare
Tom DeLonge
Tom DeLonge am 4 Feb. 2021
Alright, thanks!
James Lebak
James Lebak am 13 Okt. 2021
In MATLAB R2021b there is a new way to overload subscripting which has two advantages:
1) It allows the class author to overload only a particular type of indexing, that is, paren, dot, or brace, or some combination of types.
2) It improves the performance of indexing into contained objects.
See the section on 'Modular indexing' here to get started.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (0)

Kategorien

Mehr zu Construct and Work with Object Arrays finden Sie in Help Center und File Exchange

Produkte


Version

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by