Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optiimzation - avoid log() calls in inner loop #9

Open
x42 opened this issue Aug 13, 2022 · 8 comments
Open

Optiimzation - avoid log() calls in inner loop #9

x42 opened this issue Aug 13, 2022 · 8 comments
Labels

Comments

@x42
Copy link
Contributor

x42 commented Aug 13, 2022

https://github.com/trummerschlunk/soundsgood/blob/e8eb9ba756971c22c5da8ca5a1f887f9f342faac/soundsgood.dsp#L348

The value is for display only. With a custom GUI it's preferable to have the GUI call it.
Currently FAUST compiles this into the inner loop and calls log10() for each sample!

Since it's for display only, accuracy is not required you might want to investigate a fast_log implementation
https://www.flipcode.com/archives/Fast_log_Function.shtml

@falkTX
Copy link
Collaborator

falkTX commented Aug 16, 2022

It is best to have the values on the dsp side be linear and let the GUI deal with the calculations for log scale.

@sletz
Copy link

sletz commented Aug 16, 2022

Does this helps ?

@falkTX
Copy link
Collaborator

falkTX commented Aug 16, 2022

I dont think so. we want to avoid some calculations altogether, the issue is not optimization but one of simply not doing them.
The GUI is the one that needs to display values on screen, the values it receives do not need to be in log scale, it is quite fine to do the conversion on the GUI side.

@sletz
Copy link

sletz commented Aug 16, 2022

Then this C++ conversion code might help.

@falkTX falkTX added the dsp label Aug 27, 2022
@jkbd
Copy link

jkbd commented Aug 30, 2022

I don't know how to make use of the LogValueConverter. But I just remembered that FAUST can use external C functions via Foreign Expressions. That way, some of the normal log10 calls could be replaced with the approximation @x42 suggested above.

@jkbd
Copy link

jkbd commented Aug 30, 2022

This Taylor-approximation looked interesting to me. But further investigation showed, that this cannot solve our problem.

This Python code

import numpy as np
import matplotlib.pyplot as plt

eps = np.finfo(float).eps
x = np.linspace(eps, 2.0, num=10**4)

plt.plot(x, 20*np.log(x)/np.log(10), label="factor2decibel")

def ln_approx_5(x):
    """
    The Taylor approximation is calculated with SageMath (https://www.sagemath.org/):
    ```
    sage: ln(x).taylor(x, 0.0707945784384138, 5).horner(x)
    ```
    where `0.0707945784384138` is the x value at -23dB.
    """
    return ((((112468.2650380697*x - 49763.396319187115)*x + 9394.609770881507)*x - 997.6311574844394)*x + 70.6268772311377)*x - 4.931306190276485

plt.plot(x, 20*ln_approx_5(x)/np.log(10), label="degree 5")

def ln_approx_11(x):
    return ((((((((((406075992864.511*x - 347850542618.52094)*x + 136810736245.84268)*x - 32688422094.510403)*x + 5289515570.280675)*x - 611632740.7376956)*x + 51960338.44758817)*x - 3284384.1570663475)*x + 155011.06121954476)*x - 5486.971366164414)*x + 155.3791299085029)*x - 5.667850201820498

plt.plot(x, 20*ln_approx_11(x)/np.log(10), label="degree 11")

def ln_approx_42(x):
    return ((((((((((((((((((((((((((((((((((((((((x*(-(4.75062455944967e+46)*x + 1.4469896798574425e+47) - 2.1524999999999812e+47)*x + 2.0839019499307262e+47)*x - 1.476260185786845e+47)*x + 8.157524221420126e+46)*x - 3.6602274100007795e+46)*x + 1.3707144342764619e+46)*x - 4.370329389860752e+45)*x + 1.2042469514201538e+45)*x - 2.9013054712441056e+44)*x + 6.167924296304309e+43)*x - 1.1656278666150943e+43)*x + 1.9699766602062316e+42)*x - 2.992064900743801e+41)*x + 4.100454989478739e+40)*x - 5.087052816328745e+39)*x + 5.72827702369729e+38)*x - 5.867056670588852e+37)*x + 5.474712652474278e+36)*x - 4.659768327420024e+35)*x + 3.620521220644458e+34)*x - 2.568958037099986e+33)*x + 1.6646984097251124e+32)*x - 9.848248980054393e+30)*x + 5.3151447931161086e+29)*x - 2.614084440040622e+28)*x + 1.1697809757872537e+27)*x - 4.753363261576625e+25)*x + 1.7495071687140665e+24)*x - 5.814333388836693e+22)*x + 1.738233210776675e+21)*x - 4.653111241729626e+19)*x + 1.1091415784016607e+18)*x - 2.3383154588928156e+16)*x + 432431169745875.56)*x - 6944793221868.8955)*x + 95673154083.40453)*x - 1114003390.0013206)*x + 10785012.016971951)*x - 85896.0426594101)*x + 593.2657687415557)*x - 6.974715663591488

plt.plot(x, 20*ln_approx_42(x)/np.log(10), label="degree 42", alpha=0.5)

plt.ylim(-96, 6)
# plt.xscale('log')
plt.xlabel('Factor')
plt.ylabel('Decibel')
plt.legend()
plt.show()

produces the image
grafik
where you can see, the approximation is only close to factor2decibel within a narrow interval and with higher degrees numerical problems seem to arise.

@sletz
Copy link

sletz commented Aug 31, 2022

@x42
Copy link
Contributor Author

x42 commented Sep 2, 2022

Reading the produced C++ code of the final product now, the log here is really just the tip of the iceberg and would just be a micro optimization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants