How to write an efficient overloaded subsasgn?

2 vues (au cours des 30 derniers jours)
Jan Siegmund
Jan Siegmund le 19 Mai 2020
Commenté : James Lebak le 13 Oct 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 commentaire
Jan Siegmund
Jan Siegmund le 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?

Connectez-vous pour commenter.

Réponse acceptée

Jan Siegmund
Jan Siegmund le 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 commentaires
Tom DeLonge
Tom DeLonge le 4 Fév 2021
Alright, thanks!
James Lebak
James Lebak le 13 Oct 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.

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Construct and Work with Object Arrays dans Help Center et File Exchange

Produits


Version

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by