]> git.sesse.net Git - ffmpeg/commitdiff
lavc/aacenc_utils: replace powf(x,y) by expf(logf(x), y)
authorGanesh Ajjanagadde <gajjanag@gmail.com>
Tue, 8 Mar 2016 02:16:29 +0000 (21:16 -0500)
committerGanesh Ajjanagadde <gajjanag@gmail.com>
Fri, 18 Mar 2016 14:47:25 +0000 (07:47 -0700)
This is ~2x faster for y not an integer on Haswell+GCC, and should
generally be faster due to the fact that anyway powf essentially does
this under the hood. Made an inline function in lavu/internal.h for this
purpose.

Note that there are some accuracy differences, that should generally be
negligible. In particular, FATE still passes on this platform.

Results in ~ 7% speedup in aac encoding with -march=native, Haswell+GCC.
before:
ffmpeg -i sin.flac -acodec aac -y sin_new.aac  6.05s user 0.06s system 104% cpu 5.821 total

after:
ffmpeg -i sin.flac -acodec aac -y sin_new.aac  5.67s user 0.03s system 105% cpu 5.416 total

This is also faster than an alternative approach that pulls in powf, gets rid of
the crufty NaN checks and other special cases, exploits knowledge about the intervals, etc.
This of course does not exclude smarter approaches; just suggests that
there would need to be significant work on this front of lower utility than
searches for hotspots elsewhere.

Reviewed-by: Reimar Döffinger <Reimar.Doeffinger@gmx.de>
Reviewed-by: Ronald S. Bultje <rsbultje@gmail.com>
Signed-off-by: Ganesh Ajjanagadde <gajjanag@gmail.com>
libavcodec/aacenc_utils.h
libavutil/internal.h

index 41a62961e18a895088d81d726d7a9594ea079483..07f733746bd16c1c0bfa04b9a970a87b3e8ea4c3 100644 (file)
@@ -28,6 +28,7 @@
 #ifndef AVCODEC_AACENC_UTILS_H
 #define AVCODEC_AACENC_UTILS_H
 
+#include "libavutil/internal.h"
 #include "aac.h"
 #include "aacenctab.h"
 #include "aactab.h"
@@ -122,7 +123,10 @@ static inline float find_form_factor(int group_len, int swb_size, float thresh,
             if (s >= ethresh) {
                 nzl += 1.0f;
             } else {
-                nzl += powf(s / ethresh, nzslope);
+                if (nzslope == 2.f)
+                    nzl += (s / ethresh) * (s / ethresh);
+                else
+                    nzl += ff_fast_powf(s / ethresh, nzslope);
             }
         }
         if (e2 > thresh) {
index da76ca26d3dac66c70c7089a5f49e2fc325db8c9..340e18bc5dd76192b4db296b9edcf51ded88f5c4 100644 (file)
@@ -314,6 +314,22 @@ static av_always_inline float ff_exp10f(float x)
     return exp2f(M_LOG2_10 * x);
 }
 
+/**
+ * Compute x^y for floating point x, y. Note: this function is faster than the
+ * libm variant due to mainly 2 reasons:
+ * 1. It does not handle any edge cases. In particular, this is only guaranteed
+ * to work correctly for x > 0.
+ * 2. It is not as accurate as a standard nearly "correctly rounded" libm variant.
+ * @param x base
+ * @param y exponent
+ * @return x^y
+ */
+static av_always_inline float ff_fast_powf(float x, float y)
+{
+    return expf(logf(x) * y);
+}
+
+
 /**
  * A wrapper for open() setting O_CLOEXEC.
  */