Instructions to use patdev/k3-a40-bootstrap with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use patdev/k3-a40-bootstrap with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf patdev/k3-a40-bootstrap:BF16 # Run inference directly in the terminal: llama cli -hf patdev/k3-a40-bootstrap:BF16
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf patdev/k3-a40-bootstrap:BF16 # Run inference directly in the terminal: llama cli -hf patdev/k3-a40-bootstrap:BF16
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf patdev/k3-a40-bootstrap:BF16 # Run inference directly in the terminal: ./llama-cli -hf patdev/k3-a40-bootstrap:BF16
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf patdev/k3-a40-bootstrap:BF16 # Run inference directly in the terminal: ./build/bin/llama-cli -hf patdev/k3-a40-bootstrap:BF16
Use Docker
docker model run hf.co/patdev/k3-a40-bootstrap:BF16
- LM Studio
- Jan
- Ollama
How to use patdev/k3-a40-bootstrap with Ollama:
ollama run hf.co/patdev/k3-a40-bootstrap:BF16
- Unsloth Desktop
- Docker Model Runner
How to use patdev/k3-a40-bootstrap with Docker Model Runner:
docker model run hf.co/patdev/k3-a40-bootstrap:BF16
- Lemonade
How to use patdev/k3-a40-bootstrap with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull patdev/k3-a40-bootstrap:BF16
Run and chat with the model
lemonade run user.k3-a40-bootstrap-BF16
List all available models
lemonade list
- Atomic Chat
verdict TRT-LLM : noyau MoE 4 bits reserve a sm90
Browse files
reports/2026-08-23-mxfp4-deblocage-trtllm-et-familles-moe.md
CHANGED
|
@@ -1,166 +1,270 @@
|
|
| 1 |
-
#
|
| 2 |
-
|
| 3 |
-
Deux questions tranchées, toutes deux par de la lecture de code et de l'arithmétique vérifiable
|
| 4 |
-
plutôt que par des essais successifs : **pourquoi TensorRT-LLM refusait nos modèles**, et
|
| 5 |
-
**quelles variantes MoE sont réellement fabricables** à partir de Qwen3.8 et de Kimi K3.
|
| 6 |
-
|
| 7 |
-
## 1. Le mur TensorRT-LLM : trois formats, une seule issue
|
| 8 |
-
|
| 9 |
-
Le mode de quantification `536`, longtemps opaque, se décode depuis `QuantMode` :
|
| 10 |
-
|
| 11 |
-
```
|
| 12 |
-
536 = FP8_ROWWISE (512) + PER_TOKEN (16) + PER_CHANNEL (8)
|
| 13 |
-
```
|
| 14 |
-
|
| 15 |
-
Le FP8 officiel d'Ornith est donc du **FP8 dynamique** (poids par canal, activations par jeton).
|
| 16 |
-
Or `CutlassFusedMoE._get_quant_method()` ne connaît que ces méthodes MoE :
|
| 17 |
-
|
| 18 |
-
| condition | méthode |
|
| 19 |
-
|---|---|
|
| 20 |
-
| `has_fp8_qdq()` | `FP8QDQFusedMoEMethod` |
|
| 21 |
-
| `has_fp8_block_scales()` | `DeepSeekFP8BlockScalesFusedMoEMethod` |
|
| 22 |
-
| `has_nvfp4()` | `NVFP4CutlassFusedMoEMethod` |
|
| 23 |
-
| `is_int4_weight_only_per_group()` | `WInt4AFP8FusedMoEMethod` (**chemin W4A8**) |
|
| 24 |
-
| **`has_w4a16_mxfp4()`** | **`WFP4A16FusedMoEMethod`** |
|
| 25 |
-
| `has_w4a8_mxfp4_*()`, `has_mxfp8()` | méthodes MXFP4 / MXFP8 |
|
| 26 |
-
| sinon | `raise ValueError("Unsupported quantization mode")` |
|
| 27 |
-
|
| 28 |
-
D'où les deux échecs constatés : l'INT4 groupwise tombe sur la méthode **W4A8**, qui déréférence
|
| 29 |
-
un `input_scale` absent du checkpoint (`'NoneType' object has no attribute 'device'`), et le FP8
|
| 30 |
-
rowwise ne correspond à aucune entrée (`mode [536]`).
|
| 31 |
-
|
| 32 |
-
### La sortie : MXFP4
|
| 33 |
-
|
| 34 |
-
`ModelConfig.get_mxfp4_quant_algo()` décide selon la carte :
|
| 35 |
-
|
| 36 |
-
```python
|
| 37 |
-
if get_sm_version() >= 100: # Blackwell
|
| 38 |
-
return QuantAlgo.W4A8_MXFP4_MXFP8 # (ou _FP8 avec le backend TRITON)
|
| 39 |
-
else: # Ada sm89 = notre cas
|
| 40 |
-
return QuantAlgo.W4A16_MXFP4
|
| 41 |
-
```
|
| 42 |
-
|
| 43 |
-
Et `load_hf_quant_config()` accepte un checkpoint HF déclarant `quant_method: "mxfp4"`. Donc
|
| 44 |
-
**sur sm89, un checkpoint MXFP4 route vers `WFP4A16FusedMoEMethod`, qui est implémentée**.
|
| 45 |
-
`compressed-tensors` fournit le préréglage `MXFP4A16`, ce qui rend la production du checkpoint
|
| 46 |
-
immédiate avec `llmcompressor`.
|
| 47 |
-
|
| 48 |
-
**Conséquence : le verdict « TRT-LLM ne peut pas servir nos MoE » était vrai des formats que nous
|
| 49 |
-
avions, pas du moteur.** Il ne manquait pas un opérateur custom, il manquait le bon format d'entrée.
|
| 50 |
-
|
| 51 |
-
### Le dense charge, lui
|
| 52 |
-
|
| 53 |
-
`Qwen/Qwen3.8-27B-FP8` est en `fp8` **block-scales** (`weight_block_size: [128,128]`), chemin
|
| 54 |
-
supporté. Il a chargé sans erreur de quantification et n'a échoué que sur un `cudaMalloc out of
|
| 55 |
-
memory` : 27 Go de poids sur une carte de 49 Go, cache KV non borné. Correction :
|
| 56 |
-
`KvCacheConfig(free_gpu_memory_fraction=0.25)` et `max_seq_len=4096`.
|
| 57 |
-
|
| 58 |
-
## 2. ONNX Runtime + TensorRT : l'EP existait, la bibliothèque manquait
|
| 59 |
-
|
| 60 |
-
Le rapport du 23/08 concluait « EP absent de la build ». C'était vrai de la roue
|
| 61 |
-
**`onnxruntime-genai-cuda`**, et faux de **`onnxruntime-gpu` 1.29.0**, qui annonce :
|
| 62 |
-
|
| 63 |
-
```
|
| 64 |
-
['TensorrtExecutionProvider', 'CUDAExecutionProvider', 'CPUExecutionProvider']
|
| 65 |
-
```
|
| 66 |
-
|
| 67 |
-
L'EP échouait seulement à charger `libnvinfer.so.10`, TensorRT n'étant pas installé sur le pod.
|
| 68 |
-
Piège de version : `tensorrt-cu13-libs` fournit `libnvinfer.so.**11**` ; ORT 1.29 exige la **10**,
|
| 69 |
-
qui vient de `tensorrt-cu12-libs==10.*`.
|
| 70 |
-
|
| 71 |
-
##
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
`
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# TensorRT-LLM sur Ada : le fond du problème est un noyau Hopper-only (23/08/2026, nuit 2)
|
| 2 |
+
|
| 3 |
+
Deux questions tranchées, toutes deux par de la lecture de code et de l'arithmétique vérifiable
|
| 4 |
+
plutôt que par des essais successifs : **pourquoi TensorRT-LLM refusait nos modèles**, et
|
| 5 |
+
**quelles variantes MoE sont réellement fabricables** à partir de Qwen3.8 et de Kimi K3.
|
| 6 |
+
|
| 7 |
+
## 1. Le mur TensorRT-LLM : trois formats, une seule issue
|
| 8 |
+
|
| 9 |
+
Le mode de quantification `536`, longtemps opaque, se décode depuis `QuantMode` :
|
| 10 |
+
|
| 11 |
+
```
|
| 12 |
+
536 = FP8_ROWWISE (512) + PER_TOKEN (16) + PER_CHANNEL (8)
|
| 13 |
+
```
|
| 14 |
+
|
| 15 |
+
Le FP8 officiel d'Ornith est donc du **FP8 dynamique** (poids par canal, activations par jeton).
|
| 16 |
+
Or `CutlassFusedMoE._get_quant_method()` ne connaît que ces méthodes MoE :
|
| 17 |
+
|
| 18 |
+
| condition | méthode |
|
| 19 |
+
|---|---|
|
| 20 |
+
| `has_fp8_qdq()` | `FP8QDQFusedMoEMethod` |
|
| 21 |
+
| `has_fp8_block_scales()` | `DeepSeekFP8BlockScalesFusedMoEMethod` |
|
| 22 |
+
| `has_nvfp4()` | `NVFP4CutlassFusedMoEMethod` |
|
| 23 |
+
| `is_int4_weight_only_per_group()` | `WInt4AFP8FusedMoEMethod` (**chemin W4A8**) |
|
| 24 |
+
| **`has_w4a16_mxfp4()`** | **`WFP4A16FusedMoEMethod`** |
|
| 25 |
+
| `has_w4a8_mxfp4_*()`, `has_mxfp8()` | méthodes MXFP4 / MXFP8 |
|
| 26 |
+
| sinon | `raise ValueError("Unsupported quantization mode")` |
|
| 27 |
+
|
| 28 |
+
D'où les deux échecs constatés : l'INT4 groupwise tombe sur la méthode **W4A8**, qui déréférence
|
| 29 |
+
un `input_scale` absent du checkpoint (`'NoneType' object has no attribute 'device'`), et le FP8
|
| 30 |
+
rowwise ne correspond à aucune entrée (`mode [536]`).
|
| 31 |
+
|
| 32 |
+
### La sortie : MXFP4
|
| 33 |
+
|
| 34 |
+
`ModelConfig.get_mxfp4_quant_algo()` décide selon la carte :
|
| 35 |
+
|
| 36 |
+
```python
|
| 37 |
+
if get_sm_version() >= 100: # Blackwell
|
| 38 |
+
return QuantAlgo.W4A8_MXFP4_MXFP8 # (ou _FP8 avec le backend TRITON)
|
| 39 |
+
else: # Ada sm89 = notre cas
|
| 40 |
+
return QuantAlgo.W4A16_MXFP4
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
Et `load_hf_quant_config()` accepte un checkpoint HF déclarant `quant_method: "mxfp4"`. Donc
|
| 44 |
+
**sur sm89, un checkpoint MXFP4 route vers `WFP4A16FusedMoEMethod`, qui est implémentée**.
|
| 45 |
+
`compressed-tensors` fournit le préréglage `MXFP4A16`, ce qui rend la production du checkpoint
|
| 46 |
+
immédiate avec `llmcompressor`.
|
| 47 |
+
|
| 48 |
+
**Conséquence : le verdict « TRT-LLM ne peut pas servir nos MoE » était vrai des formats que nous
|
| 49 |
+
avions, pas du moteur.** Il ne manquait pas un opérateur custom, il manquait le bon format d'entrée.
|
| 50 |
+
|
| 51 |
+
### Le dense charge, lui
|
| 52 |
+
|
| 53 |
+
`Qwen/Qwen3.8-27B-FP8` est en `fp8` **block-scales** (`weight_block_size: [128,128]`), chemin
|
| 54 |
+
supporté. Il a chargé sans erreur de quantification et n'a échoué que sur un `cudaMalloc out of
|
| 55 |
+
memory` : 27 Go de poids sur une carte de 49 Go, cache KV non borné. Correction :
|
| 56 |
+
`KvCacheConfig(free_gpu_memory_fraction=0.25)` et `max_seq_len=4096`.
|
| 57 |
+
|
| 58 |
+
## 2. ONNX Runtime + TensorRT : l'EP existait, la bibliothèque manquait
|
| 59 |
+
|
| 60 |
+
Le rapport du 23/08 concluait « EP absent de la build ». C'était vrai de la roue
|
| 61 |
+
**`onnxruntime-genai-cuda`**, et faux de **`onnxruntime-gpu` 1.29.0**, qui annonce :
|
| 62 |
+
|
| 63 |
+
```
|
| 64 |
+
['TensorrtExecutionProvider', 'CUDAExecutionProvider', 'CPUExecutionProvider']
|
| 65 |
+
```
|
| 66 |
+
|
| 67 |
+
L'EP échouait seulement à charger `libnvinfer.so.10`, TensorRT n'étant pas installé sur le pod.
|
| 68 |
+
Piège de version : `tensorrt-cu13-libs` fournit `libnvinfer.so.**11**` ; ORT 1.29 exige la **10**,
|
| 69 |
+
qui vient de `tensorrt-cu12-libs==10.*`.
|
| 70 |
+
|
| 71 |
+
## 2 bis. Les deux verrous restants, et leurs correctifs
|
| 72 |
+
|
| 73 |
+
Ouvrir la voie MXFP4 ne suffisait pas : deux défauts de TRT-LLM 1.3.0rc22 se dressaient encore.
|
| 74 |
+
Tous deux sont du Python — aucun noyau CUDA n'a été nécessaire, contrairement à ce qu'annonçaient
|
| 75 |
+
les sessions précédentes. Publiés dans `patches_trtllm/`.
|
| 76 |
+
|
| 77 |
+
### a. Le mappage compressed-tensors ignore le MXFP4
|
| 78 |
+
|
| 79 |
+
`llmcompressor` écrit `quant_method: "compressed-tensors"` avec `format: "mxfp4-pack-quantized"`,
|
| 80 |
+
et TRT-LLM **a** une branche pour ce `quant_method`. Mais
|
| 81 |
+
`update_quant_config_from_compressed_tensors()` ne couvre que trois cas — FP8 par canal, FP8 par
|
| 82 |
+
blocs, NVFP4 (`strategy: "tensor_group"`, groupe 16) — et pas le MXFP4A16 : `strategy: "group"`,
|
| 83 |
+
`group_size: 32`, `input_activations: null`.
|
| 84 |
+
|
| 85 |
+
Pire, elle exécute `inputs_quant_config["strategy"]` **sans tester la nullité**, donc elle lève un
|
| 86 |
+
`TypeError` avant d'atteindre le moindre test utile. Correctif : garde de nullité, plus une
|
| 87 |
+
branche `num_bits == 4 and type == "float" and strategy == "group" and input_activations is None`
|
| 88 |
+
→ `QuantAlgo.W4A16_MXFP4`.
|
| 89 |
+
|
| 90 |
+
### b. Le cache mRoPE mélange CPU et GPU
|
| 91 |
+
|
| 92 |
+
`_prepare_qwen_vl_mrope_config()` construit `deltas` par `torch.cat()` de tenseurs issus des
|
| 93 |
+
paramètres multimodaux — donc du CPU — puis les écrit dans `mrope_position_deltas_cache`, sur GPU :
|
| 94 |
+
|
| 95 |
+
```
|
| 96 |
+
RuntimeError: Expected all tensors to be on the same device,
|
| 97 |
+
but got source is on cpu, different from other tensors on cuda:0
|
| 98 |
+
```
|
| 99 |
+
|
| 100 |
+
Le symptôme remonté est trompeur : le modèle **charge entièrement**, l'exécuteur démarre, et
|
| 101 |
+
l'erreur ne se manifeste qu'à la première génération, sous la forme
|
| 102 |
+
`AssertionError: Sampling failed` dans la boucle d'événements. Correctif : un `.to(device, dtype)`
|
| 103 |
+
avant `index_copy_`.
|
| 104 |
+
|
| 105 |
+
## 2 ter. L'EP TensorRT d'ONNX Runtime est bien actif
|
| 106 |
+
|
| 107 |
+
Après installation de `tensorrt-cu12-libs==10.*` :
|
| 108 |
+
|
| 109 |
+
```
|
| 110 |
+
providers actifs: ['TensorrtExecutionProvider', 'CUDAExecutionProvider', 'CPUExecutionProvider']
|
| 111 |
+
TRT_EP_ACTIF
|
| 112 |
+
```
|
| 113 |
+
|
| 114 |
+
Le verdict « EP absent de la build », qui tenait depuis trois sessions, ne valait que pour la roue
|
| 115 |
+
`onnxruntime-genai-cuda`. `onnxruntime-gpu` 1.29.0 l'embarque. Piège de version à retenir :
|
| 116 |
+
`tensorrt-cu13-libs` fournit `libnvinfer.so.**11**`, qu'ORT 1.29 ne reconnaît pas — il exige la **10**.
|
| 117 |
+
|
| 118 |
+
## 2 quater. Verdict final : le noyau MoE 4 bits est réservé à Hopper
|
| 119 |
+
|
| 120 |
+
Les deux correctifs ci-dessus ont fait leur travail — et c'est justement ce qui rend le résultat
|
| 121 |
+
concluant, puisque toutes les causes d'échec antérieures ont été éliminées une à une.
|
| 122 |
+
|
| 123 |
+
### Le dense s'exécute, mais échoue sur la qualité et la vitesse
|
| 124 |
+
|
| 125 |
+
```
|
| 126 |
+
TRTLLM_DENSE 89 jetons en 3.04s = 29.2 tok/s
|
| 127 |
+
TEXTE: 一串string string string string ... 串串串根__sontacs/串/他的__ivr
|
| 128 |
+
```
|
| 129 |
+
|
| 130 |
+
Le correctif mRoPE débloque bien la génération de bout en bout. Mais la sortie est du **charabia**
|
| 131 |
+
— le chemin FP8 block-scales est numériquement faux pour cette architecture — et 29,2 tok/s
|
| 132 |
+
représentent **4,6× moins que les 134,1 de vLLM** sur la même carte. Doublement disqualifié.
|
| 133 |
+
Ceci reproduit indépendamment, cause de plantage éliminée, l'observation « charge mais sort du
|
| 134 |
+
charabia » d'une session antérieure.
|
| 135 |
+
|
| 136 |
+
### Le MoE MXFP4 est refusé explicitement
|
| 137 |
+
|
| 138 |
+
Le correctif de mappage fonctionne : le checkpoint est reconnu, routé vers `W4A16_MXFP4`, puis
|
| 139 |
+
vers `WFP4A16FusedMoEMethod`. Et là :
|
| 140 |
+
|
| 141 |
+
```
|
| 142 |
+
NotImplementedError: WFP4A16 MoE is unsupported on SM89.
|
| 143 |
+
```
|
| 144 |
+
|
| 145 |
+
Dans `_torch/modules/fused_moe/quantization.py` :
|
| 146 |
+
|
| 147 |
+
```python
|
| 148 |
+
if module.sm_version == 90: # Hopper, et rien d'autre
|
| 149 |
+
module.interleave = [128 // self.group_size for k_shape in (...)]
|
| 150 |
+
else:
|
| 151 |
+
raise NotImplementedError(f"WFP4A16 MoE is unsupported on SM{module.sm_version}.")
|
| 152 |
+
```
|
| 153 |
+
|
| 154 |
+
**Le noyau MoE 4 bits de TRT-LLM n'existe que pour sm90.** `get_mxfp4_quant_algo()` renvoie
|
| 155 |
+
pourtant `W4A16_MXFP4` pour tout `sm < 100` : sur Ada, il désigne donc du code mort.
|
| 156 |
+
|
| 157 |
+
### Tableau de synthèse : aucun chemin MoE quantifié sur Ada
|
| 158 |
+
|
| 159 |
+
| format | résultat sur sm89 |
|
| 160 |
+
|---|---|
|
| 161 |
+
| INT4 groupwise (AWQ) | routé vers `WInt4AFP8FusedMoEMethod` (W4A8) → `input_scale` absent |
|
| 162 |
+
| FP8 rowwise (Ornith officiel) | aucune méthode MoE — `Unsupported quantization mode [536]` |
|
| 163 |
+
| **MXFP4 / W4A16** | **noyau réservé à sm90** |
|
| 164 |
+
| FP8 block-scales (dense, pas MoE) | s'exécute, mais charabia et 29,2 tok/s contre 134,1 |
|
| 165 |
+
|
| 166 |
+
**Conclusion : TensorRT-LLM ne peut pas servir un MoE quantifié sur Ada.** Ce n'est plus une
|
| 167 |
+
question de format — c'est un noyau absent, refusé explicitement. Les deux seules issues sont
|
| 168 |
+
une carte **Hopper (H100/H200, sm90)**, où le chemin MXFP4 devrait fonctionner tel quel avec nos
|
| 169 |
+
deux correctifs, ou l'écriture d'un noyau CUTLASS sm89 avec sa disposition d'entrelacement —
|
| 170 |
+
du vrai CUDA cette fois, pas du Python.
|
| 171 |
+
|
| 172 |
+
Vu que vLLM délivre 134 tok/s sur cette carte et 1 380 j/s agrégés à 32 sessions, l'effort ne se
|
| 173 |
+
justifierait que si l'on migrait vers du Hopper pour d'autres raisons.
|
| 174 |
+
|
| 175 |
+
## 3. ONNX GenAI sur Ada : 163,2 tok/s, devant vLLM
|
| 176 |
+
|
| 177 |
+
Le graphe réparé (`model_fixed3.onnx`) mesuré sur la RTX 6000 Ada :
|
| 178 |
+
|
| 179 |
+
| moteur, même carte, solo | débit |
|
| 180 |
+
|---|---:|
|
| 181 |
+
| vLLM (Ornith INT4) | 134,1 tok/s |
|
| 182 |
+
| **ONNX Runtime GenAI (CUDA EP)** | **163,2 tok/s** |
|
| 183 |
+
| ONNX GenAI sur L40S (pour mémoire) | 126,9 tok/s |
|
| 184 |
+
|
| 185 |
+
Texte français correct et cohérent. **Réserve essentielle** : ORT GenAI n'a pas de traitement
|
| 186 |
+
continu par lots — ces 163 tok/s sont un débit *mono-session*, sans équivalent agrégé
|
| 187 |
+
multi-agents. La piste reste « edge / session unique », mais elle y bat vLLM.
|
| 188 |
+
|
| 189 |
+
Piège : `libcufft.so.12` manquait au chemin alors qu'il est présent dans
|
| 190 |
+
`site-packages/nvidia/cu13/lib` du venv — un simple `LD_LIBRARY_PATH`.
|
| 191 |
+
|
| 192 |
+
## 4. Le plancher des variantes MoE demandées
|
| 193 |
+
|
| 194 |
+
La question « faire un A4B / A9B / A12B » se tranche avant tout essai, en calculant le **socle
|
| 195 |
+
incompressible** : les paramètres actifs à chaque jeton quoi qu'on fasse aux experts.
|
| 196 |
+
|
| 197 |
+
**Erreur de méthode commise puis corrigée** : une première estimation appliquait la formule de
|
| 198 |
+
l'attention classique aux 64 couches, donnant un socle de 7,24 B. Qwen3.8 est **hybride** —
|
| 199 |
+
48 couches d'attention linéaire, 16 pleines, avec porte de sortie (`attn_output_gate: true`).
|
| 200 |
+
Les tailles réelles, lues sur les formes des tenseurs :
|
| 201 |
+
|
| 202 |
+
| composant | taille |
|
| 203 |
+
|---|---:|
|
| 204 |
+
| experts routés (16 × 1024) | 16,106 B |
|
| 205 |
+
| **attention linéaire (48 couches)** | **5,562 B** |
|
| 206 |
+
| embeddings (248 320 × 5 120, non liés) | 2,543 B |
|
| 207 |
+
| attention pleine (16 couches) | 1,678 B |
|
| 208 |
+
| expert partagé | 1,007 B |
|
| 209 |
+
| routeur | 0,005 B |
|
| 210 |
+
| **socle** | **9,78 B** |
|
| 211 |
+
|
| 212 |
+
Avec l'expert partagé, le **plancher absolu** — zéro expert routé — est de **10,79 B actifs**.
|
| 213 |
+
|
| 214 |
+
| granularité | top-k | actifs/jeton |
|
| 215 |
+
|---|---|---:|
|
| 216 |
+
| 64 × 256 (dépôt parent) | 2 | 11,29 B |
|
| 217 |
+
| 64 × 256 | 5 | **12,05 B** (le plus proche de 12 B) |
|
| 218 |
+
| 16 × 1024 | 2 | 12,80 B |
|
| 219 |
+
| 16 × 1024 | 4 | 14,81 B |
|
| 220 |
+
|
| 221 |
+
**A4B et A9B sont donc impossibles pour cette famille** : ils sont sous le plancher.
|
| 222 |
+
Le seul levier serait d'amputer l'attention linéaire (5,56 B) ou les embeddings (2,54 B), ce qui
|
| 223 |
+
demande une distillation et ne serait plus le même modèle.
|
| 224 |
+
|
| 225 |
+
**Correction d'un chiffre que j'avais publié** : `patdev/Qwen3.8-27B-MoE-A12B-L4` fait
|
| 226 |
+
**11,29 B actifs** (64 × 256, top-2), pas 8,75 B comme je l'avais d'abord calculé. Son README
|
| 227 |
+
annonçant « ~12,2 B » était à peu près juste.
|
| 228 |
+
|
| 229 |
+
### Kimi K3
|
| 230 |
+
|
| 231 |
+
| composant | valeur |
|
| 232 |
+
|---|---:|
|
| 233 |
+
| attention (96 têtes × 74, 93 couches) | 18,94 B |
|
| 234 |
+
| embeddings | 2,35 B |
|
| 235 |
+
| **socle** | **21,29 B** |
|
| 236 |
+
| actif/jeton actuel (top-16 sur 320 experts) | 119,6 B |
|
| 237 |
+
| poids de `lovedheart/Kimi-K3-Lite` | **1 561 Go** |
|
| 238 |
+
|
| 239 |
+
**Les trois cibles Kimi sont impossibles, A12B comprise** : le socle fait 21,29 B avant qu'un seul
|
| 240 |
+
expert ne s'active. Et matériellement, 1 561 Go de poids contre 200 Go de disque et 49 Go de VRAM
|
| 241 |
+
interdisent jusqu'au chargement. Aucune quantité de calcul ne change ce constat.
|
| 242 |
+
|
| 243 |
+
## 5. Ce qui a été fabriqué
|
| 244 |
+
|
| 245 |
+
| dépôt | actifs/jeton | total | nature |
|
| 246 |
+
|---|---:|---:|---|
|
| 247 |
+
| `patdev/Qwen3.8-MoE-27B-A12B` | **12,80 B** | 26,90 B | re-partition **exacte** : 16 experts × 1 024, top-2. Aucun poids modifié — fusion de 4 tranches contiguës du FFN parent. Total conservé. |
|
| 248 |
+
|
| 249 |
+
Un squelette A4B a été construit puis **supprimé** : il visait 3,96 B, sous le plancher de
|
| 250 |
+
10,79 B, et son découpage de `q_proj` ignorait la porte de sortie (`attn_output_gate`), donc
|
| 251 |
+
produisait des formes fausses. Double invalidité, aucun intérêt à le conserver.
|
| 252 |
+
|
| 253 |
+
## 6. Pièges opérationnels payés cette nuit
|
| 254 |
+
|
| 255 |
+
- **`bash /run.sh` ne doit jamais être tué**, quel que soit son PID : `start_pod.sh` l'exécute en
|
| 256 |
+
`exec` et sshd en est un enfant, donc sa mort redémarre le conteneur. Deux interruptions de
|
| 257 |
+
service à cause de ça. Ne tuer que `vllm [s]erve`.
|
| 258 |
+
- **Le superviseur du bootstrap ne relance pas un `vllm serve` tué** : la restauration doit être
|
| 259 |
+
explicite.
|
| 260 |
+
- **`exec $(cat cmd.txt)`** perd les guillemets : `--limit-mm-per-prompt '{"video":0}'` devient
|
| 261 |
+
invalide et l'endpoint reste mort. Repasser par le bootstrap, qui reconstruit la commande
|
| 262 |
+
depuis l'environnement.
|
| 263 |
+
- **La garde `if __name__ == '__main__':` est obligatoire** pour TRT-LLM *et* pour `vllm.LLM()` :
|
| 264 |
+
les deux lancent des processus par spawn qui ré-importent le script. Sans elle, `MPI_ABORT`
|
| 265 |
+
d'un côté, « attempt to start a new process before bootstrapping » de l'autre. Deux échecs
|
| 266 |
+
attribués à tort aux moteurs.
|
| 267 |
+
- **Le jeton HF du pod est mort** depuis la rotation qui a suivi la fuite : les envois vers HF et
|
| 268 |
+
la publication du cache de compilation v73 échouaient silencieusement.
|
| 269 |
+
- **Convertir un modèle en place double l'occupation disque** : supprimer chaque shard source dès
|
| 270 |
+
qu'il est converti divise le pic par deux et a rendu inutile l'agrandissement du disque.
|
reports/README.md
CHANGED
|
@@ -13,7 +13,7 @@ en a conclu, pour ne pas le refaire.
|
|
| 13 |
| 2026-08-23 | `2026-08-23-pont-et-integration-claude-code.md` | Pont sous charge (fuite de connexions), compaction Claude Code (`[1m]`, réponse vide), compteur de jetons en direct, débit solo ressenti |
|
| 14 |
| 2026-08-23 | `2026-08-23-l4-graphes-cuda-et-multi-modeles.md` | L4 : 12,4 → 75,7 tok/s en activant les graphes CUDA (×6) ; rendement par Go/s vs notre TP=2 ; Kimi-K3 / Qwen3.8 déjà servis par le bootstrap ; TRT-LLM impasse confirmée |
|
| 15 |
| 2026-08-23 | `2026-08-23-tensorrt-et-onnx-mesures.md` | TRT-LLM **impasse fermée** (INT4 et FP8, sur L40S et sur Ada) ; graphe ONNX réparé et fonctionnel (126,9 tok/s L40S) ; baseline L4 corrigée 13→76 ; MTP à 29 % d’acceptation même en FP8 |
|
| 16 |
-
| 2026-08-23 | `2026-08-23-mxfp4-deblocage-trtllm-et-familles-moe.md` | **
|
| 17 |
|
| 18 |
Convention : `AAAA-MM-JJ-sujet.md`, français, sources en URL, « non trouvé » explicite, et une
|
| 19 |
section finale « ce que nous en avons fait » quand c'est appliqué.
|
|
|
|
| 13 |
| 2026-08-23 | `2026-08-23-pont-et-integration-claude-code.md` | Pont sous charge (fuite de connexions), compaction Claude Code (`[1m]`, réponse vide), compteur de jetons en direct, débit solo ressenti |
|
| 14 |
| 2026-08-23 | `2026-08-23-l4-graphes-cuda-et-multi-modeles.md` | L4 : 12,4 → 75,7 tok/s en activant les graphes CUDA (×6) ; rendement par Go/s vs notre TP=2 ; Kimi-K3 / Qwen3.8 déjà servis par le bootstrap ; TRT-LLM impasse confirmée |
|
| 15 |
| 2026-08-23 | `2026-08-23-tensorrt-et-onnx-mesures.md` | TRT-LLM **impasse fermée** (INT4 et FP8, sur L40S et sur Ada) ; graphe ONNX réparé et fonctionnel (126,9 tok/s L40S) ; baseline L4 corrigée 13→76 ; MTP à 29 % d’acceptation même en FP8 |
|
| 16 |
+
| 2026-08-23 | `2026-08-23-mxfp4-deblocage-trtllm-et-familles-moe.md` | **TRT-LLM : le noyau MoE 4 bits est reserve a sm90** — aucun chemin MoE quantifie sur Ada (2 correctifs Python ecrits, valables sur Hopper) ; l'EP TensorRT existe bien dans onnxruntime-gpu 1.29 ; **ONNX GenAI 163,2 tok/s sur Ada, devant vLLM** ; planchers reels Qwen3.8 (10,79 B) et Kimi K3 (21,29 B) : A4B et A9B impossibles |
|
| 17 |
|
| 18 |
Convention : `AAAA-MM-JJ-sujet.md`, français, sources en URL, « non trouvé » explicite, et une
|
| 19 |
section finale « ce que nous en avons fait » quand c'est appliqué.
|