Skip to content
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

1D inverse type-II DCT AVX2 optimisations #114

Open
wants to merge 6 commits into
base: 20240120
Choose a base branch
from

Conversation

frankplow
Copy link
Collaborator

This PR adds AVX2 optimisations for the type-II DCT. For now, these optimisations are only implemented at the 1D level.

Performance results:

Bitstream Before After Delta
RitualDance_1920x1080_60_10_420_32_LD 101.0 104.0 +3.0%
RitualDance_1920x1080_60_10_420_37_RA 89.0 90.0 +1.1%
Tango2_3840x2160_60_10_420_27_LD 24.0 25.0 +4.2%
benchmarking with Linux Perf Monitoring API
nop: 86.0
checkasm: using random seed 1542246724
AVX2:
 - vvc_itx_1d.idct2 [OK]
checkasm: all 6 tests passed
vvc_inv_dct2_2_c: 16.0
vvc_inv_dct2_2_avx2: 16.2
vvc_inv_dct2_4_c: 19.7
vvc_inv_dct2_4_avx2: 17.0
vvc_inv_dct2_8_c: 39.7
vvc_inv_dct2_8_avx2: 29.2
vvc_inv_dct2_16_c: 132.7
vvc_inv_dct2_16_avx2: 54.5
vvc_inv_dct2_32_c: 379.0
vvc_inv_dct2_32_avx2: 115.7
vvc_inv_dct2_64_c: 1527.7
vvc_inv_dct2_64_avx2: 385.0

@@ -172,16 +172,22 @@ typedef struct VVCDSPContext {
VVCALFDSPContext alf;
} VVCDSPContext;

void ff_vvc_dsp_init(VVCDSPContext *hpc, int bit_depth);
void ff_vvc_dsp_init(VVCDSPContext *hpc, int bit_depth,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it would be more elegant to pass VVCFrameParamSets, VVCFrameContext or something else more general here (and the call site for ff_vvc_dsp_init supports it), however including vvc_ps.h in vvcdsp.h introduced a lot of compilation errors.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, at this level, we'd better include a small set of headers

@frankplow
Copy link
Collaborator Author

629db28 disables the optimisations when sps_extended_precision_flag is set. A new set of functions will need to be written in order to support transform coefficients larger than 16 bits.

@nuomi2021
Copy link
Member

Did you check the hevc idct checkasm output? is it aligned with your result?
thank you

vvc_inv_dct2_2_c: 16.0
vvc_inv_dct2_2_avx2: 16.2
vvc_inv_dct2_4_c: 19.7
vvc_inv_dct2_4_avx2: 17.0
vvc_inv_dct2_8_c: 39.7
vvc_inv_dct2_8_avx2: 29.2
vvc_inv_dct2_16_c: 132.7
vvc_inv_dct2_16_avx2: 54.5
vvc_inv_dct2_32_c: 379.0
vvc_inv_dct2_32_avx2: 115.7
vvc_inv_dct2_64_c: 1527.7
vvc_inv_dct2_64_avx2: 385.0

@frankplow
Copy link
Collaborator Author

Did you check the hevc idct checkasm output? is it aligned with your result? thank you

vvc_inv_dct2_2_c: 16.0
vvc_inv_dct2_2_avx2: 16.2
vvc_inv_dct2_4_c: 19.7
vvc_inv_dct2_4_avx2: 17.0
vvc_inv_dct2_8_c: 39.7
vvc_inv_dct2_8_avx2: 29.2
vvc_inv_dct2_16_c: 132.7
vvc_inv_dct2_16_avx2: 54.5
vvc_inv_dct2_32_c: 379.0
vvc_inv_dct2_32_avx2: 115.7
vvc_inv_dct2_64_c: 1527.7
vvc_inv_dct2_64_avx2: 385.0

Here are the relevant entries from the HEVC IDCT checkasm benchmark:

hevc_idct_4x4_8_c: 141.5
hevc_idct_4x4_8_avx: 44.7
hevc_idct_4x4_10_c: 133.2
hevc_idct_4x4_10_avx: 43.5
hevc_idct_8x8_8_c: 870.7
hevc_idct_8x8_8_avx: 134.2
hevc_idct_8x8_10_c: 879.2
hevc_idct_8x8_10_avx: 137.2
hevc_idct_16x16_8_c: 5861.0
hevc_idct_16x16_8_avx: 696.2
hevc_idct_16x16_10_c: 5835.5
hevc_idct_16x16_10_avx: 695.5
hevc_idct_32x32_8_c: 47877.5
hevc_idct_32x32_8_avx: 3863.0
hevc_idct_32x32_10_c: 47965.5
hevc_idct_32x32_10_avx: 3856.2

Note that the HEVC optimisations are performed at the 2D level rather than the 1D level. Many of the instructions in the SIMD optimisations are spent loading data into and extracting data from the SIMD registers. This is all the more true for FFVVC due to the strides in the IDCT function signature. The FFVVC IDCT can be optimised at the 2D level in the future to get performance gains closer to HEVC's, but for now the 1D optimisations work alone and they provide the backbone needed for any future optimisation.

@nuomi2021
Copy link
Member

but for now the 1D optimisations work alone and they provide the backbone needed for any future optimisation.

how about dav1d, it has similar 1d function. or 2d only

@frankplow
Copy link
Collaborator Author

frankplow commented Jul 19, 2023

but for now the 1D optimisations work alone and they provide the backbone needed for any future optimisation.

how about dav1d, it has similar 1d function. or 2d only

dav1d uses 2D and then some, incorporating some of the vectorisation as well to save a transpose operation. According to this lecture, this allowed them to double performance compared to only 1D SIMD optimisations. It's worth noting that doing these higher-level optimisations comes at a cost in terms of complexity though. dav1d has over 10,000 lines of inverse transform assembly for AVX2 alone!

@nuomi2021
Copy link
Member

nuomi2021 commented Jul 19, 2023

dav1d has over 10,000 lines of inverse transform assembly for AVX2 alone!

It was worth it. dav1d is most fast decoder in we see so far. and the current vvc transform function for some files cost 10% cpu.
Is it possible, just use their code directly? DCT functions are similar. we may only need to change some parameters(asm tables)

@frankplow
Copy link
Collaborator Author

Is it possible, just use their code directly? DCT functions are similar. we may only need to change some parameters(asm tables)

I will look into this. I don't think it will be quite this simple - some internal data representations in FFVVC will need to be changed as dav1d relies on packed input data but it looks like there is only one place non-packed transform coefficients are actually used in FFVVC.

@nuomi2021
Copy link
Member

I will look into this

👍, we can start with 2x2 or 4x4 block. zero the entire block and set the fireset coeff to 1

some internal data representations in FFVVC will need to be changed
no problem. You can do any reasonable change

m21, m22, m23, m24, \
m11, m12, m13, m14

const vvc_dct2_8_odd_mat, dw matvec_mul_4_permute(dct2_8_odd_mat_permute( \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vvc_itx_1d.asm:49: warning: single-line macro `matvec_mul_4_permute' exists, but not taking 1 parameter [-w+pp-macro-params-single]

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a bug in NASM - the inner macro is expanded. These macros could be removed and these permutations applied directly to the transform matrices at the cost of readability, or we could look at adding -w-pp-macro-params-single, if we really want to get rid of the warning.

@frankplow frankplow changed the base branch from 20230811 to main August 21, 2023 13:28
@frankplow
Copy link
Collaborator Author

Rebase and re-target onto main.

@frankplow
Copy link
Collaborator Author

frankplow commented Aug 27, 2023

Reset to 6105322. Work done porting FFmpeg HEVC ASM can now be found at frankplow:ffmpeg-hevc-idct/#130. This has been done as there is little in common between the two trees.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants