Trójwarstwowy scheduler priorytetów skraca opóźnienia lokalnych modeli językowych z ponad sekundy do mniej niż dwóch dziesiątych sekundy, zapewniając responsywność aplikacji czatowych nawet wtedy, gdy telefon wykonuje prace w tle. Zoptymalizowany pod procesor Tensor G3 obsługujący model o 3 miliardach parametrów, redukuje opóźnienie z 1420 ms do 161 ms, nie przerywając przy tym zadań działających w tle.
Dlaczego lokalne modele LLM mają trudności
Uruchamianie dużego modelu językowego na procesorze mobilnym to walka o zasoby. Na procesorze Tensor G3 model 3B pochłania już około 85% jednostki przetwarzania neuronowego (NPU). Gdy zadanie o niskim priorytecie – takie jak indeksator offline – działa w tym samym czasie, gdy użytkownik otwiera okno czatu, postrzegany czas odpowiedzi wzrasta z około 140 ms do 1400 ms, co oznacza dziesięciokrotne spowolnienie, które użytkownicy natychmiast zauważają.
Problem nie dotyczy tylko prędkości. Urządzenia mobilne muszą godzić płynność interfejsu użytkownika (UI), czas pracy na baterii oraz wiele aplikacji, które jednocześnie żądają mocy obliczeniowej. Naiwna kolejka, która przetwarza zadania po kolei, zmusza wątek UI do oczekiwania na prace w tle, co zmienia konwersacyjnego asystenta w powolne i frustrujące narzędzie.
Jak działa trójwarstwowy scheduler
Nowy scheduler wprowadza do potoku wnioskowania (inference pipeline) trzy skoordynowane komponenty:
- Priority Queue – kopiec (min-heap), który porządkuje nadchodzące zadania według statycznego poziomu ważności.
- Preemption Controller – w przypadku pojawienia się żądania o wyższym priorytecie, wstrzymuje on zadania o niższym priorytecie zamiast je odrzucać.
- Token Budget Governor – ogranicza liczbę tokenów, jakie zadanie może wygenerować, w oparciu o stan cyklu życia aplikacji.
Wspólnie pozwalają one żądaniu czatu w pierwszym planie (foreground) wyskoczyć na początek kolejki, podczas gdy zadania w tle pozostają w stanie wstrzymania (parked state), gotowe do wznowienia, gdy zwolnią się zasoby.
Poziomy priorytetów i wywłaszczanie (preemption)
Cztery poziomy definiują, co może zostać przerwane:
| Poziom | Opis |
|---|---|
| Foreground Chat | Krytyczna interakcja z UI |
| Inline Suggestion | Podpowiedzi typu autouzupełnianie |
| Background Summary | Okresowe podsumowywanie treści |
| Offline Indexing | Masowe przetwarzanie danych |
Scheduler nigdy nie przerywa zadania o niskim priorytecie. Zamiast tego wykonuje migawkę (snapshot) pamięci podręcznej klucz-wartość (KV cache) modelu – struktury przechowującej pośrednie wyniki mechanizmu uwagi (attention) – i wstrzymuje zadanie. Gdy żądanie o wysokim priorytecie zostanie zakończone, kontroler przywraca migawkę i pozwala zadaniu w tle kontynuować pracę od miejsca, w którym została przerwana. Takie podejście „pauza i wznowienie” pozwala uniknąć kosztownego ponownego przeliczania, które nastąpiłoby w przypadku restartu zadania od zera.
Częściowe usuwanie (eviction) z KV cache dodatkowo ogranicza marnotrawstwo. Statyczny prompt systemowy pozostaje w pamięci podręcznej, podczas gdy usuwane są jedynie dynamiczne zwroty w rozmowie. Wynikiem jest redukcja kosztu ponownego wypełniania (re-prefilling) modelu po pauzie o 40–60%.
Zarządzanie budżetem tokenów bez użycia timerów
Wiele implementacji polega na timerach, aby zgadywać, kiedy zadanie powinno zwolnić czas procesora (CPU) lub NPU. Timery są mało precyzyjne; mogą albo pozbawić UI zasobów, albo nie w pełni wykorzystać chipa. Scheduler zastępuje timery komponentem ProcessLifecycleOwner z systemu Android, który emituje zdarzenia cyklu życia, niezawodnie wskazujące, czy aplikacja znajduje się w pierwszym planie, czy w tle.
- ON_RESUME – aplikacja odzyskuje pełny budżet obliczeniowy, co pozwala na niezakłócone wykonywanie oczekujących zadań w pierwszym planie.
- ON_STOP – aplikacja ogranicza zadania w tle do około 25% ich normalnego budżetu tokenów, zachowując zapas na wypadek nagłego żądania ze strony UI.
Dzięki powiązaniu alokacji zasobów ze zdarzeniami cyklu życia, system reaguje na rzeczywiste zachowanie użytkownika, a nie na arbitralne interwały czasowe.
Zyski wydajnościowe i kompromisy
W przypadku naiwnej kolejki typu „kto pierwszy, ten lepszy” (first-come-first-served), zadanie w tle zwiększa opóźnienie czatu w pierwszym planie do około 1420 ms. Przy aktywnym schedulerze priorytetów to samo żądanie czatu kończy się w około 161 ms, co stanowi dziesięciokrotną poprawę i przywraca płynność obsługi użytkownika.
Wznowienie wstrzymanego zadania zwiększa jego całkowity czas wykonania o około 22%. Ponieważ prace w tle nie są krytyczne, kompromis ten pozostaje akceptowalny, zwłaszcza gdy interfejs użytkownika pozostaje responsywny.
