מתזמן עדיפויות בעל שלוש שכבות מפחית את השיהוי (latency) של מודל שפה על המכשיר (on-device) מיותר משנייה לפחות מעשיריות השנייה, ושומר על אפליקציות צ'אט מגיבות גם כשהטלפון עסוק בעבודה ברקע. המתזמן, שנבנה עבור שבב Tensor G3 המריץ מודל בעל 3 מיליארד פרמטרים, מצמצם את השיהוי מ-1,420 מילי-שניות ל-161 מילי-שניות מבלי לעצור משימות רקע.
למה מודלי שפה (LLMs) על המכשיר מתקשים
הרצת מודל שפה גדול על מעבד נייד היא מאבק על משאבים. ב-Tensor G3, המודל בעל ה-3B כבר צורך כ-85% מיחידת העיבוד העצבית (NPU). כאשר משימה בעלת עדיפות נמוכה — כגון אינדקס (indexer) לא מקוון — רצה במקביל לפתיחת חלון צ'אט על ידי המשתמש, זמן התגובה הנתפס קופץ מ-140 מילי-שניות בערך ל-1,400 מילי-שניות, האטה פי עשרה שהמשתמשים מבחינים בה באופן מיידי.
הבעיה אינה רק מהירות. מכשירים ניידים חייבים לאזן בין חלקות ממשק המשתמש (UI), חיי סוללה ואפליקציות מרובות, כולן מבקשות כוח מחשוב. תור פשוט (naïve queue) המעבד משימות לפי סדר הגעתן מאלץ את תור ה-UI לחכות לעבודה ברקע, מה שהופך עוזר שיחתי לחוויה איטית וכבדה.
איך עובד המתזמן בעל שלוש השכבות
המתזמן החדש מכניס שלושה רכיבים מתואמים לתוך צינור ההסקה (inference pipeline):
- תור עדיפויות (Priority Queue) – min-heap המסדר משימות נכנסות לפי רמת חשיבות סטטית.
- בקר קדימות (Preemption Controller) – כאשר מגיעה בקשה בעלת עדיפות גבוהה יותר, הוא עוצר משימות בעלות עדיפות נמוכה יותר במקום לבטל אותן.
- בקר תקציב טוקנים (Token Budget Governor) – מגביל את מספר הטוקנים שמשימה רשאית לייצר בהתאם למצב מחזור החיים של האפליקציה.
יחד, הם מאפשרים לבקשת צ'אט בראשית הממשק (foreground) לקפוץ לתחילת התור, בעוד משימות רקע נשארות במצב "חניה", מוכנות להמשיך ברגע שמשאבים יתפנו.
דרגות עדיפות וקדימות (Preemption)
ארבע דרגות מגדירות מה ניתן להפסיק:
| דרגה | תיאור |
|---|---|
| צ'אט בראשית הממשק (Foreground Chat) | אינטראקציית UI קריטית |
| הצעה בתוך השדה (Inline Suggestion) | רמזים בסגנון השלמה אוטומטית |
| סיכום ברקע (Background Summary) | סיכום תוכן תקופתי |
| אינדוקס לא מקוון (Offline Indexing) | עיבוד נתונים בכמות גדולה |
המתזמן לעולם אינו מבטל משימה בעלת עדיפות נמוכה. במקום זאת, הוא יוצר "צילום מצב" (snapshot) של מטמון המפתח-ערך (KV cache) של המודל — מבנה המחזיק תוצאות קשב (attention) ביניים — ומחנה את המשימה. כאשר הבקשה בעלת העדיפות הגבוהה מסתיימת, הבקר משחזר את צילום המצב ומאפשר למשימת הרקע להמשיך בדיוק מהנקודה שבה הפסיקה. גישת "עצור-והמשך" זו מונעת את החישוב מחדש היקר שהיה מתרחש אילו המשימה הייתה מופעלת מראשית.
גירוש חלקי של ה-KV-cache מפחית עוד יותר את הבזבוז. ה-system prompt הסטטי נשאר במטמון, בעוד שרק תורות שיחה דינמיים מגורשים. התוצאה היא הפחתה של 40%–60% בעלות המילוי מחדש (re-prefilling) של המודל לאחר עצירה.
ניהול תקציבי טוקנים ללא טיימרים
מימושים רבים מסתמכים על טיימרים כדי לנחש מתי משימה צריכה לוותר על זמן ה-CPU או ה-NPU. טיימרים הם כלי גס; הם עלולים לגרום למחסור במשאבים עבור ה-UI או לניצול חסר של השבב. המתזמן מחליף את הטיימרים ב-ProcessLifecycleOwner של Android, אשר משדר אירועי מחזור חיים המצביעים באופן אמין על כך שהאפליקציה נמצאת בראשית הממשק (foreground) או ברקע (background).
- ON_RESUME – האפליקציה מקבלת מחדש תקציב מחשוב מלא, מה שמאפשר למשימות foreground ממתינות לרוץ ללא הפרעה.
- ON_STOP – האפליקציה מגבילה משימות רקע לכ-25% מתקציב הטוקנים הרגיל שלהן, כדי לשמור על מרווח ביטחון לכל בקשת UI פתאומית.
על ידי קישור הקצאת המשאבים לאירועי מחזור חיים, המערכת מגיבה להתנהגות משתמש אמיתית במקום למקטעי זמן שרירותיים.
שיפורי ביצועים ופשרות (Trade-offs)
תחת תור פשוט מסוג first-come-first-served, משימת רקע דוחפת את השיהוי של צ'אט בראשית הממשק לכ-1,420 מילי-שניות. עם המתזמן בעל העדיפויות פעיל, אותה בקשת צ'אט מסתיימת בערך ב-161 מילי-שניות, שיפור פי עשר שמחזיר חוויית משתמש רציפה.
המשך עבודה של משימה שהופסקה מוסיף כ-22% לזמן הביצוע הכולל שלה. מכיוון שעבודת רקע אינה קריטית, הפשרה נותרת מקובלת, במיוחד כאשר ממשק המשתמש נשאר מהיר וקולח.
