Skip to content

Commit de7fb48

Browse files
hsharma35facebook-github-bot
authored andcommitted
Fix overflow and stride>1 fallback in cadence::quantized_conv1d HiFi kernels (#19193)
Summary: PR #19193 Fixes two correctness bugs in the HiFi kernels for cadence::quantized_conv1d_ncl.out and cadence::quantized_conv1d_nlc.out. The int8 path (xa_nn_conv2d_per_chan_sym8sxasym8s) produces incorrect results with stride > 1 on some backends (e.g., Artemis HiFi4) and is now redirected to the generic fallback for that case. The uint8 path overflowed WORD32 when computing out_multiplier32 if eff_scale >= 1.0 (i.e., output_scale > bias_scale), which is now clamped to INT32_MAX. Reviewed By: zonglinpeng Differential Revision: D102821209
1 parent d9688da commit de7fb48

2 files changed

Lines changed: 22 additions & 18 deletions

File tree

backends/cadence/hifi/operators/op_quantized_conv1d_ncl.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ namespace native {
2424

2525
namespace {
2626

27-
// Optimized NCHW 1D convolution for int8 x int8 -> int8
2827
void xa_opt_quantized_conv1d_ncl_asym8sxsym8s_asym8s(
2928
KernelRuntimeContext& ctx,
3029
const Tensor& input,
@@ -134,10 +133,12 @@ void xa_opt_quantized_conv1d_ncl_asym8sxsym8s_asym8s(
134133
WORD32 p_out_multiplier32[out_channels];
135134
WORD32 p_out_shift32[out_channels];
136135

137-
float out_scale = 1. / output_scale;
136+
const float eff_scale = bias_scale * (1.0f / output_scale);
138137

139138
for (int i = 0; i < out_channels; i++) {
140-
p_out_multiplier32[i] = bias_scale * out_scale * 2147483648;
139+
p_out_multiplier32[i] = (eff_scale >= 1.0f)
140+
? static_cast<WORD32>(2147483647)
141+
: static_cast<WORD32>(eff_scale * 2147483648.0f);
141142
p_out_shift32[i] = 0;
142143
}
143144

@@ -202,7 +203,6 @@ void xa_opt_quantized_conv1d_ncl_asym8sxsym8s_asym8s(
202203
}
203204
}
204205

205-
// Optimized NCHW 1D convolution for uint8 x uint8 -> uint8
206206
void xa_opt_quantized_conv1d_ncl_asym8uxsym8u_asym8u(
207207
KernelRuntimeContext& ctx,
208208
const Tensor& input,
@@ -240,7 +240,10 @@ void xa_opt_quantized_conv1d_ncl_asym8uxsym8u_asym8u(
240240
WORD32 x_stride = stride[0];
241241
WORD32 x_padding = padding[0];
242242
WORD32 input_zero_bias = -in_zero_point;
243-
WORD32 out_multiplier32 = bias_scale * (1. / output_scale) * 2147483648;
243+
const float eff_scale = bias_scale * (1.0f / output_scale);
244+
WORD32 out_multiplier32 = (eff_scale >= 1.0f)
245+
? static_cast<WORD32>(2147483647)
246+
: static_cast<WORD32>(eff_scale * 2147483648.0f);
244247
WORD32 out_shift32 = 0;
245248
WORD32 kernel_zero_bias = -weight_zero_point;
246249

@@ -358,7 +361,6 @@ void quantized_conv1d_ncl_per_tensor_out(
358361
Tensor& out) {
359362
// HiFi nnlib kernels only support dilation=1.
360363
// Fall back to generic implementation for dilation > 1.
361-
// Note: For 1D convolution, dilation is a single-element array.
362364
if (dilation[0] != 1) {
363365
impl::generic::native::quantized_conv1d_ncl_per_tensor_out(
364366
ctx,
@@ -419,9 +421,9 @@ void quantized_conv1d_ncl_per_tensor_out(
419421
out);
420422
}
421423
} else if (dtype == ScalarType::Byte) {
422-
// HiFi nnlib conv1d_std kernel does not support depthwise (groups > 1).
423-
// Fall back to generic implementation.
424-
if (groups > 1) {
424+
// HiFi nnlib conv1d_std kernel does not support depthwise (groups > 1)
425+
// or stride > 1. Fall back to generic implementation.
426+
if (groups > 1 || stride[0] > 1) {
425427
impl::generic::native::quantized_conv1d_ncl_per_tensor_out(
426428
ctx,
427429
input,

backends/cadence/hifi/operators/op_quantized_conv1d_nlc.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ namespace native {
2424

2525
namespace {
2626

27-
// Optimized NLC 1D convolution for int8 x int8 -> int8
2827
void xa_opt_quantized_conv1d_nlc_asym8sxsym8s_asym8s(
2928
KernelRuntimeContext& ctx,
3029
const Tensor& input,
@@ -76,10 +75,12 @@ void xa_opt_quantized_conv1d_nlc_asym8sxsym8s_asym8s(
7675
WORD32 p_out_multiplier32[out_channels];
7776
WORD32 p_out_shift32[out_channels];
7877

79-
float out_scale = 1. / output_scale;
78+
const float eff_scale = bias_scale * (1.0f / output_scale);
8079

8180
for (int i = 0; i < out_channels; i++) {
82-
p_out_multiplier32[i] = bias_scale * out_scale * 2147483648;
81+
p_out_multiplier32[i] = (eff_scale >= 1.0f)
82+
? static_cast<WORD32>(2147483647)
83+
: static_cast<WORD32>(eff_scale * 2147483648.0f);
8384
p_out_shift32[i] = 0;
8485
}
8586

@@ -144,7 +145,6 @@ void xa_opt_quantized_conv1d_nlc_asym8sxsym8s_asym8s(
144145
}
145146
}
146147

147-
// Optimized NLC 1D convolution for uint8 x uint8 -> uint8
148148
void xa_opt_quantized_conv1d_nlc_asym8uxsym8u_asym8u(
149149
KernelRuntimeContext& ctx,
150150
const Tensor& input,
@@ -176,7 +176,10 @@ void xa_opt_quantized_conv1d_nlc_asym8uxsym8u_asym8u(
176176
WORD32 x_stride = stride[stride.size() - 1];
177177
WORD32 x_padding = padding[padding.size() - 1];
178178
WORD32 input_zero_bias = -in_zero_point;
179-
WORD32 out_multiplier32 = bias_scale * (1. / output_scale) * 2147483648;
179+
const float eff_scale = bias_scale * (1.0f / output_scale);
180+
WORD32 out_multiplier32 = (eff_scale >= 1.0f)
181+
? static_cast<WORD32>(2147483647)
182+
: static_cast<WORD32>(eff_scale * 2147483648.0f);
180183
WORD32 out_shift32 = 0;
181184
WORD32 kernel_zero_bias = -weight_zero_point;
182185

@@ -237,7 +240,6 @@ void quantized_conv1d_nlc_per_tensor_out(
237240
Tensor& out) {
238241
// HiFi nnlib kernels only support dilation=1.
239242
// Fall back to generic implementation for dilation > 1.
240-
// Note: For 1D convolution, dilation is a single-element array.
241243
if (dilation[dilation.size() - 1] != 1) {
242244
impl::generic::native::quantized_conv1d_nlc_per_tensor_out(
243245
ctx,
@@ -298,9 +300,9 @@ void quantized_conv1d_nlc_per_tensor_out(
298300
out);
299301
}
300302
} else if (dtype == ScalarType::Byte) {
301-
// HiFi nnlib conv1d_std kernel does not support depthwise (groups > 1).
302-
// Fall back to generic implementation.
303-
if (groups > 1) {
303+
// HiFi nnlib conv1d_std kernel does not support depthwise (groups > 1)
304+
// or stride > 1. Fall back to generic implementation.
305+
if (groups > 1 || stride[stride.size() - 1] > 1) {
304306
impl::generic::native::quantized_conv1d_nlc_per_tensor_out(
305307
ctx,
306308
input,

0 commit comments

Comments
 (0)