Remove the pdiff_lut_scale in nlmeans and increase weight_lut table size
from 2^9 to 500000, this change will avoid using pdiff_lut_scale in
nlmeans_slice() for weight_lut table search, improving the performance
by about 12%. (in 1080P size picture case).
Use the profiling command like:
perf stat -a -d -r 5 ./ffmpeg -i input -an -vf nlmeans=s=30 -vframes 10 \
-f null /dev/null
without this change:
when s=1.0(default value) 63s
s=30.0 72s
after this change:
s=1.0(default value) 56s
s=30.0 63s
Reviewed-by: Carl Eugen Hoyos <ceffmpeg@gmail.com>
Signed-off-by: Jun Zhao <mypopydev@gmail.com>
Signed-off-by: Clément Bœsch <u@pkh.me>
This helps figuring out where the filter is slow:
70.53% ffmpeg_g ffmpeg_g [.] nlmeans_slice
25.73% ffmpeg_g ffmpeg_g [.] compute_safe_ssd_integral_image_c
1.74% ffmpeg_g ffmpeg_g [.] compute_unsafe_ssd_integral_image
0.82% ffmpeg_g ffmpeg_g [.] ff_mjpeg_decode_sos
0.51% ffmpeg_g [unknown] [k] 0xffffffff91800a80
0.24% ffmpeg_g ffmpeg_g [.] weight_averages
(Tested with a large image that takes several seconds to process)
Since this function is irrelevant speed wise, the file's TODO is
updated.
before: ssd_integral_image_c: 49204.6
after: ssd_integral_image_c: 44272.8
Unrolling by 4 made the biggest difference on odroid-c2 (aarch64);
unrolling by 2 or 8 both raised 46k cycles vs 44k for 4.
Additionally, this is a much better reference when writing SIMD (SIMD
vectorization will just target 16 instead of 4).
SIMD code will not have to deal with padding itself. Overwriting in that
function may have been possible but involve large overreading of the
sources. Instead, we simply make sure the width to process is always a
multiple of 16. Additionally, there must be some actual area to process
so the SIMD code can have its boundary checks after processing the first
pixels.