Upload validated RK3576 FP16 RKNN dynamic KV-cache release
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +49 -0
- README.md +160 -0
- adapter/audio_adapter_h104_t100_fp16.rknn +3 -0
- adapter/audio_adapter_h104_t25_fp16.rknn +3 -0
- adapter/audio_adapter_h104_t50_fp16.rknn +3 -0
- adapter/audio_adapter_h104_t75_fp16.rknn +3 -0
- decoder/block_s128/layer0/block_fp16.rknn +3 -0
- decoder/block_s128/layer1/block_fp16.rknn +3 -0
- decoder/block_s128/layer2/block_fp16.rknn +3 -0
- decoder/block_s128/layer3/block_fp16.rknn +3 -0
- decoder/block_s128/layer4/block_fp16.rknn +3 -0
- decoder/block_s128/layer5/block_fp16.rknn +3 -0
- decoder/block_s128/layer6/block_fp16.rknn +3 -0
- decoder/block_s128/layer7/block_fp16.rknn +3 -0
- decoder/block_s256/layer0/block_fp16.rknn +3 -0
- decoder/block_s256/layer1/block_fp16.rknn +3 -0
- decoder/block_s256/layer2/block_fp16.rknn +3 -0
- decoder/block_s256/layer3/block_fp16.rknn +3 -0
- decoder/block_s256/layer4/block_fp16.rknn +3 -0
- decoder/block_s256/layer5/block_fp16.rknn +3 -0
- decoder/block_s256/layer6/block_fp16.rknn +3 -0
- decoder/block_s256/layer7/block_fp16.rknn +3 -0
- decoder/block_s512/layer0/block_fp16.rknn +3 -0
- decoder/block_s512/layer1/block_fp16.rknn +3 -0
- decoder/block_s512/layer2/block_fp16.rknn +3 -0
- decoder/block_s512/layer3/block_fp16.rknn +3 -0
- decoder/block_s512/layer4/block_fp16.rknn +3 -0
- decoder/block_s512/layer5/block_fp16.rknn +3 -0
- decoder/block_s512/layer6/block_fp16.rknn +3 -0
- decoder/block_s512/layer7/block_fp16.rknn +3 -0
- decoder/head_shards/shard00/head_fp16.rknn +3 -0
- decoder/head_shards/shard01/head_fp16.rknn +3 -0
- decoder/head_shards/shard02/head_fp16.rknn +3 -0
- decoder/head_shards/shard03/head_fp16.rknn +3 -0
- decoder/head_shards/shard04/head_fp16.rknn +3 -0
- decoder/head_shards/shard05/head_fp16.rknn +3 -0
- decoder/head_shards/shard06/head_fp16.rknn +3 -0
- decoder/head_shards/shard07/head_fp16.rknn +3 -0
- decoder/kv/layer0/kv_fp16.rknn +3 -0
- decoder/kv/layer1/kv_fp16.rknn +3 -0
- decoder/kv/layer2/kv_fp16.rknn +3 -0
- decoder/kv/layer3/kv_fp16.rknn +3 -0
- decoder/kv/layer4/kv_fp16.rknn +3 -0
- decoder/kv/layer5/kv_fp16.rknn +3 -0
- decoder/kv/layer6/kv_fp16.rknn +3 -0
- decoder/kv/layer7/kv_fp16.rknn +3 -0
- docs/architecture-and-operation.zh-CN.md +70 -0
- docs/benchmark-and-acceptance.zh-CN.md +95 -0
- encoder/audio_encoder_f800_fp16.rknn +3 -0
- prefill/prefill_kv_s110_fp16.rknn +3 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,52 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
adapter/audio_adapter_h104_t100_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
adapter/audio_adapter_h104_t25_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
adapter/audio_adapter_h104_t50_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
adapter/audio_adapter_h104_t75_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
decoder/block_s128/layer0/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 41 |
+
decoder/block_s128/layer1/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 42 |
+
decoder/block_s128/layer2/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 43 |
+
decoder/block_s128/layer3/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 44 |
+
decoder/block_s128/layer4/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 45 |
+
decoder/block_s128/layer5/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 46 |
+
decoder/block_s128/layer6/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 47 |
+
decoder/block_s128/layer7/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 48 |
+
decoder/block_s256/layer0/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 49 |
+
decoder/block_s256/layer1/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 50 |
+
decoder/block_s256/layer2/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 51 |
+
decoder/block_s256/layer3/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 52 |
+
decoder/block_s256/layer4/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 53 |
+
decoder/block_s256/layer5/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 54 |
+
decoder/block_s256/layer6/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 55 |
+
decoder/block_s256/layer7/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 56 |
+
decoder/block_s512/layer0/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 57 |
+
decoder/block_s512/layer1/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 58 |
+
decoder/block_s512/layer2/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 59 |
+
decoder/block_s512/layer3/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 60 |
+
decoder/block_s512/layer4/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 61 |
+
decoder/block_s512/layer5/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 62 |
+
decoder/block_s512/layer6/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 63 |
+
decoder/block_s512/layer7/block_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 64 |
+
decoder/head_shards/shard00/head_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 65 |
+
decoder/head_shards/shard01/head_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 66 |
+
decoder/head_shards/shard02/head_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 67 |
+
decoder/head_shards/shard03/head_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 68 |
+
decoder/head_shards/shard04/head_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 69 |
+
decoder/head_shards/shard05/head_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 70 |
+
decoder/head_shards/shard06/head_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 71 |
+
decoder/head_shards/shard07/head_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 72 |
+
decoder/kv/layer0/kv_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 73 |
+
decoder/kv/layer1/kv_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 74 |
+
decoder/kv/layer2/kv_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 75 |
+
decoder/kv/layer3/kv_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 76 |
+
decoder/kv/layer4/kv_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 77 |
+
decoder/kv/layer5/kv_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 78 |
+
decoder/kv/layer6/kv_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 79 |
+
decoder/kv/layer7/kv_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 80 |
+
encoder/audio_encoder_f800_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 81 |
+
prefill/prefill_kv_s110_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 82 |
+
prefill/prefill_kv_s35_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 83 |
+
prefill/prefill_kv_s60_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
| 84 |
+
prefill/prefill_kv_s85_fp16.rknn filter=lfs diff=lfs merge=lfs -text
|
README.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: other
|
| 3 |
+
library_name: rknn
|
| 4 |
+
tags:
|
| 5 |
+
- automatic-speech-recognition
|
| 6 |
+
- audio8-asr
|
| 7 |
+
- rknn
|
| 8 |
+
- rk3576
|
| 9 |
+
- npu
|
| 10 |
+
- qwen2
|
| 11 |
+
- fp16
|
| 12 |
+
base_model: Edge0/Audio8-ASR-0.1B
|
| 13 |
+
---
|
| 14 |
+
|
| 15 |
+
# Audio8-ASR-0.1B — RK3576 FP16 RKNN deployment
|
| 16 |
+
|
| 17 |
+
This repository provides a deployable FP16 RKNN partition of
|
| 18 |
+
[Edge0/Audio8-ASR-0.1B](https://huggingface.co/Edge0/Audio8-ASR-0.1B) for the
|
| 19 |
+
Rockchip RK3576 NPU, plus the board runtime needed to drive it.
|
| 20 |
+
|
| 21 |
+
It is **not** a replacement for the upstream model snapshot. Download the
|
| 22 |
+
upstream model separately for `config.json`, tokenizer/processor files and the
|
| 23 |
+
original weights used by host-side preprocessing and validation. Follow the
|
| 24 |
+
upstream model license and terms in addition to this release's files.
|
| 25 |
+
|
| 26 |
+
## What is included
|
| 27 |
+
|
| 28 |
+
The release layout is intentionally explicit:
|
| 29 |
+
|
| 30 |
+
```text
|
| 31 |
+
audio8-asr-rknn-rk3576/
|
| 32 |
+
├── encoder/audio_encoder_f800_fp16.rknn
|
| 33 |
+
├── adapter/
|
| 34 |
+
│ ├── audio_adapter_h104_t25_fp16.rknn
|
| 35 |
+
│ ├── audio_adapter_h104_t50_fp16.rknn
|
| 36 |
+
│ ├── audio_adapter_h104_t75_fp16.rknn
|
| 37 |
+
│ └── audio_adapter_h104_t100_fp16.rknn
|
| 38 |
+
├── prefill/
|
| 39 |
+
│ ├── prefill_kv_s35_fp16.rknn
|
| 40 |
+
│ ├── prefill_kv_s60_fp16.rknn
|
| 41 |
+
│ ├── prefill_kv_s85_fp16.rknn
|
| 42 |
+
│ └── prefill_kv_s110_fp16.rknn
|
| 43 |
+
├── decoder/
|
| 44 |
+
│ ├── kv/layer0..layer7/kv_fp16.rknn
|
| 45 |
+
│ ├── block_s128/layer0..layer7/block_fp16.rknn
|
| 46 |
+
│ ├── block_s256/layer0..layer7/block_fp16.rknn
|
| 47 |
+
│ ├── block_s512/layer0..layer7/block_fp16.rknn
|
| 48 |
+
│ └── head_shards/shard00..shard07/head_fp16.rknn
|
| 49 |
+
├── token_embeddings_fp32.npy
|
| 50 |
+
├── runtime/board_run_end_to_end_dynamic_buckets.py
|
| 51 |
+
├── runtime/requirements-rk3576.txt
|
| 52 |
+
├── docs/benchmark-and-acceptance.zh-CN.md
|
| 53 |
+
└── docs/architecture-and-operation.zh-CN.md
|
| 54 |
+
```
|
| 55 |
+
|
| 56 |
+
The release does not include upstream weights, source audio, ONNX intermediates,
|
| 57 |
+
or calibration/validation tensors. `token_embeddings_fp32.npy` is the decoder
|
| 58 |
+
embedding lookup table exported from the upstream snapshot; it is included
|
| 59 |
+
because the lightweight board runtime uses it for each generated token.
|
| 60 |
+
|
| 61 |
+
## Architecture
|
| 62 |
+
|
| 63 |
+
Audio8-ASR is autoregressive ASR. The runtime sequence is:
|
| 64 |
+
|
| 65 |
+
```text
|
| 66 |
+
mel features (CPU preprocessing)
|
| 67 |
+
→ audio encoder [RKNN / NPU]
|
| 68 |
+
→ audio MLP tower + projector [RKNN / NPU]
|
| 69 |
+
→ Qwen2 prefill, logits + initial K/V [RKNN / NPU]
|
| 70 |
+
→ repeated Qwen2 token decoding to EOS [RKNN / NPU]
|
| 71 |
+
```
|
| 72 |
+
|
| 73 |
+
The language decoder has 8 layers, hidden size 512, 8 attention/KV heads and
|
| 74 |
+
head dimension 64. Its K/V cache is deliberately **host-owned**, rank-3 FP32
|
| 75 |
+
buffers `[heads, Smax, head_dim] = [8, Smax, 64]`. The CPU performs only cache
|
| 76 |
+
allocation/updates, RoPE and attention-mask preparation, embedding lookup and
|
| 77 |
+
argmax. All neural layers stay in RKNN NPU graphs.
|
| 78 |
+
|
| 79 |
+
RKNN uses static shapes, while the upstream model uses a DynamicCache. The
|
| 80 |
+
runtime reproduces the behavior through cache capacities `128 → 256 → 512`.
|
| 81 |
+
When full, it copies only the valid K/V region to a larger CPU buffer and picks
|
| 82 |
+
the matching stateless NPU decoder-block graph. There is no graph-internal
|
| 83 |
+
Concat, ScatterND or runtime-owned persistent cache.
|
| 84 |
+
|
| 85 |
+
## Runtime requirements
|
| 86 |
+
|
| 87 |
+
Tested target:
|
| 88 |
+
|
| 89 |
+
```text
|
| 90 |
+
RK3576
|
| 91 |
+
RKNPU driver 0.9.8
|
| 92 |
+
RKNN Lite2 / Runtime 2.3.2
|
| 93 |
+
Python 3 with numpy and rknnlite.api
|
| 94 |
+
```
|
| 95 |
+
|
| 96 |
+
Install the `runtime/` directory and the model tree at the same deployment root
|
| 97 |
+
used in its constants, or change those paths in the runtime. The runtime takes
|
| 98 |
+
already-prepared `input_features.npy`, `input_ids.npy`, `audio_positions.npy`
|
| 99 |
+
and `rotary_inv_freq.npy`; generate them using the accompanying source archive
|
| 100 |
+
with the same upstream processor and prompt template.
|
| 101 |
+
|
| 102 |
+
For each audio length, select matching static components:
|
| 103 |
+
|
| 104 |
+
| Audio duration | audio placeholders | Adapter | Prefill graph |
|
| 105 |
+
|---:|---:|---|---|
|
| 106 |
+
| 2 s | 25 | T25 | S35 |
|
| 107 |
+
| 4 s | 50 | T50 | S60 |
|
| 108 |
+
| 6 s | 75 | T75 | S85 |
|
| 109 |
+
| 8 s | 100 | T100 | S110 |
|
| 110 |
+
|
| 111 |
+
The adapter output count must exactly equal the audio-placeholder count. Do
|
| 112 |
+
not take the first N values from T100 for a shorter prompt: that changes the
|
| 113 |
+
upstream adaptive-pooling semantics and is incorrect.
|
| 114 |
+
|
| 115 |
+
Example board invocation after preparing an S85 input:
|
| 116 |
+
|
| 117 |
+
```bash
|
| 118 |
+
python3 runtime/board_run_end_to_end_dynamic_buckets.py \
|
| 119 |
+
--input-dir prefill_input_s6 \
|
| 120 |
+
--prefill-rknn prefill/prefill_kv_s85_fp16.rknn \
|
| 121 |
+
--adapter-rknn adapter/audio_adapter_h104_t75_fp16.rknn \
|
| 122 |
+
--model /path/to/upstream-Audio8-ASR-0.1B \
|
| 123 |
+
--output result.json
|
| 124 |
+
```
|
| 125 |
+
|
| 126 |
+
The program stops at the upstream EOS id under normal operation. Its
|
| 127 |
+
`--ignore-eos` option is only for cache scheduler stress validation; do not use
|
| 128 |
+
it for user-facing transcription.
|
| 129 |
+
|
| 130 |
+
## Validated accuracy and board benchmark
|
| 131 |
+
|
| 132 |
+
All regular tests ran from real RKNN prefill through real RKNN autoregressive
|
| 133 |
+
decoding to EOS on RK3576. Each output was token-identical to the original
|
| 134 |
+
PyTorch CPU FP32 greedy reference; thus NPU-vs-FP32 CER/WER was 0%/0%.
|
| 135 |
+
|
| 136 |
+
| Audio | Prefill length | KV capacity used | Steady neural E2E | RTF | End RSS |
|
| 137 |
+
|---:|---:|---|---:|---:|---:|
|
| 138 |
+
| 2 s | 35 | 128 | 1231.49 ms | 0.616 | 1113.15 MiB |
|
| 139 |
+
| 4 s | 60 | 128 | 3371.87 ms | 0.843 | 1114.12 MiB |
|
| 140 |
+
| 6 s | 85 | 128 | 4116.86 ms | 0.686 | 1116.10 MiB |
|
| 141 |
+
| 8 s | 110 | 128 → 256 | 4344.29 ms | 0.543 | 1232.23 MiB |
|
| 142 |
+
|
| 143 |
+
`Steady neural E2E` includes encoder, adapter, prefill, decoder RKNN calls,
|
| 144 |
+
CPU K/V writes and any cache migration. It excludes model loading/runtime
|
| 145 |
+
initialization. Normal RKNN Lite `inference()` timing combines buffer transfer,
|
| 146 |
+
NPU work and synchronization; the presented numbers do not falsely claim a
|
| 147 |
+
separate DMA/H2D/D2H time.
|
| 148 |
+
|
| 149 |
+
Additional EOS-ignored scheduler stress testing ran 180 decoder steps from a
|
| 150 |
+
real 6-second prefill, triggering both `128→256` and `256→512`. All 181 NPU
|
| 151 |
+
tokens matched FP32; cache copies cost 11.21 ms and 34.70 ms respectively, and
|
| 152 |
+
the final RSS was 1379.02 MiB. This validates cache scheduling, not ASR text
|
| 153 |
+
quality beyond EOS.
|
| 154 |
+
|
| 155 |
+
## Reproducibility source archive
|
| 156 |
+
|
| 157 |
+
Export scripts, input preparation code, board probes, JSON evidence and full
|
| 158 |
+
Chinese acceptance documentation are in the companion GitHub branch:
|
| 159 |
+
|
| 160 |
+
https://github.com/Aaaou/Audio8-ASR-RKNN/tree/rknn-dynamic-kv-cache-validated
|
adapter/audio_adapter_h104_t100_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4f40ee9fdcd504765b2a95c39198e7b30cdce2f653041707681fc734d258874b
|
| 3 |
+
size 68950208
|
adapter/audio_adapter_h104_t25_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:606a5eeacfe9a83b4d2f56c7844151638df2123292f06b94cc557b1f4d22fb05
|
| 3 |
+
size 68937791
|
adapter/audio_adapter_h104_t50_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:01dd259552ee74e865ddc1e663fced34ae2ca406745d77d876629ef0c61f8ffc
|
| 3 |
+
size 68942975
|
adapter/audio_adapter_h104_t75_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9be5d1ff9d34dc73fafdf207f530c22a34855590da3ed22c2c174056bda07dc7
|
| 3 |
+
size 68948159
|
decoder/block_s128/layer0/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5e789691719abdfd1813a9d57e366a140c397af3b15d45c1e2dc3468bb1d6c41
|
| 3 |
+
size 5706842
|
decoder/block_s128/layer1/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9198906cef2e021bb19626c096db1992ae9c550d2cab2eb5ec848ed196958ff6
|
| 3 |
+
size 5706842
|
decoder/block_s128/layer2/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d7a14f145ede4d32d13fbc4083b6ca5d04a01bfa1bc723688cfde782a65979be
|
| 3 |
+
size 5706842
|
decoder/block_s128/layer3/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:db8721dd3b128f473b684f1e999a1489eaded87c279eb9c35a89e13d6be63392
|
| 3 |
+
size 5706842
|
decoder/block_s128/layer4/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:42df3fb10fca4c113a92c60afea8609505ff4be1a66611ef6fab18862e71eae0
|
| 3 |
+
size 5706842
|
decoder/block_s128/layer5/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b59f45a049706687c0051d4f3b8be7ee35a233bab8dd61833277b50b9e257ba4
|
| 3 |
+
size 5706842
|
decoder/block_s128/layer6/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:cfde3e70b280b6ffdbd1197c72b61258a3e69740bebe3bda02317a2e6b3a10ec
|
| 3 |
+
size 5706842
|
decoder/block_s128/layer7/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5cd0a2aa5aa597b40c889afb5f9a33df95fd7ac2bc02bd4e76f97038fdacb3b4
|
| 3 |
+
size 5706842
|
decoder/block_s256/layer0/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:933dfdcd2c831df15df10cdce3f6d659d9161dc37d2fd7379d29df9f157f23b3
|
| 3 |
+
size 5717594
|
decoder/block_s256/layer1/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:13454a9f052bdb974ff5f7deb4b67a6913c778d530f8cc03a1c50688f364fa70
|
| 3 |
+
size 5717594
|
decoder/block_s256/layer2/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:bb8021e743ee1d528922d2f7d9349f829f3639308af4f141db796e4e8ad9749e
|
| 3 |
+
size 5717594
|
decoder/block_s256/layer3/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6471d7974c489499fe3d488f4f28b2363e0d786d2640c8cbc1e3fbbe167637fc
|
| 3 |
+
size 5717594
|
decoder/block_s256/layer4/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6e7495b16a6437d74ca304081564caa2779fda10fb0d21961b2f4be0744d92fc
|
| 3 |
+
size 5717594
|
decoder/block_s256/layer5/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e6ea02c345f559281fbaadcd2f008ad1d73dffa669bdb8df195de2915c47543a
|
| 3 |
+
size 5717594
|
decoder/block_s256/layer6/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4806f8d72d6fc90f8aecc2e022be1e098857bfef094373504e7a5443ae1a9252
|
| 3 |
+
size 5717594
|
decoder/block_s256/layer7/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:00bd10a619285b80f659f4b0f15677bd88d43ec825e0a61bbbf844738e907631
|
| 3 |
+
size 5717594
|
decoder/block_s512/layer0/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ae8ff11cffc050e3aed17ededf766a69a0c7bee6cfabcbac8aa2c0ac68d596ff
|
| 3 |
+
size 5739098
|
decoder/block_s512/layer1/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:87c12f32a19462d37a4d1b53911bac16155903b51dc475e619a4e68fe075e6e1
|
| 3 |
+
size 5739098
|
decoder/block_s512/layer2/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b5c9b0c1c933bf1dd00ee207956d768213b614d89369d79c8da4578d659b1c5b
|
| 3 |
+
size 5739098
|
decoder/block_s512/layer3/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c6e442610370344a4304363c2f750bf166edc79d5290a383772c07f8a2b9a41f
|
| 3 |
+
size 5739098
|
decoder/block_s512/layer4/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e7a9e6c78777e975e4e64c81dbc190b7c62e4295e7ab0c372a0a72ea0442c69e
|
| 3 |
+
size 5739098
|
decoder/block_s512/layer5/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1ec3ad64e9f4596712f23816db6b41ab5a8a3a36f39091d334eed1a983162a97
|
| 3 |
+
size 5739098
|
decoder/block_s512/layer6/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d93d10eb9d62719860ad38d2e4728040d33016ecfdbf05457bb41373e39ab376
|
| 3 |
+
size 5739098
|
decoder/block_s512/layer7/block_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:fce264635762b53ed43166e35c026fa14ace4666441dc525b14b42d59241f98d
|
| 3 |
+
size 5739098
|
decoder/head_shards/shard00/head_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:36020a743b7b7a7f49a2e076ebeb353b1502afab1bb37b52918ab617adf3b16f
|
| 3 |
+
size 19526321
|
decoder/head_shards/shard01/head_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:578ba0c7c5e63c1687bc851384019b91c7aaa86a91bc23a5dfe5db926c246f50
|
| 3 |
+
size 19526321
|
decoder/head_shards/shard02/head_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:64335a3db4f4b54bac29dd4b79c6c34df4ce57fd5f8c3a0b0b6b3471c073672d
|
| 3 |
+
size 19526321
|
decoder/head_shards/shard03/head_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ce40f1a1105f70c75efcff1003ac859bd9d256e43c68a3796295d07eca4282a7
|
| 3 |
+
size 19526321
|
decoder/head_shards/shard04/head_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:22fda36159907ed3d2a640902a90c3482422f327e75369ad40bf3838e442a919
|
| 3 |
+
size 19526321
|
decoder/head_shards/shard05/head_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:410832b318d1890b7221b2c82f9a356e4164b22db53fc04fd4137a0eccacbd1c
|
| 3 |
+
size 19526321
|
decoder/head_shards/shard06/head_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a3bd1b398a5bccbb9790468a96f4447d9095761a00d2466913f607fd023c3f46
|
| 3 |
+
size 19526321
|
decoder/head_shards/shard07/head_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a1df27beed56626fcdeaac99872f57d2bb63ab39f7360f7fb0f3e5e4c01134cd
|
| 3 |
+
size 19526321
|
decoder/kv/layer0/kv_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a86a70a715ad90f063dac90e2e2f46153253ba4793343089ab1229cb4901f949
|
| 3 |
+
size 1167000
|
decoder/kv/layer1/kv_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9544cbfeb17368be16a3dcad991218df564ae48f64d7e5b13deea28361cec8dd
|
| 3 |
+
size 1167000
|
decoder/kv/layer2/kv_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:fa021be3bdb14c2f1e0931bf1d646a4801ba6d38ab3bd41d0aaa12beb140b89f
|
| 3 |
+
size 1167000
|
decoder/kv/layer3/kv_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7770bcf11d390a42a116a11e99acf62365dedce5e9d6f2154a03238687ee0e23
|
| 3 |
+
size 1167000
|
decoder/kv/layer4/kv_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:111446ce7395b82e0b11741e8f819327b66737d6bfeff09cc0e9f502e04e6ce2
|
| 3 |
+
size 1167000
|
decoder/kv/layer5/kv_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d89912dbe2a72a23f90fa55a2277947b2bc03e1ad70f93ec012919dfc81857f9
|
| 3 |
+
size 1167000
|
decoder/kv/layer6/kv_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:80ff77e7caf6aa317f5b559fe011d5ac0e30ab8f139f2f0aad11fd201c1c0b77
|
| 3 |
+
size 1167000
|
decoder/kv/layer7/kv_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5b2bc7a96937d3a35740167c67df2698398a5f9997c8ee8c8da098caa1b86a20
|
| 3 |
+
size 1167000
|
docs/architecture-and-operation.zh-CN.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# RK3576 / RKNN KV-cache 策略调研
|
| 2 |
+
|
| 3 |
+
## 结论
|
| 4 |
+
|
| 5 |
+
RK3576 NPU 可以执行带有 cache 输入、Concat、Gather/Slice、Attention 的静态图;因此不能说硬件“完全不支持 KV cache”。但 RKNN Lite 普通 `inference()` 是无状态函数接口,没有一个通用的、跨调用自动持久化的 KV-cache 对象。所谓“由 NPU 自己更新 cache”必须在图中显式实现写回(Concat、ScatterND、预分配 buffer + position 等),并不等同于 runtime 自动保存状态。
|
| 6 |
+
|
| 7 |
+
当前项目第一版用了 Transformers `DynamicCache.update()` 导出路径。该路径把 cache 更新/Concat trace 进 ONNX,再由 RKNN 重写 layout。它在 ONNX Runtime 上正确,但 RK3576 上第 0 层的 projection 正常、Concat 后即出现约 140% L2 偏差,说明当前问题是编译后 cache layout/reorder/Gather/Concat 语义,而非 RK3576 缺少 attention 算力。
|
| 8 |
+
|
| 9 |
+
本地 TTS RK3576 研究也记录了同类事实:完整 AR FP16 图曾在实板 `rs-gather` submit 失败;问题收敛到 compiler 为 attention / ScatterND 生成的固定重排 Gather 路径。另一个 Fast AR 图在 position 1 分叉;无状态 FFN 子图则稳定。这些记录支持“状态写回/重排路径是风险中心”的判断。
|
| 10 |
+
|
| 11 |
+
## 三种实现路线
|
| 12 |
+
|
| 13 |
+
### 1. NPU 图内动态 Concat/ScatterND
|
| 14 |
+
|
| 15 |
+
```text
|
| 16 |
+
NPU 读取旧 cache → NPU 计算新 K/V → NPU Concat/Scatter 写回 → Attention
|
| 17 |
+
```
|
| 18 |
+
|
| 19 |
+
优点:理论上减少 CPU 拼接,数据路径短。
|
| 20 |
+
|
| 21 |
+
风险:当前已经失败;容易触发 RKNN 的 `-rs-gather`、layout 重排、ScatterND 和静态轴问题。即使 compiler 能生成 `.rknn`,也必须逐位置验证,不能以首轮能运行作为通过标准。
|
| 22 |
+
|
| 23 |
+
### 2. CPU 管理 cache,NPU 读只读历史 cache(推荐第一修复路线)
|
| 24 |
+
|
| 25 |
+
```text
|
| 26 |
+
CPU 保存 old K/V
|
| 27 |
+
NPU 计算当前 token 的 attention、FFN、logits 和 new K/V
|
| 28 |
+
CPU concat(old, new_delta)
|
| 29 |
+
```
|
| 30 |
+
|
| 31 |
+
优点:跨调用状态明确,CPU concat 只有约 3.63 ms;失败时边界清楚,可按 token 调试。缺点:每步需要搬运历史 K/V,且 decoder 图需要避免再次调用 `DynamicCache.update()` 的内部 Concat。
|
| 32 |
+
|
| 33 |
+
### 3. 固定最大 cache + NPU 位置写入
|
| 34 |
+
|
| 35 |
+
```text
|
| 36 |
+
预分配 [B,H,Smax,D],用 cache_position 写入当前位置
|
| 37 |
+
```
|
| 38 |
+
|
| 39 |
+
优点:固定 shape,有机会实现 zero-copy/少搬运。
|
| 40 |
+
|
| 41 |
+
风险:仍依赖 Scatter/Masked assignment、position 和 layout;应在路线 2 证明数学递归正确后再尝试。
|
| 42 |
+
|
| 43 |
+
## 当前推荐顺序
|
| 44 |
+
|
| 45 |
+
```text
|
| 46 |
+
先修正 decoder 图,去除 DynamicCache.update() 的图内写回/Concat;
|
| 47 |
+
让 CPU 跨步保存并追加 K/V,NPU 图只消费明确的只读历史 cache;
|
| 48 |
+
先做第 0 层和 token 1 的逐中间量比较;
|
| 49 |
+
通过后扩展 8 层与 token 0/1/2/3/16/EOS;
|
| 50 |
+
最后再试固定最大 cache 的 NPU 写入。
|
| 51 |
+
```
|
| 52 |
+
|
| 53 |
+
## 验收门槛
|
| 54 |
+
|
| 55 |
+
KV cache 是递归状态,门槛比一次性 encoder 更严格:
|
| 56 |
+
|
| 57 |
+
```text
|
| 58 |
+
每层 K/V delta normalized L2 <= 0.5%:候选通过
|
| 59 |
+
0.5%~1%:警告,不能直接部署
|
| 60 |
+
>1%:不通过
|
| 61 |
+
decode logits normalized L2 <= 0.5%,且 top-1 token 不变
|
| 62 |
+
token 0/1/2/3/16/EOS 全部一致
|
| 63 |
+
最终 CER/WER 不出现稳定退化
|
| 64 |
+
```
|
| 65 |
+
|
| 66 |
+
当前图:logits L2 113.16%、K/V delta 最大 L2 143.56%、token 13→3711,属于明确失败。
|
| 67 |
+
|
| 68 |
+
## 时间解释
|
| 69 |
+
|
| 70 |
+
当前 `97.68 ms` 是普通 `rknn.inference()` 混合总时间,包含输入准备、runtime/layout、driver submit、NPU 计算、输出回收和同步;不能称为纯搬运。单独可测的 CPU concat 是 3.63 ms,历史 K/V 输入约 3.44 MiB,delta 输出 32 KiB。后续应继续使用 runtime layer table 报告 NPU operator time 和 CPU boundary time,把剩余量称为 runtime/data-boundary overhead,而不是 DMA 纯时间。
|
docs/benchmark-and-acceptance.zh-CN.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Audio8-ASR:动态 KV-cache bucket 与多时长端到端验收
|
| 2 |
+
|
| 3 |
+
**结论:通过本阶段验收。** 在 RK3576 上,FP16 RKNN 路径以 CPU 持有 KV buffer、NPU 运行全部神经网络图的方式,完成了 2、4、6、8 秒音频的真实预填充、自回归生成和 EOS 终止。四组输出与原始 PyTorch CPU FP32 标准路径逐 token 完全一致,故 NPU 相对标准路径的 CER/WER 均为 **0% / 0%**。8 秒组还实际触发并验证了 `128 → 256` KV bucket 迁移,迁移后继续生成至 EOS,序列仍完全一致。
|
| 4 |
+
|
| 5 |
+
这里的“端到端”指:标准音频特征(mel)输入 → RKNN encoder → RKNN audio tower/projector → RKNN prefill → RKNN decoder 自回归至 EOS。音频文件读取、重采样/特征生成和 tokenizer 文本解码尚未包进同一个板端命令,故不把它们计入下述 neural-inference 时延。
|
| 6 |
+
|
| 7 |
+
## 已落地的动态窗口机制
|
| 8 |
+
|
| 9 |
+
原模型的 Qwen2 decoder 用 `DynamicCache`,最大 position 为 32768、没有 sliding window;本地 prefill ONNX 本身是固定长度且没有 `past_key_values` 输入。因此,RKNN 静态 shape 的部署实现以 bucket 复刻该语义:从最小可用的 `Smax=128` 开始;当写入位置达到上限时,CPU 将 8 层 K/V 的**有效区**复制到更大 buffer,切换同一层对应的 `block_256.rknn` 或 `block_512.rknn`,并从同一 token、同一 RoPE position 继续计算。`128→256` 已由自然 ASR EOS 样本触发;`256→512` 已由下文的 FP32 对照压力路径触发,尚未由自然 ASR EOS 样本触发。
|
| 10 |
+
|
| 11 |
+
跨 token 的 cache 采用 `[heads, Smax, head_dim] = [8, Smax, 64]` 的 rank-3 外部布局。CPU 只做 buffer 管理、KV 原地写入、RoPE/mask 准备、argmax 和 embedding lookup;每层新的 K/V projection、attention/FFN block、最终 RMSNorm/LM-head shard 都经 RKNN 在 NPU 上执行。没有图内 `DynamicCache`、Concat、ScatterND 或隐式 runtime cache state。
|
| 12 |
+
|
| 13 |
+
## 精度与功能验收
|
| 14 |
+
|
| 15 |
+
| 截取音频 | prefill 序列长度 | audio placeholder / adapter bucket | 生成 token 数(含首 token 与 EOS) | EOS | KV bucket | 与 CPU FP32 token | NPU vs CPU FP32 CER / WER |
|
| 16 |
+
|---:|---:|---:|---:|---|---|---|---|
|
| 17 |
+
| 2 s | 35 | 25 / T25 | 7 | 151645 | 128 | 7/7,一致 | 0% / 0% |
|
| 18 |
+
| 4 s | 60 | 50 / T50 | 19 | 151645 | 128 | 19/19,一致 | 0% / 0% |
|
| 19 |
+
| 6 s | 85 | 75 / T75 | 23 | 151645 | 128 | 23/23,一致 | 0% / 0% |
|
| 20 |
+
| 8 s | 110 | 100 / T100 | 23 | 151645 | 128→256 | 23/23,一致 | 0% / 0% |
|
| 21 |
+
|
| 22 |
+
`CER/WER` 使用小写、去标点、压缩空白的英文规范化;CER 不计空格。由于每条 token id 序列完全相同,文本解码也必然完全相同。标准路径中的 2/4/6 秒文本依次为:
|
| 23 |
+
|
| 24 |
+
| 时长 | 标准 FP32 文本(与 RKNN 相同) |
|
| 25 |
+
|---:|---|
|
| 26 |
+
| 2 s | `Quilter is apostle.` |
|
| 27 |
+
| 4 s | `Mr. Quilter is the apostle of the middle classes, and we are glad.` |
|
| 28 |
+
| 6 s / 8 s | `Mr. Quilter is the apostle of the middle classes, and we are glad to welcome his gospel.` |
|
| 29 |
+
|
| 30 |
+
### 短音频问题及修复验证
|
| 31 |
+
|
| 32 |
+
首版短音频 runtime 将固定 `T100` adapter 的前 N 个 embedding 截取给 prompt。这与原模型不同:原模型会先运行 tower,再以**实际 placeholder 数**做 adaptive pooling。该错误使 2 秒组 embedding 相对 L2 达 156.97%,首 token 从 FP32 的 2183 错变为 12275;它是开发层面的 adapter pooling 形状错误,不是 decoder KV-cache 或量化精度问题。
|
| 33 |
+
|
| 34 |
+
现已将 adapter 导出为 T25、T50、T75、T100 四个静态 RKNN 图,runtime 按实际 placeholder 数选择,且强制要求 adapter 输出 token 数恰好等于 placeholder 数。板端探针的修复后结果如下。
|
| 35 |
+
|
| 36 |
+
| 时长 | adapter embedding 相对 L2(对 FP32 注入 embedding) | RKNN prefill logits 相对 L2(理想 embedding 对 FP32) | NPU frontend 相对理想 prefill logits L2 | 首 token FP32 / RKNN |
|
| 37 |
+
|---:|---:|---:|---:|---|
|
| 38 |
+
| 2 s | 0.7531% | 0.5552% | 0.5581% | 2183 / 2183 |
|
| 39 |
+
| 4 s | 1.1082% | 1.4813% | 0.8022% | 12275 / 12275 |
|
| 40 |
+
| 6 s | 0.8460% | 0.4250% | 0.6936% | 12275 / 12275 |
|
| 41 |
+
|
| 42 |
+
这些 L2 是数值健康度的辅助指标,不单独定义 ASR 是否可接受;本验收的硬判据是 greedy 自回归过程中的完整 token、EOS 与文本误差。四条均通过。
|
| 43 |
+
|
| 44 |
+
## RK3576 板端性能(稳态神经网络路径)
|
| 45 |
+
|
| 46 |
+
“稳态 E2E”是 encoder + adapter + prefill + decoder NPU 调用 + CPU KV 原地写入 + 已发生的 bucket copy;它排除了模型加载、RKNN runtime 初始化和释放。`process wall` 是整段 Python 进程壁钟时间,包含这些一次性成本,因此不能与稳态时延混用。
|
| 47 |
+
|
| 48 |
+
| 音频 | Encoder | Adapter | Prefill | Decoder NPU 总计 | CPU KV 写入 | bucket 迁移拷贝 | 稳态 E2E | RTF | process wall | RSS(结束时) |
|
| 49 |
+
|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|
|
| 50 |
+
| 2 s | 408.55 ms | 58.06 ms | 103.95 ms | 659.53 ms | 1.40 ms | — | **1231.49 ms** | **0.616** | 10179.55 ms | 1113.15 MiB |
|
| 51 |
+
| 4 s | 389.64 ms | 45.97 ms | 84.42 ms | 2844.99 ms | 6.84 ms | — | **3371.87 ms** | **0.843** | 13259.35 ms | 1114.12 MiB |
|
| 52 |
+
| 6 s | 413.23 ms | 62.38 ms | 150.35 ms | 3482.55 ms | 8.35 ms | — | **4116.86 ms** | **0.686** | 13771.63 ms | 1116.10 MiB |
|
| 53 |
+
| 8 s | 405.26 ms | 58.87 ms | 165.19 ms | 3690.71 ms | 7.81 ms | **16.46 ms** (`128→256`) | **4344.29 ms** | **0.543** | 15017.83 ms | 1232.23 MiB |
|
| 54 |
+
|
| 55 |
+
8 秒组的 16.46 ms 是 CPU 对 16 个 K/V tensor 的有效内容重新分配/复制与 bucket 切换成本;不是 NPU 内部自动 cache 更新。迁移后 RSS 比未跨界的 6 秒组高约 116 MiB,符合同时驻留 S256 block 图及更大 K/V host buffer 的预期。
|
| 56 |
+
|
| 57 |
+
解码 NPU 调用内含 Host↔NPU input/output buffer 提交、NPU 执行和同步等待,当前 RKNN Lite `inference()` API 没有为这三项提供可用的逐项计时。因此本报告不伪造“搬运 xx ms”:上述 `decoder NPU 总计`是三者的合计;CPU KV 写入和 CPU bucket copy 则已独立计时。后续若要拆出 DMA/H2D/D2H,需切换至 RKNN zero-copy / memory binding API 并对 buffer 生命周期单独埋点。
|
| 58 |
+
|
| 59 |
+
## 产物与可复现入口
|
| 60 |
+
|
| 61 |
+
核心 runtime 是 [board_run_end_to_end_dynamic_buckets.py](C:/Users/Administrator/Documents/ChatGPT/asr/board_run_end_to_end_dynamic_buckets.py),它新增 `--adapter-rknn` 并对 adapter token 数与 placeholder 数做硬校验。`export_audio_adapter_bucket.py` 已修正为按 `--tokens` 命名 ONNX,以生成 T25/T50/T75/T100 图。
|
| 62 |
+
|
| 63 |
+
原始板端结果与 CPU 标准参考:
|
| 64 |
+
|
| 65 |
+
- [2 秒 RKNN 结果](C:/Users/Administrator/Documents/ChatGPT/asr/dynamic_length_s2.json)、[2 秒 FP32 参考](C:/Users/Administrator/Documents/ChatGPT/asr/standard_length_s2.json)
|
| 66 |
+
- [4 秒 RKNN 结果](C:/Users/Administrator/Documents/ChatGPT/asr/dynamic_length_s4.json)、[4 秒 FP32 参考](C:/Users/Administrator/Documents/ChatGPT/asr/standard_length_s4.json)
|
| 67 |
+
- [6 秒 RKNN 结果](C:/Users/Administrator/Documents/ChatGPT/asr/dynamic_length_s6.json)、[6 秒 FP32 参考](C:/Users/Administrator/Documents/ChatGPT/asr/standard_length_s6.json)
|
| 68 |
+
- [8 秒动态跨 bucket 结果](C:/Users/Administrator/Documents/ChatGPT/asr/dynamic_length_s8.json)
|
| 69 |
+
- [FP32 参考生成工具](C:/Users/Administrator/Documents/ChatGPT/asr/generate_length_standard_reference.py)
|
| 70 |
+
|
| 71 |
+
## 二级迁移压力验收:256→512
|
| 72 |
+
|
| 73 |
+
在上述自然 ASR 验收之外,增加了一组**缓存调度压力测试**,目的不是评价 EOS 后文本的语义,而是让同一条真实 6 秒音频的 NPU/FP32 decoder 在首次 EOS 后按 greedy 规则继续运行,以构造超过 256 的真实 KV context。两端均执行相同的“忽略 EOS、仍将当前 argmax token 回灌”规则;这不是正常用户可见的 ASR 解码模式。
|
| 74 |
+
|
| 75 |
+
| 项目 | 结果 |
|
| 76 |
+
|---|---|
|
| 77 |
+
| 起始 prefill 长度 | 85 |
|
| 78 |
+
| 后续 decoder step | 180 |
|
| 79 |
+
| 总 token(含 prefill 首 token) | 181 |
|
| 80 |
+
| 实际迁移 | `128→256`(11.21 ms);`256→512`(34.70 ms) |
|
| 81 |
+
| 最终 bucket | 512 |
|
| 82 |
+
| NPU 对 FP32 token | **181/181 完全一致** |
|
| 83 |
+
| 首个不一致 token | 无 |
|
| 84 |
+
| NPU decoder 合计 | 32611.01 ms |
|
| 85 |
+
| CPU KV 原地写入合计 | 61.94 ms |
|
| 86 |
+
| 稳态全链路合计 | 33321.24 ms |
|
| 87 |
+
| 结束 RSS | 1379.02 MiB |
|
| 88 |
+
|
| 89 |
+
这证明 S512 RKNN decoder block 可在迁移后读取由 CPU 复制的 rank-3 K/V buffer,并维持与 FP32 相同的贪心轨迹。其结果是**二级 cache 调度的功能和数值验收通过**;但由于该轨迹被明确设计为 EOS 后继续回灌,不能将它误解为自然语音的 WER/CER 验收。自然 ASR 部分的质量结论仍以 2/4/6/8 秒四条真实 EOS 样本的 0% NPU-vs-FP32 CER/WER 为准。
|
| 90 |
+
|
| 91 |
+
对应的可复现产物:
|
| 92 |
+
|
| 93 |
+
- [256→512 板端压力结果](</C:/Users/Administrator/Documents/ChatGPT/asr/dynamic_stress_s6_256_to_512.json>)
|
| 94 |
+
- [对应 FP32 强制延长参考](</C:/Users/Administrator/Documents/ChatGPT/asr/forced_decoder_reference_s6_180.json>)
|
| 95 |
+
- [FP32 强制延长参考生成器](</C:/Users/Administrator/Documents/ChatGPT/asr/generate_forced_decoder_reference.py>)
|
encoder/audio_encoder_f800_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:eba40833fd2111d06089ac6d34fd9c418a37bc96167c4d0a1353941541a5e19a
|
| 3 |
+
size 389160766
|
prefill/prefill_kv_s110_fp16.rknn
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:09386971d142ab6a801b725503b338f824cd5ad0547b5127533320e2e9ad0b0a
|
| 3 |
+
size 212455543
|