Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions onnxruntime/core/providers/cpu/nn/pool_functors.h
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ struct AveragePool2DTask final {
for (int64_t ph = 0; ph < pooled_height; ++ph) {
int64_t hstart = ph * stride_h - pads[0];
int64_t hend = hstart + kernel_shape[0] * dilation_h;
hend = std::min(hend, height + pads[1]);
hend = std::min(hend, height + pads[2]);
for (int64_t pw = 0; pw < pooled_width; ++pw) {
int64_t wstart = pw * stride_w - pads[1];
int64_t wend = wstart + kernel_shape[1] * dilation_w;
Expand Down Expand Up @@ -535,11 +535,11 @@ struct AveragePool3DTask {
for (int64_t ph = 0; ph < pooled_height; ++ph) {
int64_t hstart = ph * stride_h - pads[0];
int64_t hend = hstart + kernel_shape[0] * dilation_h;
hend = std::min(hend, height + pads[1]);
hend = std::min(hend, height + pads[3]);
for (int64_t pw = 0; pw < pooled_width; ++pw) {
int64_t wstart = pw * stride_w - pads[1];
int64_t wend = wstart + kernel_shape[1] * dilation_w;
wend = std::min(wend, width + pads[3]);
wend = std::min(wend, width + pads[4]);
for (int64_t pd = 0; pd < pooled_depth; ++pd) {
int64_t dstart = pd * stride_d - pads[2];
int64_t dend = dstart + kernel_shape[2] * dilation_d;
Expand Down
72 changes: 72 additions & 0 deletions onnxruntime/test/providers/cpu/nn/pool_op_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,78 @@ TEST(PoolTest, AveragePool_IncludePadPixel) {
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}

// Regression test for https://github.com/microsoft/onnxruntime/issues/26708
// AveragePool with count_include_pad=1 and asymmetric pads (only bottom/right)
// was using incorrect pad index for hend, producing wrong results.
TEST(PoolTest, AveragePool_CountIncludePad_AsymmetricPads) {
OpTester test("AveragePool", 19);

test.AddAttribute("auto_pad", "");
test.AddAttribute("strides", std::vector<int64_t>{1, 1});
test.AddAttribute("pads", vector<int64_t>{0, 0, 1, 1}); // no top/left, 1 bottom, 1 right
test.AddAttribute("kernel_shape", vector<int64_t>{2, 2});
test.AddAttribute("count_include_pad", (int64_t)1);

// Input: 2x2 all ones
std::vector<float> x_vals = {1.0f, 1.0f,
1.0f, 1.0f};
std::vector<int64_t> x_dims = {1, 1, 2, 2};

// Output: 2x2
// Top-left: (1+1+1+1)/4 = 1.0
// Top-right: (1+0+1+0)/4 = 0.5
// Bottom-left: (1+1+0+0)/4 = 0.5
// Bottom-right: (1+0+0+0)/4 = 0.25
std::vector<int64_t> expected_dims = {1, 1, 2, 2};
std::vector<float> expected_vals = {1.0f, 0.5f,
0.5f, 0.25f};

test.AddInput<float>("X", x_dims, x_vals);
test.AddOutput<float>("Y", expected_dims, expected_vals);
// This test targets the CPU fix only. Exclude EPs whose external libraries
// (cuDNN, CoreML, etc.) also produce wrong results for this case.
test.Run(OpTester::ExpectResult::kExpectSuccess, "",
{kCudaExecutionProvider, kCudaNHWCExecutionProvider,
kTensorrtExecutionProvider, kAclExecutionProvider, kOpenVINOExecutionProvider,
kDnnlExecutionProvider, kCoreMLExecutionProvider, kQnnExecutionProvider,
kDmlExecutionProvider});
}

// AveragePool3D with count_include_pad=1 and asymmetric pads (only back/bottom)
// Regression test for 3D path of the pad-index bug
TEST(PoolTest, AveragePool3D_CountIncludePad_AsymmetricPads) {
OpTester test("AveragePool", 19);
test.AddAttribute("auto_pad", "");
test.AddAttribute("strides", std::vector<int64_t>{1, 1, 1});
test.AddAttribute("pads", std::vector<int64_t>{0, 0, 0, 1, 1, 0}); // no front/top/left, 1 back, 1 bottom
test.AddAttribute("kernel_shape", std::vector<int64_t>{2, 2, 2});
test.AddAttribute("count_include_pad", (int64_t)1);
// Input: 2x2x2 all ones (N=1, C=1, D=2, H=2, W=2)
std::vector<float> x3d_vals = {
1.0f, 1.0f,
1.0f, 1.0f,
1.0f, 1.0f,
1.0f, 1.0f};
std::vector<int64_t> x3d_dims = {1, 1, 2, 2, 2};
// Output: 2x2x1 (D x H x W)
// D=0,H=0,W=0: (8 ones)/8 = 1.0
// D=1,H=0,W=0: (4 ones + 4 padded zeros)/8 = 0.5
// D=0,H=1,W=0: (4 ones + 4 padded zeros)/8 = 0.5
// D=1,H=1,W=0: (2 ones + 6 padded zeros)/8 = 0.25
std::vector<int64_t> expected3d_dims = {1, 1, 2, 2, 1};
std::vector<float> expected3d_vals = {1.0f, 0.5f,
0.5f, 0.25f};
test.AddInput<float>("X", x3d_dims, x3d_vals);
test.AddOutput<float>("Y", expected3d_dims, expected3d_vals);
// This test targets the CPU fix only. Exclude EPs whose external libraries
// (cuDNN, CoreML, etc.) also produce wrong results for this case.
test.Run(OpTester::ExpectResult::kExpectSuccess, "",
{kCudaExecutionProvider, kCudaNHWCExecutionProvider,
kTensorrtExecutionProvider, kAclExecutionProvider, kOpenVINOExecutionProvider,
kDnnlExecutionProvider, kCoreMLExecutionProvider, kQnnExecutionProvider,
kDmlExecutionProvider});
}

Comment thread
titaiwangms marked this conversation as resolved.
// test 'strides' attribute not specified
TEST(PoolTest, AveragePool_DefaultStrides) {
OpTester test("AveragePool");
Expand Down
Loading