rnnoise icon indicating copy to clipboard operation
rnnoise copied to clipboard

Create SIMD-accelerated version of `compute_gru` function

Open Ameobea opened this issue 2 years ago • 3 comments

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 as compute_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/xzEGxj8ne

Testing 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.

Ameobea avatar Jul 19 '21 03:07 Ameobea

@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.

Ameobea avatar Jul 20 '21 21:07 Ameobea

Thanks for taking the time to look into it :) I have created a PR on your fork to improve SIMD detection: https://github.com/Ameobea/rnnoise/pull/1

a-rose avatar Jul 21 '21 15:07 a-rose

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

Ameobea avatar Jul 25 '21 02:07 Ameobea