Fix round_prefer_ceil nearest mode for negative halfway values in Resize op#28345
Conversation
…ize op The ROUND_PREFER_CEIL nearest mode used std::round which rounds away from zero. For positive halfway values (e.g., 0.5, 1.5), this correctly rounds to ceiling. However, for negative halfway values (e.g., -0.5, -1.5), rounding away from zero gives floor instead of ceiling. Add an explicit check for negative halfway values, paralleling the existing fix in ROUND_PREFER_FLOOR for positive halfway values. This ensures the ONNX spec semantics are correctly implemented: at exactly N.5, prefer ceiling regardless of sign. Fixed in both CPU (upsamplebase.h) and CUDA (resize_impl.cu) implementations. Agent-Logs-Url: https://github.com/microsoft/onnxruntime/sessions/3c71cd3c-5e0f-41ee-8c78-c727c500c5b1 Co-authored-by: tianleiwu <30328909+tianleiwu@users.noreply.github.com>
|
@copilot, please add a test case for this. |
…formation Add two tests: 1. ResizeOpNearestUpSample_RoundPreferCeil_HalfPixel: exercises non-integer scale (26->64) which produces many fractional boundaries 2. ResizeOpNearestUpSample_RoundPreferCeil_HalfPixel_2x2to7x8: exercises a positive .5 boundary where round_prefer_ceil selects ceiling Agent-Logs-Url: https://github.com/microsoft/onnxruntime/sessions/b0f24e47-531c-431c-9dca-505a646f71b7 Co-authored-by: tianleiwu <30328909+tianleiwu@users.noreply.github.com>
Added two test cases in commit 076bea0:
Both pass on the CPU provider. |
tianleiwu
left a comment
There was a problem hiding this comment.
Summary
Clean, well-scoped bug fix that adds the missing negative-halfway-value handling to ROUND_PREFER_CEIL in both CPU and CUDA Resize implementations. The fix mirrors the existing ROUND_PREFER_FLOOR positive-halfway check symmetrically. Two new test cases exercise the fix with different scale factors. Low risk.
CPU & CUDA Fix
The fix correctly mirrors the ROUND_PREFER_FLOOR pattern: FLOOR checks + 0.5f for positive halfway values where std::round/roundf (rounds away from zero) disagrees with floor; CEIL now checks - 0.5f for negative halfway values where std::round/roundf disagrees with ceil. The symmetry is clean and easy to reason about.
CUDA implementation uses _Ceil consistently with the existing _Floor usage in NearestPixel_ROUND_PREFER_FLOOR, and static_cast<int> matching the CUDA convention.
Tests
Two complementary test cases: one exercises a non-integer scale (26→64) with negative intermediate coordinates where the bug manifests, the other exercises positive 0.5 boundaries confirming round_prefer_ceil selects ceiling there too. Both follow existing patterns.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Description
ROUND_PREFER_CEILin the Resize operator used barestd::round/roundf, which rounds away from zero. This is correct for positive halfway values (e.g.,round(0.5) = 1 = ceil(0.5)) but wrong for negative halfway values (e.g.,round(-0.5) = -1, butceil(-0.5) = 0).Negative coordinates occur naturally with the
half_pixelcoordinate transformation mode for the first output pixels when upsampling.Added an explicit negative-halfway check, mirroring the existing positive-halfway check in
ROUND_PREFER_FLOOR:Same fix applied to the CUDA implementation (
resize_impl.cu).Added two test cases in
resize_op_test.cc:ResizeOpNearestUpSample_RoundPreferCeil_HalfPixel— exercises non-integer scale (26→64) from the original issue report, verifying correct source pixel selection at fractional boundaries.ResizeOpNearestUpSample_RoundPreferCeil_HalfPixel_2x2to7x8— exercises a positive 0.5 boundary whereround_prefer_ceilselects ceiling.Motivation and Context
The
round_prefer_floorpath already had an explicit halfway-case override (for positive values wherestd::rounddisagrees with floor). Theround_prefer_ceilpath was missing the symmetric fix for negative values, violating the ONNX spec semantics of "at ties, prefer ceiling."