Krótka odpowiedź: Tesla P40 generuje tokeny przyzwoicie, ale przetwarzanie długiego promptu (prefill) jest na niej wolne — bo P40 (układ GP102) nie ma Tensor Cores i nie oferuje wysokiej przepustowości FP16 znanej z późniejszych akceleratorów. Jeśli Twój przypadek to krótkie pytania i długie odpowiedzi, P40 może być bardzo dobrym wyborem pod względem koszt/VRAM. Jeśli to agenty i RAG z wielkim kontekstem — prefill zaboli i warto rozważyć V100 32GB.
Sprzedaję używane P40 i widzę, jak ludzie się na tym potykają. Ktoś kupuje kartę, odpala model, zadaje krótkie pytanie — działa błyskawicznie. Potem wkleja pół dokumentacji do kontekstu i nagle karta "zawiesza się" na kilkanaście sekund, zanim w ogóle zacznie odpowiadać. Nic się nie zepsuło. Tak po prostu działa Pascal. Wolę Ci to powiedzieć teraz, przed zakupem, niż czytać potem, że oszukałem.
Zanim wejdziemy w szczegóły — mapa objawu, przyczyny i tego, co z tym zrobić:
| Objaw | Przyczyna | Co zrobić |
|---|---|---|
| Długi czas przed pierwszym tokenem | Koszt prefillu (przetwarzanie promptu) | Skrócić realny kontekst, dobrać kwantyzację, zmierzyć własny czas |
| Generacja po starcie jest OK | Decode ma inny profil (limit przepustowości pamięci) | Nie diagnozować karty jako uszkodzonej |
| Nadal za wolno mimo strojenia | Ograniczenie architektury / charakter workloadu | Rozważyć V100 32GB |
Najważniejsze na start
- Generacja tokenów (decode) na P40 jest OK — to najczęstszy powód, dla którego ludzie ją kupują i są zadowoleni.
- Przetwarzanie promptu (prefill) jest wolne — brak Tensor Cores, brak wysokiej przepustowości FP16 na GP102. Im dłuższy kontekst, tym dłużej czekasz na pierwszy token.
- Boli to głównie w agentach, RAG i pracy na długich dokumentach, gdzie kontekst potrafi mieć tysiące tokenów przy każdym zapytaniu.
- Da się to łagodzić: dobór kwantyzacji, ustawienia
batch/ubatchw llama.cpp, krótszy realny kontekst oraz — gdy workload ma wspólny prefiks — mechanizmy prompt/prefix cache. - Nie ma cudów — jeśli szybki prefill jest krytyczny, V100 32GB jest w tej klasie używanych kart znacznie lepszym wyborem niż P40.
- Konkretne liczby zależą od modelu i ustawień; niżej podaję nasze zmierzone na P40 (Bielik, PLLuM, Llama), a nie cudze wykresy.
Co się właściwie dzieje: prefill kontra decode
Inferencja LLM ma dwie fazy. Pierwsza to prefill — model musi przeczytać cały prompt (kontekst) i policzyć jego reprezentację, zanim wyprodukuje pierwszy token. To operacja mocno macierzowa, świetnie zrównoleglona, i tu nowsze GPU z odpowiednimi jednostkami macierzowymi osiągają znacznie wyższą przepustowość. Druga faza to decode — generowanie kolejnych tokenów jeden po drugim; przy małym batchu decode typowych modeli bywa przede wszystkim ograniczony przepustowością pamięci, a nie surową mocą obliczeniową FP16.
P40 (układ GP102) nie ma Tensor Cores i nie oferuje wysokiej przepustowości FP16 znanej z późniejszych akceleratorów. To cecha tego konkretnego układu, a nie całej rodziny Pascal — P100/GP100 jest tu istotnym wyjątkiem (szczegóły architektoniczne rozwinąłem w tekście o tym, co CUDA 13 oznacza dla Pascala i Volty). Za to P40 ma 24 GB pamięci i przyzwoitą przepustowość, więc decode wychodzi jej zaskakująco dobrze. Efekt: krótkie pytanie → szybka odpowiedź. Długi prompt → karta najpierw "myśli" przez prefill, a dopiero potem rusza generacja.
To nie jest usterka egzemplarza. To profil wydajności całej architektury.
Kiedy to naprawdę boli (a kiedy nie)
Powiem wprost, bo to najważniejszy akapit tego wpisu:
- Nie boli, gdy zadajesz krótkie pytania i chcesz dłuższych odpowiedzi. Chat, asystent do pisania, tłumaczenia krótkich fragmentów, generowanie kodu z krótkiego opisu — tu P40 jest bardzo rozsądnym wyborem cena/pamięć.
- Boli, gdy każde zapytanie niesie ze sobą duży kontekst: agenty przeklejające historię narzędzi i myśli, RAG dokładający kilka fragmentów dokumentów, analiza długich plików, "przeczytaj ten PDF i odpowiedz". Tu prefill dominuje czas odpowiedzi, a Pascal jest w tej fazie najsłabszy.
Jeśli Twój przypadek to ta druga grupa — czytaj dalej po sekcje o łagodzeniu, ale miej z tyłu głowy, że mierzysz się z ograniczeniem architektury. Więcej o doborze GPU pod konkretny typ inferencji napisałem w przewodniku o najlepszym GPU do inferencji LLM.
Jak realnie łagodzić wolny prefill na P40
Nie ma jednego ustawienia, które usuwa ograniczenie architektury — ale kilka parametrów realnie pomaga.
1. Dobór kwantyzacji
Kwantyzacja zmniejsza model i zmniejsza ilość danych do przemielenia. Na Pascalu warto trzymać się formatów, które ta architektura obsługuje efektywnie w liczbach całkowitych, zamiast liczyć na przyspieszenie z FP16. W praktyce oznacza to eksperymenty z wariantami Q4/Q5/Q6 w llama.cpp i sprawdzenie, który daje akceptowalny czas prefillu przy jakości, która Ci wystarcza.
Nasze pomiary na P40 (GGUF, llama-bench, -ngl 99, pełny power limit 250 W, driver 580.173.02, llama.cpp build 6ad4ab0, -r 3) — prompt eval / generacja tok/s:
| Model / quant | Prompt eval (pp512) | Prompt eval (pp2048) | Generacja (tg128) |
|---|---|---|---|
| Bielik-11B Q4_K_M | 593,6 | 550,8 | 28,5 |
| Bielik-11B Q5_K_M | 562,3 | — | 24,3 |
| PLLuM-12B Q4_K_M | 612,2 | 578,0 | 27,1 |
| Llama-3.1-8B Q4_K_M | 933,1 | — | 41,1 |
W Bieliku-11B na naszej P40 Q4_K_M był szybszy od Q5_K_M: ~5,6% w pp512 i ~17% w tg128. Mniejszy quant redukuje ilość danych do przemielenia, ale rzeczywisty zysk zależy również od implementacji kerneli i kosztu dekwantyzacji, więc to jeden model i jedna para quantów — nie przenosimy tej różnicy automatycznie na inne modele czy backendy. Widać też, że mniejszy model (8B) wyraźnie przyspiesza obie fazy. Który wariant wybrać, zależy od modelu i akceptowalnej jakości.
2. Ustawienia batch i ubatch w llama.cpp
To najbardziej niedoceniany zestaw pokręteł. Parametry --batch-size (n_batch) i --ubatch-size (n_ubatch) sterują tym, jak duże porcje promptu są przetwarzane naraz podczas prefillu. Zbyt małe wartości marnują równoległość karty; zbyt duże potrafią uderzyć w pamięć. W użytej przez nas wersji punktem startowym było -ub 512 — ale wartości domyślne llama.cpp zmieniają się w czasie, więc sprawdź --help swojej wersji, zamiast opierać się na trwałej tezie o default. Optymalne ustawienie pozostaje specyficzne dla karty i modelu; nie mierzyliśmy w tej kampanii osobnego sweepu -ub, więc nie podajemy tu jego liczb — warto zmierzyć czas do pierwszego tokenu na własnym prompcie.
Co natomiast zmierzyliśmy wprost, to jak rośnie koszt prefillu wraz z długością kontekstu. Bielik-11B Q4_K_M na P40, ten sam przebieg, przy rosnącym prompcie (-p 512,2048,4096,8192):
| Długość promptu (tok.) | Prompt eval (tok/s) |
|---|---|
| 512 | 595,6 |
| 2048 | 551,8 |
| 4096 | 502,7 |
| 8192 | 429,7 |
Szczyt zużycia VRAM w całym sweepie (do kontekstu 8192) to ~8,3 GB — daleko od limitu 24 GB, więc na P40 to prędkość, nie pojemność, jest tu wąskim gardłem. Rate prefillu spada łagodnie z długością (z 595,6 przy 512 do 429,7 przy 8192 tok.), co znaczy, że czas prefillu rośnie mniej więcej z liczbą tokenów — każdy token wejścia kosztuje. To prowadzi wprost do najtańszego przyspieszenia.
3. Krótszy realny kontekst
Najtańsze przyspieszenie prefillu to po prostu mniej tokenów wejścia. W RAG to znaczy: agresywniejsze przycinanie, mniej i lepiej dobranych fragmentów zamiast "wrzućmy wszystko na wszelki wypadek". W agentach — kompaktowanie historii, podsumowywanie zamiast doklejania pełnych logów. Każdy token, którego nie wyślesz, to token, którego P40 nie musi przemielić.
4. Cache promptu i "rozgrzewka"
Warto rozróżnić dwa różne mechanizmy. KV cache przyspiesza dalszy decode w obrębie jednego, aktywnego kontekstu — to nie jest to samo co ponowne wykorzystanie wspólnego prefiksu (prompt/prefix cache) między kolejnymi zapytaniami. Jeśli duża część kontekstu się nie zmienia (np. stały system prompt, ta sama dokumentacja), to właśnie prompt cache pozwala nie liczyć prefillu tego samego fragmentu w kółko — ale jego działanie zależy od serwera, wersji i zgodności prefiksu. Nie zakładaj, że każde zapytanie automatycznie odzyska poprzedni prefill; to szczególnie ważne w RAG, gdzie fragmenty często się zmieniają. Podobnie "rozgrzewka" — pierwsze uruchomienie modelu bywa wolniejsze niż kolejne, więc jednorazowy koszt startu nie powinien zniekształcać Twojej oceny wydajności. Zakres, w jakim dany serwer (llama.cpp, Ollama) buforuje prefill, sprawdź w swojej konfiguracji.
5. Świadomość braku Flash Attention
Flash Attention to optymalizacja mechanizmu uwagi, która przyspiesza pracę z długim kontekstem. Nie zakładamy jednak, że --flash-attn rozwiąże problem prefillu na P40: efekt -fa zależy od wersji llama.cpp, modelu, typu KV cache i dostępnych kerneli, a jego macierz wsparcia się zmienia. W tej kampanii nie mierzyliśmy osobno FA on/off na P40, więc nie podajemy tu procentowego zysku — i nie stawiamy tezy, że Flash Attention jest na tej karcie "sprzętowo niedostępne" w tym samym sensie co Tensor Cores. Jeśli sam się na to zdecydujesz, zmierz oba warianty na swoim prompcie i porównaj.
Kiedy przestać walczyć i wziąć V100
Będę uczciwy do końca: powyższe ustawienia łagodzą, nie usuwają problemu. Jeśli budujesz agenta, który przy każdym kroku przepycha kilka tysięcy tokenów kontekstu, albo pracujesz na długich dokumentach i czas do pierwszego tokenu jest dla Ciebie krytyczny — żadne pokrętło w llama.cpp nie zamieni Pascala w architekturę z Tensor Cores.
Wtedy w tej klasie używanych kart znacznie lepszym wyborem niż P40 jest V100 32GB. Volta ma Tensor Cores i realnie sprawniejszy FP16, więc prefill długiego kontekstu wychodzi jej wyraźnie lepiej niż P40. Skalę przewagi widać na tym samym modelu i quancie — Bielik-11B Q4_K_M, ten sam benchmark, llama-bench -ngl 99, pełny power limit:
| Metryka | P40 | V100-PCIE-16GB |
|---|---|---|
| Prompt eval pp512 (tok/s) | 595,6 | 1868,6 |
| Prompt eval pp2048 (tok/s) | 551,8 | 1719,9 |
| Generacja tg128 (tok/s) | 28,5 | 83,0 |
W matched benchmarku mieliśmy V100-PCIE-16GB; rekomendowana wyżej wersja 32 GB ma tę samą klasę architektury obliczeniowej (Volta, Tensor Cores), ale powyższych liczb nie przedstawiamy jako osobnego pomiaru V100 32 GB. W tym teście V100 była na prefillu ~3,1× szybsza od P40 (a w generacji ~2,9×) — wynik jest zgodny z przewagami Volty, choć benchmark nie izoluje samego wpływu Tensor Cores od HBM2 i innych różnic architektury. To droższa karta i mówię to, wiedząc, że część z Was wybierze mimo wszystko tańszą P40 — i słusznie, jeśli Wasze prompty są krótkie. Chodzi o to, żebyś wybrał świadomie, a nie odkrył profil wydajności dopiero po zakupie.
Źródła
- NVIDIA Tesla P40 — dane techniczne (Pascal, brak Tensor Cores, słaby FP16): https://images.nvidia.com/content/pdf/tesla/184427-Tesla-P40-Datasheet-NV-Final-Letter-Web.pdf
- NVIDIA Volta — whitepaper architektury (Tensor Cores, których Pascal nie ma): https://images.nvidia.com/content/volta-architecture/pdf/volta-architecture-whitepaper.pdf
- llama.cpp — parametry
--batch-size/--ubatch-sizenajlepiej sprawdzić wllama-cli --help/llama-bench --helpdla konkretnego commitu (nasze pomiary: build6ad4ab0); repozytorium narzędzia: https://github.com/ggml-org/llama.cpp
Zastrzeżenie: Sprzedajemy karty UŻYWANE, z rynku wtórnego serwerowego. P40 jest często wybierana ze względu na 24 GB VRAM przy relatywnie niskiej cenie na rynku wtórnym, ale ma realne ograniczenie w postaci wolnego prefillu — jeśli ktoś Ci mówi, że jest szybka "we wszystkim", nie mów tego ode mnie. Każdą kartę przed wysyłką przepuszczamy przez wieloetapową kwalifikację obejmującą m.in. kontrolę VRAM, burn-in z watchdogiem, ECC, PCIe i poprawność obliczeń — nie zmienia to oczywiście profilu wydajności architektury: testujemy sprawność egzemplarza, nie obiecujemy, że Pascal nagle dostanie Tensor Cores. Masz wątpliwości, czy P40 pasuje do Twojego zastosowania? napisz do nas — wolę odradzić zakup niż przyjąć zwrot.
FAQ
- Czy P40 jest "wolna"?
- Nie w generacji tokenów — tu jest zaskakująco dobra jak na cenę i 24 GB pamięci. Wolna jest w przetwarzaniu długiego promptu. To dwie różne fazy i mylenie ich rodzi rozczarowania.
- Czy da się dorobić Tensor Cores albo Flash Attention przez sterownik?
- Tensor Cores to brak sprzętowy układu GP102 — tego sterownik nie dorobi. Flash Attention to co innego: to optymalizacja programowa, dostępna w llama.cpp przez
-fa, tyle że jej realny zysk na P40 zależy od wersji, modelu i kerneli, a my go w tej kampanii nie zmierzyliśmy. Praktycznie problem prefillu obchodzi się lepszymi ustawieniami i krótszym kontekstem, nie flagą. - Ile realnie trwa prefill na P40?
- U nas Bielik-11B Q4_K_M na P40 robi prompt eval ~594 tok/s przy 512 tokenach i ~551 przy 2048. Przy pp2048 ≈551 tok/s samo prompt evaluation 2048 tokenów odpowiada orientacyjnie ~3,7 s pracy mierzonej przez
llama-bench— to nie jest pełny TTFT aplikacji (dochodzą tokenizacja, scheduling, transfery, narzut serwera i pierwszy krok decode). Między 512 a 2048 tok. przepustowość zmieniła się niewiele, więc w tym zakresie czas prefillu rośnie przede wszystkim wraz z liczbą tokenów; przy znacznie dłuższych kontekstach zależność może się zmienić. Twoja liczba zależy od modelu, kwantyzacji, kontekstu i batcha. - Mam RAG z długimi dokumentami — brać P40 czy V100?
- Jeśli kontekst jest duży i zależy Ci na czasie odpowiedzi — V100 32GB. Jeśli budżet jest ciasny, a dokumenty da się agresywnie przycinać, P40 może wystarczyć. Napisz, opiszę Ci realistycznie oba warianty.
- Czy Ollama i llama.cpp obsługują te ustawienia batch na P40?
- Tak, backendem obu jest llama.cpp. Praktyczny setup P40 pod lokalny LLM opisałem w tekście o P40 i Ollamie.
