How to write an efficient overloaded subsasgn?

2 visualizaciones (últimos 30 días)
Jan Siegmund
Jan Siegmund el 19 de Mayo de 2020
Comentada: James Lebak el 13 de Oct. de 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 comentario
Jan Siegmund
Jan Siegmund el 19 de Mayo de 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?

Iniciar sesión para comentar.

Respuesta aceptada

Jan Siegmund
Jan Siegmund el 19 de Mayo de 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 comentarios
Tom DeLonge
Tom DeLonge el 4 de Feb. de 2021
Alright, thanks!
James Lebak
James Lebak el 13 de Oct. de 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.

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre Construct and Work with Object Arrays en Help Center y File Exchange.

Productos


Versión

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by