octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

FYI: subasgn argument optimization


From: Jaroslav Hajek
Subject: FYI: subasgn argument optimization
Date: Thu, 13 Aug 2009 16:41:45 +0200

hi all,

this originated as a proof-of-concept, but eventually I managed to put
it in a usable state, so I pushed it to get possible feedback.
http://hg.savannah.gnu.org/hgweb/octave/rev/e79470be3ecb

Summary & background:
with this patch, Octave will attempt to optimize certain calls to
overloaded subsasgn (indexed assignment) m-file methods for user
classes.
Specifically, when A is a value of user class, then doing
A(I) = X
actually translates to
A = subsasgn (A, substruct("()",{I}), X);

The problem with the latter is that inherently, multiple copies of A
will exist at the time of the call (caller's scope and callee's scope,
as well as an internal copy),
thus an attempt to modify the copy inside subsasgn will cause a copy
to unshare the data.
With the new patch, when
A(I) = X
is executed, and the corresponding overloaded subsasgn method is
declared like this:

function obj = subsasgn (obj, subs, val)

then Octave will try to be smart and ignore the copy still stored
inside A; this will allow the method to modify the object's fields
without a redundant copy.

The effect can be demonstrated by the following benchmark, using the
polynomial class from Octave examples.

p = polynomial ([1:2e6]); # a big polynomial
tic;
for i = 0:50
  p{i} = i;  # change i-th order coefficient.
endfor
toc

with a recent version, I get:

Elapsed time is 0.485235 seconds.

with the new patch, the result is:

Elapsed time is 0.0172369 seconds.

while the first version copies 2 million numbers in each cycle, the
latter avoids it. Another way to observe this is to use system memory
monitor.
For classes storing significant amounts of data, the performance
improvements may be significant.
Of course, another option is to use a handle class, but those are less
Octavish (or Matlabish) and you need to handle multiple references all
yourself.

2 more comments:
1. this doesn't quite solve the problem in its entirety, since a
common practice inside subsasgn methods is to call subsasgn again to
handle the rest of index chain if needed.
However, calling through subsasgn bypasses the optimizations.
2. Since only one physical copy of the object always exists, an error
inside subsasgn.m does not revoke changes that have already been made.
It is solely the callee's responsibility not to leave the object in an
invalid state. This may possibly alter the way code works (though well
written code should probably work well). The internal variable
optimize_subsasgn_calls is provided to switch off the optimization, if
it causes problems. Another option is to declare different output and
input arguments in the method.
If this feature eventually stays in Octave, I think there should be a
big warning added somewhere in the docs.

Comments? Thoughts?

cheers

-- 
RNDr. Jaroslav Hajek
computing expert & GNU Octave developer
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz


reply via email to

[Prev in Thread] Current Thread [Next in Thread]