0
$\begingroup$

I'm processing multiple (independent) Exponential Moving Average 1-Pole filters on different parameters I have within my Audio application, with the intent of smooth each param value at audio rate:

for (int i = 0; i < mParams.GetSize(); i++) {
    mParams.Get(i)->SmoothBlock(blockSize);
}

...

inline void SmoothBlock(int blockSize) {
    double inputA0 = mValue * a0;

    for (int sampleIndex = 0; sampleIndex < blockSize; sampleIndex++) {
        mSmoothedValues[sampleIndex] = z1 = inputA0 + z1 * b1;
    }
}   

I'd like to take advantage of CPU SIMD instructions, processing them in parallel, but I'm not really sure how I can achieve this.

Any tips?

$\endgroup$
  • 1
    $\begingroup$ I'm voting to close this question as off-topic because I think this is more a programming than signals question, and would be a better fit for stackoverflow. $\endgroup$ – MBaz Dec 14 '18 at 16:03
  • 1
    $\begingroup$ @MBaz I'd like to disagree; the question is about algorithm restructuring of something for superior performance, and I do see a strong DSP component in that (as for IIRs, this typically involves mathematical transformations on the coefficients, which surpasses the scope of a pure programming question) $\endgroup$ – Marcus Müller Dec 14 '18 at 16:06
  • $\begingroup$ oh wait, I misread and missed the central point: these filters are independent! $\endgroup$ – Marcus Müller Dec 14 '18 at 16:07
  • $\begingroup$ @markzzz: Are you sure that SIMD instructions are not generated? Take your code to godbolt.org and compile with -march=native -O3 and see if SIMD instructions are generated. $\endgroup$ – user14717 Dec 14 '18 at 18:11
  • $\begingroup$ @markzzz: somehow your central code line isn't really valid C, so be a bit careful. $\endgroup$ – Marcus Müller Dec 14 '18 at 19:26
1
$\begingroup$

usually, SIMD instructions work by loading the values you want to apply the same operation to into a wide register, and then applying the vectorized instruction to it.

Now, collating values from all over memory to end up in one say 256-bit wide register, just to do 8 multiplications at once, probably doesn't pay.

If you, however, are able to decide the in-memory layout of these parallel streams $x_i$ to be interleaved, i.e.

\begin{matrix} x_0[0] & x_1[0] & x_2[0] &\cdots&x_7[0]&x_0[1] & x_1[1]&\cdots &x_7[1] & x_8[2]&\cdots \end{matrix}

then you could load the consecutive values into one SIMD register without need for any memory or register shuffling; that would be desirable.

Again, in your specific case I wouldn't expect too much from optimization for SIMD: If a single-tap IIR is already the bottleneck, your application is not CPU, but memory bandwidth bound.

If you just think you can speed up your application significantly by speeding up this especially cheap operation: I'm afraid that's rather unlikely; if it's trivial to parallelize on an instruction level, your compiler stands a good chance of doing exactly that, and really, one multiply-accumulate per output sample is pretty idyllic, so I doubt there's much to be done, considering the cost of rearranging numbers to make that work (your API defines samples to not be in interleaved order, and your compiler can't do anything about that).

There's other aspects to be looked at; among these are questions like whether double is really necessary for what is presumably fixed-point numbers with less than 32 bit of dynamic range.

$\endgroup$
  • $\begingroup$ I don't need to optimize from 90% to 1%. But since I've somethings like 40 paramters smoothing constantly (because they are modulated at audio rate all the time), it use somethings like 4% of CPU only for smooth. Maybe I can reduce this amount simply pack data in parallel, no? $\endgroup$ – markzzz Dec 16 '18 at 17:20
  • $\begingroup$ 40 different smoothed streams really, from an intuition of mine, sounds like memory bandwidth congestion more than CPU congestion. $\endgroup$ – Marcus Müller Dec 16 '18 at 21:16
  • $\begingroup$ Uhm, not really ! They will be 4 doubles * 40. i.e. 1280 bytes. Quite normal for a non-basic synth... $\endgroup$ – markzzz Dec 17 '18 at 9:50
0
$\begingroup$

Intel's Integrated Performance Primitives library contains DSP building blocks that are optimised for DSP on a number of processors. There are IIR specific functions (and more specifically here) but you are going to have to get a bit familiar with this library, provided that your hardware is Intel based of course. Other companies probably have similar libraries for their products too.

Hope this helps.

$\endgroup$
  • $\begingroup$ I already use IPP, but that's not the problem. Is organize data. $\endgroup$ – markzzz Dec 16 '18 at 17:18
  • $\begingroup$ @markzzz Thanks for letting me know, I am sorry, I did not get that. From the way the question is phrased, I interpreted it as trying to generate code that takes advantage of special capabilities of a processor wherever they exist. $\endgroup$ – A_A Dec 17 '18 at 9:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.