2372640_en-US

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

2372640_en-US

2372640_en-US

Conv2D on i.MX 8M Plus VX delegate produces incorrect output when either spatial kernel dim >= 16

Summary

On i.MX 8M Plus EVK, Conv2D ops where either spatial kernel dimension (H or W) is >= 16 produce incorrect output under the VX delegate (libvx_delegate.so). The model loads, the Conv2D is bound to an OPENVX kernel by vsi_nn_kernel_selector, error_during_init/prepare/invoke are all 0, and inference latency is normal, but the int8 output is saturated to a single value (int8 = 127) at every position across diverse inputs.

The boundary is sharp between K=15 and K=16 along either spatial axis. This matches the threshold of the documented stride > 15 limit (https://community.nxp.com/t5/i-MX-Processors/Conv2D-not-working-with-stride-16-for-NPU-Kernel-crashe...).

Two questions:

  1. Is this kernel-dim ≥ 16 cliff a known limitation, and if so could it be added to the i.MX Machine Learning User's Guide (UG10166) Conv2D constraints section?

  2. Should vsi_nn_op_conv2d::op_check (or the VX delegate's partition logic) reject this case at graph-compile time so the op falls back to CPU? The current "accept, run, return constant int8=127, no diagnostic" behaviour is unsafe — a deployed model with a large kernel appears to load and run normally.


Environment

Component Value

Boardi.MX 8M Plus EVK
BSPNXP i.MX Release Distro 6.18-whinlatter (VERSION_ID=6.18-whinlatter)
KernelLinux 6.18.2-1.0.0-gf49f45233f7b SMP PREEMPT (aarch64)
libvx_delegate.so md52f88ec0871d18298bfa357ddaaea4d6d
libGAL.so md5af4806f617b23363b3be69c4dad2dc05
libOpenVX.so{,.1,.1.3.0} md592f85c32746d4d0b38800e21503d13d0 (all three identical)
imx-gpu-viv package1:6.4.11.p4.4-aarch64-r0
tim-vx package1.2.2-r0
OVxlib (runtime-reported)OVXLIB_VERSION==1.2.14
TFLite runtimeTFLite 2.19.0 (/usr/bin/tensorflow-lite-2.19.0/examples/benchmark_model)

Reproducer

The attached conv_1x17_broken.tflite (2,136 bytes) is a single-Conv2D artifact: kernel (1, 17), input 1×1×1000×5 int8, output 1×1×1000×8 int8, per-channel int8 weight quantization, padding=SAME, stride=(1,1), no fused activation.

# On the i.MX 8M Plus board:
python3 reproduce.py conv_1x17_broken.tflite        # exits 1: BROKEN, saturated to int8=127
python3 reproduce.py conv_1x15_torch_control.tflite # exits 0: OK (K<16, same pipeline)

reproduce.py (attached, depends only on tflite_runtime and numpy) feeds 6 seeded random int8 inputs through plain and VX-delegated interpreters and reports mean|Δ|, max|Δ|, and the count of unique int8 output values from the VX path.


Kernel-size sweep

Single-Conv2D unit-test models, INT8 PTQ. mean|Δ| board VX vs board CPU on the same int8 input bytes; uniq_VX = unique int8 output values across 6 inputs (out of 256).

kernel (H, W) mean |Δ| uniq_VX result

(1, 11)0.03256OK
(1, 15)0.02256OK
(1, 16)134.91BROKEN (constant int8=127)
(1, 17)136.91BROKEN (constant int8=127)
(1, 23)130.51BROKEN (constant int8=127)
(15, 1)0.11256OK
(17, 1)136.91BROKEN (constant int8=127)
(23, 1)129.31BROKEN (constant int8=127)
(3, 3), (5, 5), (7, 7)< 0.2256OK
(15, 15) (area 225)0.41256OK
(3, 23)123.41BROKEN (constant int8=127)
(5, 15)0.24256OK

The threshold applies independently to H and W. In every broken case the VX output saturates to int8 = 127 at every position — saturation to the positive int8 extreme (rather than to output_zp or 0) suggests either multiplier-shift overflow before the final clamp, or a fixed value being written into the output tile in place of the MAC result. The issue doesn't seem related to kernel area (e.g., 15x15 works fine)

The threshold is necessary but not sufficient — some int8 weight value patterns at K ≥ 16 trigger the bug, others don't. We've done byte-level isolation experiments (grafting individual TFLite tensor fields between broken and non-broken artifacts) narrowing the value-pattern trigger to specific tensor fields. Happy to share the isolation results and tooling if useful.


Verbose log excerpt (VSI_NN_LOG_LEVEL=5, broken case)

INFO: Vx delegate: error_during_init    set to 0.
INFO: Vx delegate: error_during_prepare set to 0.
INFO: Vx delegate: error_during_invoke  set to 0.
I [vsi_nn_CreateGraph:1327] OVXLIB_VERSION==1.2.14
D [setup_node:535] Setup node id[3] uid[30000] op[DATACONVERT]
D [setup_node:535] Setup node id[0] uid[1]     op[PERMUTE]
D [setup_node:535] Setup node id[1] uid[2]     op[CONV2D]
D [setup_node:535] Setup node id[2] uid[3]     op[PERMUTE]
D [setup_node:535] Setup node id[4] uid[30001] op[DATACONVERT]
D [vsi_nn_kernel_selector:1286] Instance OPENVX node with kernel "conv2d"

Full log attached as vsi_nn_log_level_5_conv_1x17.txt.


Attachments

Bundled as bug_report_artifacts.tar.gz

  • conv_1x17_broken.tflite — 2,136-byte broken artifact.
  • conv_1x15_torch_control.tflite — 2,056-byte sub-threshold control, same pipeline.
  • reproduce.py — board-side reproducer (tflite_runtime + numpy only).
  • vsi_nn_log_level_5_conv_1x17.txt — full verbose log.

Additional artifacts available on request: byte-level isolation tooling, a structurally-identical working (1, 17) artifact for delta analysis, full sufficient-condition graft results.

i.MX 8M | i.MX 8M Mini | i.MX 8M NanoLinuxSuspected Software DefectRe: Conv2D on i.MX 8M Plus VX delegate produces incorrect output when either spatial kernel dim >

Hi @themis_stewart 

Thanks for your information, i am checking with internal team about your two questions.

Best Regards,
Zhiming

Re: Conv2D on i.MX 8M Plus VX delegate produces incorrect output when either spatial kernel dim >

Hello @themis_stewart 

Please try the following patch based on L6.18.2 to fallback the op to the CPU if the kernel size is > 16

Best Regards,
Zhiming

Re: Conv2D on i.MX 8M Plus VX delegate produces incorrect output when either spatial kernel dim >

Thanks very much for the quick turnaround on this — we've applied and tested the guard patch and can confirm it resolves the issue on our side.

We built the patched libvx_delegate.so from the lf-6.18.2_1.0.0 delegate source with your op_map.cc change and validated it on our i.MX 8M Plus EVK against the minimal reproducers from the original report. With the patch:

  • The affected INT8 Conv2D (spatial kernel ≥ 16) is now cleanly rejected by the delegate and falls back to TFLite CPU, with the log message making the fallback explicit — no more silent saturation to int8 = 127. Output matches the CPU reference exactly.
  • Our production models (kernels ≤ 15) are unaffected — still fully delegated to the NPU, so the guard doesn't over-trigger.

The CPU-fallback path is performing well for us in practice, though the fallback is naturally slower than a model able to run fully on the NPU. We're happy to share detailed before/after benchmarks privately if they'd be useful for your regression coverage.

Thanks again — much appreciated.

タグ(1)
評価なし
バージョン履歴
最終更新日:
火曜日
更新者: