octave-maintainers
[Top][All Lists]
Advanced

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

mixed linear/logical indexing question


From: Rik
Subject: mixed linear/logical indexing question
Date: Wed, 19 Dec 2018 11:09:51 -0800

Recently, sliding windows of statistics functions (movXXX) were added to
Octave.  All of these functions depend on a base function movfun.  As part
of implementing movfun I used the profiler to examine the performance and I
found a hot spot responsible for 70% of the run time.  Unfortunately, I
couldn't see any way to improve things without jumping out of the Octave
language in to C++.  I'm hoping someone else might look at this and have an
idea.

The code is below

--- Code Start ---
## Apply "shrink" boundary conditions
## Function is not applied to any window elements outside the original data.
function y = shrink_bc (fcn, x, idxp, win, wlen, odim)
  N   = length (x);
  idx = idxp + win;
  tf  = (idx > 0) & (idx <= N);  # idx inside boundaries

  n   = length (idxp);
  y   = zeros (n, odim);
  ## FIXME: This nested for loop accounts for 70% of running time.
  ##        Given that "shrink" is the default Endpoint value this
  ##        code needs to be reworked.
  for i = 1:n
    k      = idx(tf(:,i),i);
    y(i,:) = fcn (x(k));
  endfor
endfunction
--- Code End ---

In my case, the following conditions are a suitable example

+verbatim+
fcn = @mean;
x = randi (1e4, [1000, 1]);
idxp = 1:25;
win = (-25:25).';
wlen = [51, 51];
odim = 1;
-verbatim-

Indexing in Octave is insanely fast, but this is a weird case because it is
not simply linear indexing [x(5)], nor is it logical indexing [x(x < 1)]. 
It is a hybrid where the indices are linear (as would be returned from
find()) but only some of them are valid so they need to be masked with a
logical value.

When I run this code repeatedly in a benchmark it requires ~3.0
milliseconds, but in the overall code it is called 2000 times so the
function is taking ~6 seconds which feels long.

In this example, the value of k for i = 1 is 1:26, for i = 2, 1:27, etc., etc.

I tried recoding using cellfun

idx = cellfun (@(n) (1:n), num2cell ((wlen(1) - idxp(end)):(wlen(end)-1)),
'uniformoutput', false);
y = cellfun (@(i) fcn (x(i)), idx);

but this takes ~4.5 milliseconds to run.

Anybody have any good tricks to try?

If not, it makes me wonder whether a C++ function that did this mixed
indexing could be useful.  Another feature which is not implemented for
movfun is "includenan"/"omitnan".  The core need is similar to that above
in that I have a function handle, some linear indices, and some logical
indices (based on isnan()).

--Rik





reply via email to

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