On Wed, 28 Apr 2021, Josh Dekker wrote:
From: Rafal Dabrowa <fatwild...@gmail.com>
First a couple technical details:
The use of '.ifeqs "\op", "sshr"' needs to be changed into '.ifc \op,
sshr', because gas-preprocessor doesn't implement '.ifeqs'.
The checkasm tests for hevc_pel that were added in
9c513edb7999a35ddcc6e3a8d984a96c8fb492a3 aren't actually ever run when you
run "make fate-checkasm", because they're not added in
tests/fate/checkasm.mak. They're, IMO, separated way too finegrainedly
into 10 test groups of hevc_epel, hevc_epel_uni, hevc_epel_uni_w, etc. I'd
strongly suggest you'd merge them into one single group, hevc_pel, just
like the file name. That makes it easier to hook up to fate.
(As a side note, the fact that new checkasm tests need to be hooked up in
fate like this in tests/fate/checkasm.mak is easy to overlook, and the
benefit from being able to mark one specific group of checkasm as
known-failure to ignore, is not used very much. So maybe we should
reconsider to just have one single "fate-checkasm" which runs the full
suite?)
All the tests crash under checkasm on linux. The reason is that they use
e.g. x3 for loop counter, while the variable is declared as int. Checkasm
tests against this by making sure the upper half of such registers are
filled with garbage, but the wrapper that does that can't be used on apple
platforms, so that aspect goes untested when developing on a mac. So
please test checkasm on something else than a mac too.
Then, there's the sheer size of the patch. You said you considered
templating it - if possible that would be very welcome. I haven't looked
closely enough to be able to say easily how to do it, if at all though.
Then finally, the code is very very stall prone. It might not be
measurable on an M1, but is very real on other cores. While you can say "I
haven't bothered tuning it yet", the thing is, you don't need to actually
run it on such a core to roughly do much better scheduling. I did one
initial test on one function and got it sped up by 4% by just adjusting it
in an initial way. Example:
function ff_hevc_put_hevc_epel_h48_8_neon, export=1
[...]
1: ld3 {v26.16b, v27.16b, v28.16b}, [x1], x5
ushr v29.2d, v26.2d, #8 // Uses v26 which was loaded
right before
ushr v30.2d, v27.2d, #8
ushr v31.2d, v28.2d, #8
ld1 {v24.s}[0], [x1], x5
ld1 {v25.s}[0], [x1], x2 // Uses x1 which was updated in the
previous instruction
mov v29.b[7], v24.b[0] // Uses v24 which was loaded almost
right before
mov v30.b[7], v24.b[1]
mov v31.b[7], v24.b[2]
mov v29.b[15], v25.b[0]
mov v30.b[15], v25.b[1]
mov v31.b[15], v25.b[2]
movi v16.8h, #0 // This has no dependencies and could be
done anytime, while e.g. waiting for results for the loads above!
movi v17.8h, #0
movi v18.8h, #0
movi v20.8h, #0
movi v21.8h, #0
movi v22.8h, #0
calc_epelb v16, v26, v27, v28, v29
calc_epelb2 v20, v26, v27, v28, v29
calc_epelb v17, v27, v28, v29, v30
calc_epelb2 v21, v27, v28, v29, v30
calc_epelb v18, v28, v29, v30, v31
calc_epelb2 v22, v28, v29, v30, v31
st3 {v16.8h, v17.8h, v18.8h}, [x0], #48
st3 {v20.8h, v21.8h, v22.8h}, [x0], x10
subs x3, x3, #1 // This updates the condition flags
right before the branch, while we could stick it anywhere else in the
loop, where we have an instruction waiting for the result of the previous
one
b.ne 1b
ret
A trivial rescheduling of it looks like this:
1: ld3 {v26.16b, v27.16b, v28.16b}, [x1], x5
movi v16.8h, #0
movi v17.8h, #0
movi v18.8h, #0
ld1 {v24.s}[0], [x1], x5
movi v20.8h, #0
movi v21.8h, #0
movi v22.8h, #0
ld1 {v25.s}[0], [x1], x2
ushr v29.2d, v26.2d, #8
ushr v30.2d, v27.2d, #8
ushr v31.2d, v28.2d, #8
mov v29.b[7], v24.b[0]
mov v30.b[7], v24.b[1]
mov v31.b[7], v24.b[2]
mov v29.b[15], v25.b[0]
mov v30.b[15], v25.b[1]
mov v31.b[15], v25.b[2]
calc_epelb v16, v26, v27, v28, v29
calc_epelb2 v20, v26, v27, v28, v29
calc_epelb v17, v27, v28, v29, v30
calc_epelb2 v21, v27, v28, v29, v30
calc_epelb v18, v28, v29, v30, v31
calc_epelb2 v22, v28, v29, v30, v31
st3 {v16.8h, v17.8h, v18.8h}, [x0], #48
subs x3, x3, #1 // height
st3 {v20.8h, v21.8h, v22.8h}, [x0], x10
b.ne 1b
The first version gave these checkasm numbers for me:
Cortex A53 A72 A73
put_hevc_epel_h48_8_neon: 3312.7 2545.7 2961.5
The new version was:
put_hevc_epel_h48_8_neon: 3168.7 2497.0 2842.5
That is a 4% speedup on A53, 1.8% speedup on A72 and 4% speedup on A73.
(The latter two were quite noisy though so the exact benefit is unknown.)
One doesn't necessarily need to run and test and tune all of it for the
exact perfect scheduling, but the functions look trivial enough that you
can improve it a lot like this by just shuffling things around.
// Martin
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".