W3C home > Mailing lists > Public > public-audio@w3.org > October to December 2012

Re: DSP API overlapping arrays + inv() and neg()

From: Jens Nockert <jens@nockert.se>
Date: Tue, 6 Nov 2012 11:21:30 +0100
Cc: public-audio@w3.org
Message-Id: <C229F005-2BD4-459C-8225-A335DA14BC94@nockert.se>
To: Marcus Geelnard <mage@opera.com>, Jussi Kalliokoski <jussi.kalliokoski@gmail.com>

On 6 Nov 2012, at 08:48, Marcus Geelnard <mage@opera.com> wrote:

> That might be something worth pursuing. At some point the API only supported the source-is-destination paradigm, and I encountered the inv/neg problem too. Are you suggesting that there should be another signature, (dest/src1, src2), in addition to the current (dest, src1, src2) signature, or should we drop the latter from the API?

The idea me and Jussi discussed was to allow for both, but disallow (or make undefined) overlap in all cases where dst is not exactly the same view as either src1, src2 or src3.

> Keep in mind, there are a few disadvantages of the source-is-destination paradigm:
> 
> 1) Order matters, as you pointed out. May require additional operations to cover all use-cases.

Yes, but these operations are probably already useful. Neg and inv could be useful operations, but they could also wait, they can easily be implemented in terms of other operations.

> 2) In many situations, you need to do an explicit memory-copy operation, for instance:
> 
>   a = b - c   becomes:
> 
>   a.set(b);
>   DSP.sub(a, c);

Since I think 3-operand versions still should be allowed, the more problematic situation if you do not allow any overlapping arguments at all is

  a = b - a

but that can be solved with the madd operation

 DSP.madd(a, -1.0f, b) /* a = (a * -1.0f) + b, */

if we also allow for scalars to replace a Float32Array in all arguments, instead of only the last argument.

I think this is a good idea, and my SM implementation of the DSP part of the API already supports it, the cost in extra complexity in my code is zero, but in an optimised implementation it would require some extra branches probably.

Division is a bit more complex,

 a = b / a

since a * (1.0f / b) is not the same as a / b.

> 3) Some operations (Filter & FFT) can't be done in-place, so you'd either have to use a different paradigm for those operations (and solve the overlapping-problem anyway - possibly using exceptions), or use internal destination buffers and do an extra memory-copy operation.

I think people want to do these in-place, but then the implementation should have internal buffers and do the extra copy that is sometimes required automatically. But I think the FFT interface may grow a lot more complex with time (see FFTW for example), so we might want to keep it quite minimal in an initial version.

> My idea with the current spec would be to disallow overlapping operation, and for some operations support source & destination to be the same. If violated, throw an exception.

Checking and throwing an exception could be expensive for very short vectors, couldn't the order of evaluation just be undefined? Then most weird types of overlap would be disallowed, and if the implementations use threads, then it will be 'enforced' at runtime from the beginning.

> We also have to consider the case where the the second source argument (if any) overlaps with the destination argument, so for instance in DSP.sub(a, b, c), a, b, and c may all be overlapping (e.g. thanks to TypedArray.subarray).

Or DSP.madd, which is even worse

-- Jens Nockert
Received on Tuesday, 6 November 2012 10:22:01 UTC

This archive was generated by hypermail 2.3.1 : Tuesday, 6 January 2015 21:50:03 UTC