-
Notifications
You must be signed in to change notification settings - Fork 890
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
Create SIMD-accelerated version of compute_gru
function
#191
base: master
Are you sure you want to change the base?
Conversation
* Add `-O3 -march=native` to the compiler flags in the autoconf/automake/autoetc. stuff * Optimize biquad filter implementation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good work ! I have worked on an AVX implementation, so there are a few pitfalls I can help you avoid. I'm not a maintainer on this repo though, so I can't guarantee this will ever be accepeted.
@a-rose thank you very much for the review. I'm glad you were aware of the fact that FMA support doesn't always exist when AVX2 support does. |
* We already have the value in a register, so avoid spilling to stack and reading back
Update FMA check
Thanks for taking the time to look into it :) I have created a PR on your fork to improve SIMD detection: Ameobea#1 |
Fix SIMD flags detection
I have also opened a pull request on the Xiph-run Gitlab instance referenced in the README: https://gitlab.xiph.org/xiph/rnnoise/-/merge_requests/2 |
Original merge request: xiph/rnnoise#191
I did some CPU profiling of pulseeffects / easyeffects which includes this library as a dependency for its noise reduction functionality. This led me to see that the
compute_gru
function was the hottest one in the whole application:The changes in this pull request create a new function
compute_gru_avx
which has the same functionality ascompute_gru
but uses SIMD intrinsics to accelerate the function dramatically. The main changes focus on computing the sums in the GRU function 8 at a time and using FMAs to combine multiplications and adds into a single operation, increasing accuracy as a result. This also serves to reduce the overhead of loop counter checking which my profiling let me to believe was the most expensive part of the whole function before these changes. Additionally, converting the weights (which are stored as 8-bit signed integers) is done 8 at a time using SIMD for an additional speedup.I also made some changes to the build configuration for compiler flags that use
-O3
instead of-O2
which yielded some benefits on my machine as well as pasing-march=native
which facilitates the SIMD used. If these CPU features aren't available, they will be disabled at build-time.After the optimizations, the
compute_gru_avx
function uses only ~4.4% of the total CPU time compared to ~19.63% from before - a 4.45x speedup:Here is a compiler explorer that shows the full assembly produced by the optimized
compute_gru_avx
function: https://c.godbolt.org/z/xzEGxj8neTesting done on my own machine using pulseeffects +
librnnoise.so
built with the optimized code seems to work identically to before with reduced CPU usage for the application.Let me know if you think this is something that you'd like to get merged into the project. I'm happy to make any changes necessary. There may be a better/different way you'd like to handle the CPU feature detection and and I'd love suggestions on how to handle that.