How to write an efficient overloaded subsasgn?

2 次查看(过去 30 天)
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 个评论
Jan Siegmund
Jan Siegmund 2020-5-19
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?

请先登录,再进行评论。

采纳的回答

Jan Siegmund
Jan Siegmund 2020-5-19
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 个评论
James Lebak
James Lebak 2021-10-13
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.

请先登录,再进行评论。

更多回答(0 个)

类别

Help CenterFile Exchange 中查找有关 Construct and Work with Object Arrays 的更多信息

产品


版本

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by