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

Optimize dBFS/amplitude conversion functions #7535

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

LostRobotMusic
Copy link
Contributor

@LostRobotMusic LostRobotMusic commented Oct 8, 2024

std::pow(10.f, x) and log10f are painfully slow functions when run per-sample, as is commonly required via dbfsToAmp and ampToDbfs. This PR sacrifices a completely negligible amount of precision for a significant performance boost for several LMMS plugins:

static inline float fastPow10f(float x)
{
	return expf(2.302585092994046f * x);
}

static inline float fastLog10f(float x)
{
	return logf(x) * 0.4342944819032518f;
}

Notice that these are mathematically equivalent operations, not approximations. The lost precision, which is very nearly 0, is solely due to the limited precision of floats.


Compiled via GCC with -O2:

1 billion iterations of log10f(x):
31,138,340,305      cycles
8.419502684 seconds time elapsed

1 billion iterations of fastLog10f(x):
15,626,908,607      cycles
4.226729945 seconds time elapsed

fastLog10f is 1.993x as fast on this hardware.

1 billion cycles of pow(10.f, x):
26,823,368,193      cycles
7.258407044 seconds time elapsed

1 billion cycles of fastPow10f(x):
16,135,296,386      cycles
4.315204418 seconds time elapsed

fastPow10f is 1.662x as fast on this hardware.
(This might even provide a larger benefit on older hardware, I've seen performance benefits of up to 3x reported by others.)


It might be worth exploring some faster and less-precise alternatives in the future, but what this PR provides is a significant improvement for no actual downsides whatsoever.

Copy link
Contributor

@Rossmaxx Rossmaxx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor thoughts regarding style.

include/lmms_math.h Outdated Show resolved Hide resolved
include/lmms_math.h Show resolved Hide resolved
Copy link
Member

@messmerd messmerd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't tested it, but I verified that the math is correct [Desmos link], and the changes are minimal, so I think it's safe to merge.

include/lmms_math.h Outdated Show resolved Hide resolved
include/lmms_math.h Outdated Show resolved Hide resolved
@LostRobotMusic
Copy link
Contributor Author

LostRobotMusic commented Oct 8, 2024

@messmerd I get compilation errors when compiling those changes on my PC, std::expf and std::logf are not declared. This might be relevant: https://stackoverflow.com/a/56420862/5759631

The best workaround seems to be simply using expf and logf.

@LostRobotMusic
Copy link
Contributor Author

Alternatively, it looks like std::exp and std::log can be used, which are overloaded to have the proper behavior for each type. I've updated the PR to use those.

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

Successfully merging this pull request may close these issues.

3 participants