Ricerca

Misurato, con i dati per verificarlo.

Il ragionamento anticipato non è esatto, quindi è stato misurato su risposte verificabili. Ogni tabella qui sotto ha il suo script e il suo JSON nel repository, e il diario di ricerca conserva le note di lavoro, le più recenti per prime.

Metodo

Problemi con una risposta numerica nota, scritti in italiano in tempo reale: 5-8 caratteri al secondo, qualche pausa naturale, Invio subito dopo l'ultimo carattere, senza rileggere. Lo script è research/thinking_ahead.py; scrive ogni problema con e senza ragionamento anticipato e registra l'attesa per la prima parola della risposta, i token di ragionamento in totale e quelli rimasti dopo Invio, e se la risposta è giusta.

I modelli sono Qwen3 Q4_K_M in thinking mode su llama.cpp (b11747). La macchina di riferimento è una RTX 2060 con 6 GB di VRAM (i5-10400, 16 GB DDR4, Windows 11): Qwen3-4B sta nella VRAM a circa 83 tok/s, Qwen3-14B no (38% sulla GPU, circa 5 tok/s). La seconda macchina è un MacBook Pro M2 Pro, 16 GB, con Metal. Due esecuzioni degli stessi 24 problemi differiscono fino a un secondo nella media: confronta righe misurate una dopo l'altra.

Risultati

Modello · macchinaProblemiCorretteAttesa media, senzaAttesa media, MAFDETMediana, senza → MAFDET
Qwen3-4B
RTX 2060 · 6 GB
2424/24 in entrambi i casi12.2 s3.2 s10.7 s → 2.9 s
Qwen3-14B
RTX 2060 · 6 GB
66/6 in entrambi i casi108 s47 s—
Qwen3-4B
MacBook Pro M2 Pro · 16 GB
2424/24 in entrambi i casi18.1 s5.6 s16.7 s → 4.1 s
Qwen3-14B
MacBook Pro M2 Pro · 16 GB
66/6 in entrambi i casi32.7 s12.1 s26.5 s → 11.7 s

Ragionamento anticipato, Qwen3-4B sulla RTX 2060, 24 problemi (research/thinking_ahead.py, dati thinking_ahead_4b.json):

Senza ragionamento anticipatomafdet strike
Risposte corrette24/2424/24
Attesa mediana per la prima parola10.7 s2.9 s
Attesa media12.2 s3.2 s
Più velocein 24 problemi su 24
Ragionamento in totale944 token662 token
Ragionamento rimasto dopo Invio944 token244 token

Stessa accuratezza, meno ragionamento in totale (il materiale raccolto durante la digitazione evita al modello di ricominciare da capo), e quasi due terzi di esso fatti prima di Invio. La cornice degli appunti conta: una cornice generica ha dato 22/24 e una mediana di 4.4 s; nessuna cornice ha dato 22/24, 6.9 s e il 70% di ragionamento in più. Con la cornice a lista, la riga di esempio e un logit bias contro parole come user, incomplete, typing durante il ragionamento anticipato, la quota di frasi negli appunti che parlano del messaggio in sé invece del suo contenuto è passata dall'86% al 17-26%.

Risposta esatta in anticipo

Qwen3-4B, senza ragionamento, pausa prima di Invio con il testo invariato: la risposta stessa viene scritta in anticipo, e quella parte è esatta (con decoding greedy, identica token per token a quella avviata dopo Invio; verificato).

RispostaScritta prima di InvioRisposta completa sullo schermo dopo Invio, strikeSenza strike
300 token2001.2 s3.5 s
168 token168 (tutta)istantanea1.9 s

Modelli più grandi

Quello che il modello può fare prima di Invio è limitato dal tempo di digitazione × la sua velocità di scrittura:

ModelloSta in 6 GB?ScriveRagionamento scritto durante un messaggio di 30 s
Qwen3-4Bsì83 tok/squasi tutto
Qwen3-8Bno, in parte sulla CPU13-16 tok/s130-280 token
Qwen3-14Bno, in parte sulla CPU5 tok/scirca 160 token

Anche così, sul 14B (6 problemi, 6/6 corrette in entrambi i casi) il ragionamento anticipato dimezza l'attesa media dopo Invio: 108 s → 47 s, con 164 token di ragionamento scritti prima di Invio in media. Le singole esecuzioni variano molto (lo stesso problema ha impiegato 106 s una volta e 154 s un'altra), quindi 6 problemi danno l'ordine di grandezza. La lettura anticipata guadagna tanto più quanto più grande è il modello: il 14B legge un documento incollato da 3.000 token in circa 10 s, tutti nascosti mentre scrivi.

Indovinare il finale (--branches, sperimentale). Il ragionamento rimasto dopo Invio riguarda per lo più la fine del messaggio, che arriva per ultima. Con --branches 1 il modello indovina anche come finirai e ragiona sull'ipotesi in uno slot tutto suo. Stessi 24 problemi, due esecuzioni ciascuno: 48/48 corrette, attesa media 4.17 s → 3.51 s, decimo più lento 7.9 s → 5.3 s, 14 messaggi su 48 indovinati esattamente. Un guadagno modesto, soprattutto sulle risposte più lente, su 24 problemi non ancora significativo (sign test p = 0.15). Sul 14B nessun ramo ha mai iniziato a ragionare prima di Invio: nell'app un ramo è dato solo ai modelli che stanno nella VRAM.

Un modello piccolo che raccoglie per uno grande (--gatherer, sperimentale). Un Qwen3-0.6B veloce, anche fine-tuned per questo, che scrive materiale mentre digiti perché il 14B lo legga a Invio. Sulla RTX 2060 non batte il 14B che ragiona in anticipo da solo: 47 s contro 60 s senza addestramento e 79-86 s con fine-tuning; perfino materiale ideale scritto a mano dà 62 s, o 49 s se presentato come ragionamento del modello stesso. Il 14B lo legge, poi rifà i calcoli. Le domande aperte per chi vuole portare avanti la cosa sono nel README.

Su un Mac

MacBook Pro M2 Pro, 16 GB, macOS 26.2, llama.cpp con Metal; gli stessi script e gli stessi problemi.

M2 ProSenza ragionamento anticipatomafdet strike
Qwen3-4B, 24 problemi: corrette24/2424/24
Attesa mediana16.7 s4.1 s
Attesa media18.1 s5.6 s
Ragionamento in totale / rimasto dopo Invio966 / 966773 / 248
Qwen3-14B, 6 problemi: corrette6/66/6
Attesa mediana26.5 s11.7 s
Attesa media32.7 s12.1 s

Il 4B scrive a 54 tok/s sull'M2 Pro (83-87 sulla RTX 2060), quindi entrambe le attese sono più lunghe che sul PC, e il ragionamento anticipato ne toglie circa la stessa quota. Il 14B è dove il Mac fa la differenza: Metal può usare 12 GB della memoria unificata, quindi l'intero modello è sulla GPU e scrive a 18 tok/s. Durante le esecuzioni il Mac ha raggiunto la pressione termica Heavy per qualche minuto. Dati: thinking_ahead_4b_m2pro.json, thinking_ahead_4b_m2pro_fixed.json, thinking_ahead_14b_m2pro.json.

Provato, e perché no

  • --recycle (le risposte alle versioni precedenti del messaggio come bozze n-gram): +4% di velocità di decode con digitazione naturale, +20% sul codice, primo token leggermente più tardi.
  • --draft (Qwen3-0.6B che abbozza per il 14B): sulla GPU toglie VRAM al 14B, che quindi esegue più layer sulla CPU (4.8 → 3.5 tok/s); sulla CPU guadagna l'8% con bozze da 4 token e dimezza la velocità di lettura.
  • Il ragionamento anticipato come bozza per lo speculative decoding dopo Invio: non più veloce sul 4B (73 tok/s in entrambi i casi) e più lento sul 14B (5.0 → 3.1 tok/s), perché i layer sulla CPU calcolano ogni token della bozza e solo l'11% dei token abbozzati era giusto. Script: research/notes_as_draft.py.
  • IQ4_XS al posto di Q4_K_M sul 4B (RTX 4070 SUPER): 4% più veloce, una risposta peggiore su 28. Non vale la pena sul 4B; sul 14B, dove è il 31% più veloce con le stesse risposte, è in valutazione.

Fatto chiave imparato: su un modello diviso tra GPU e CPU, i layer sulla CPU calcolano ogni token che ricevono. Qualsiasi cosa elabori più token insieme costa al 14B quasi in proporzione. Per velocizzare il 14B, togli lavoro alla CPU.

Cercasi aiuto: Radeon

MAFDET gira sulle schede Radeon con la build Vulkan di llama.cpp, ma nessuno l'ha ancora misurato su una. Il percorso Vulkan in sé è verificato, sulla RTX 2060 (Qwen3-4B legge 2.103 token/s e ne scrive 83, più o meno come con CUDA). Se hai una scheda dedicata, RX 5000 o successiva, 8 GB o più è l'ideale, circa mezz'ora colmerebbe questo vuoto:

  1. Installa MAFDET e aprilo una volta: dovrebbe trovare la tua scheda, installare llama.cpp Vulkan e scaricare Qwen3-4B. mafdet doctor mostra cosa ha trovato.
  2. Nell'app, Modelli, Misura Qwen3-4B.
  3. Dalla cartella di MAFDET, con il suo ambiente attivo: python research/thinking_ahead.py radeon_4b.json. Circa 20 minuti; lascia la macchina altrimenti inattiva.
  4. Apri una issue con l'output di mafdet doctor, i numeri di Misura e radeon_4b.json.