Skip to content

Optimize bicubic resize with OpenMP - #1143

Open
AhmedDusuki wants to merge 1 commit into
microsoft:mainfrom
AhmedDusuki:perf/bicubic-resize-openmp
Open

AhmedDusuki wants to merge 1 commit into
microsoft:mainfrom
AhmedDusuki:perf/bicubic-resize-openmp

Conversation

@AhmedDusuki

Copy link
Copy Markdown

Addresses #1057.

Summary

This adds optional OpenMP row parallelism to the float-domain bicubic resize used by the vision C API.

Both the horizontal and vertical passes operate on independent rows. The existing scalar helpers remain unchanged and are used for small workloads and builds without OpenMP. The implementation does not set a thread count, so applications retain control through their normal OpenMP runtime configuration.

OpenMP discovery is limited to eligible C API vision builds. Android, iOS, and Emscripten retain the scalar path because enabling OpenMP on those targets would change their runtime and deployment requirements.

Performance

Fresh local measurements were taken on an AMD Ryzen 5 2600X using GCC 14.4.0 in a release build. The TorchVision reference used PyTorch 2.14.1+cpu and TorchVision 0.29.1+cpu.

No thread count was configured for the original scalar path, this PR, or the default TorchVision column. On this machine, the OpenMP runtime selected 12 threads while PyTorch selected 6 intra-op threads by default. A separate TorchVision run explicitly used 12 intra-op threads for a matched thread-count reference.

Each configuration was launched three times. Every run used three warm-ups followed by 40, 30, 20, 15, or 10 timed samples from the smallest to largest case. Each table entry is the median of the three run medians.

Source to target Original scalar This PR, default Speedup TorchVision float, default TorchVision float, 12 threads
224x224 to 768x768 3.48 ms 3.53 ms 0.99x 3.19 ms 2.38 ms
640x480 to 912x672 5.86 ms 5.84 ms 1.00x 4.28 ms 3.46 ms
1300x876 to 960x624 11.81 ms 3.97 ms 2.98x 6.96 ms 5.93 ms
1920x1080 to 1056x576 19.20 ms 6.30 ms 3.05x 9.94 ms 6.86 ms
3024x4032 to 672x912 87.69 ms 21.35 ms 4.11x 25.22 ms 18.15 ms

The two smallest cases remain on the scalar path because they are below the parallel-work threshold. Their small timing differences are normal run-to-run variation.

The original and OpenMP paths produced identical output hashes in every run. TorchVision float is included as a familiar performance reference, but it is not an exact implementation comparison because it has slightly different floating-point results.

Correctness

Parallelism changes only which independent rows execute concurrently. The tap order and floating-point accumulation within each output pixel are unchanged.

The new regression test compares the scalar and OpenMP horizontal and vertical helpers using deterministic input and uneven dimensions. Both passes produce exactly equal output.

Validation

  • complete Linux pp_api_test: 204 passed, 2 disabled
  • Linux Python extension and C API builds passed
  • MSVC C API build passed
  • OpenMP-disabled scalar build and benchmark passed
  • repaired Linux wheel installed and ran successfully in a clean environment
  • the installed wheel loaded its bundled libgomp
  • public Gemma image processing produced identical output with 1 and 12 OpenMP threads
  • git diff --check passed

This PR focuses on the OpenMP portion of #1057. Explicit SIMD remains a possible follow-up if further optimization is needed.

Parallelize independent rows in the horizontal and vertical float-domain bicubic passes for large workloads, while retaining the scalar path for small images and builds without OpenMP.

Add optional CMake discovery and linkage for supported C API vision targets, with exact scalar/OpenMP regression coverage.
@AhmedDusuki
AhmedDusuki requested a review from a team as a code owner October 20, 2026 23:59
Copilot AI balanced review requested due to automatic review settings October 20, 2026 23:59
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@AhmedDusuki

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

Independent row writes preserve scalar accumulation order, and no blocking issues were identified in build integration or regression coverage.

No open issues 🎉

What changed in this PR

Adds optional OpenMP acceleration to vision C API bicubic resizing, addressing the parallelism portion of #1057 while retaining scalar execution for small workloads and unsupported builds.

Changes:

  • Parallelizes independent rows above a work threshold.
  • Adds conditional OpenMP discovery and linking.
  • Tests exact equality between scalar and parallel resize helpers.
File Description
test/​pp_api_test/​test_processor.cc Adds scalar/OpenMP equality regression coverage.
shared/​api/​image_resample_float.h Adds row-parallel helpers and threshold-based dispatch.
CMakeLists.txt Enables optional OpenMP for eligible vision C API builds.
cmake/​ext_python.cmake Links OpenMP into eligible Python extension builds.

Review effort: Balanced

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.

2 participants