Skip to content

libvmaf/cuda: compute the 16-bit motion rounding offset with a shift - #1691

Open
wakamex wants to merge 1 commit into
Netflix:masterfrom
wakamex:cuda-motion-pow
Open

wakamex wants to merge 1 commit into
Netflix:masterfrom
wakamex:cuda-motion-pow

Conversation

@wakamex

@wakamex wakamex commented Oct 19, 2026

Copy link
Copy Markdown

On master, calculate_motion_score_kernel_16bpc (libvmaf/src/feature/cuda/integer_motion/motion_score.cu:88) sets the rounding offset with

unsigned add_before_shift_y = pow(2, (src.bpc - 1));

in every thread, so every pixel of a 10-bit frame pays for a double-precision pow(). Consumer GPUs run FP64 slowly (1/64 of the FP32 rate on the RTX 3090's GA102), and in the 10-bit run below the motion kernel is the most expensive kernel, 53% of all GPU kernel time. The 8-bit kernel doesn't have this.

This PR replaces it with 1u << (src.bpc - 1), which is the same value for every supported bit depth.

Kernel times from Nsight Systems (nsys profile -t cuda, then the cuda_gpu_kern_sum report), RTX 3090, driver 615.71.09, libvmaf built with CUDA 13.1. The input is 96 frames of 1080p 10-bit 4:2:0: FFmpeg's testsrc2 as the reference and a noised and blurred copy as the distorted clip, scored with vmaf -b 10 -m path=model/vmaf_v0.6.1.json --gpumask 0. Lower is better.

GPU kernel time master 229f247 this branch
calculate_motion_score_kernel_16bpc, mean per frame 0.689 ms 0.089 ms
all kernels, 96 frames 125.0 ms 66.1 ms

Every per-frame feature and VMAF score in the CSV output is the same as master on this clip and on an 8-bit version of it.

This is the only pow() in the CUDA device code. The other pow() calls under libvmaf/src/feature/cuda/ are in integer_adm_cuda.c and run on the host.

Validation

libvmaf built with -Denable_cuda=true -Denable_float=true -Dbuilt_in_models=true (CUDA 13.1, GCC 13), master 229f247 against this branch. The unit tests give the same result on both: 30 of 31 pass, and test_cuda_pic_preallocation segfaults in test_cuda_picture_preallocation_method_host_pinned on master too.

calculate_motion_score_kernel_16bpc set add_before_shift_y to
pow(2, (src.bpc - 1)), a double-precision pow() in every thread.
1u << (src.bpc - 1) is the same value in integer arithmetic.
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.

1 participant