אופטימיזציה של הסקה על גבי המכשיר עבור Apple Silicon

מנוע מקומי מותאם המשפר את תפוקת ההכנה והפענוח.

מחבריםPerplexity Engineering

חישוב היברידי ב-Apple silicon מתאם משימה בין בינה בחזית הענן לבין מודל מקומי במחשב ה-Mac. מודלים בענן מטפלים במחקר ובהסקה, בעוד מודל מקומי פועל מול קבצים פרטיים ואפליקציות במחשב ה-Mac.

כדי שחלוקת עבודה זו תרגיש חלקה, הסקה מקומית חייבת לעמוד בקצב של שאר המשימה. דבר זה דורש מנוע שיכול לעבד הנחיות במהירות ולשמור על קצב יצירת אסימונים גבוה.

לילי, מנוע ההסקה המקומי וקל המשקל שלנו, נבנה במיוחד עבור שבבי Apple Silicon ועבור Qwen3.6-35B-A3B, עם אופטימיזציות נפרדות לשלב מילוי המטמון (prefill) ולשלב הפענוח (decode). הדגמה עצמאית זמינה לציבור ב-GitHub.

מבוא

דרך נפוצה להריץ מודלי שפה גדולים (LLM) על גבי מחשב Mac היא באמצעות MLX, מסגרת עבודת למידת המכונה של אולם עבור Apple silicon. ספריית העזר שלה, MLX-LM, מוסיפה את רכיבים הנדרשים לטעינה ויצירה של טקסט עם מגוון רחב של מודלי שפה. יחד, MLX ו-MLX-LM מספקות ערימה מוכנה מראש לכל מטרה עבור הסקת LLM מקומית.

Qwen3.6-35B-A3B הוא מודל היברידי ומדולל (sparse): הוא משתמש בניתוב מבוסס תערובת מומחים (MoE) ומשלב מצבים מחזוריים (recurrent states) בגודל קבוע יחד עם מנגנון קשב מלא. בחירות ארכיטקטוניות אלו מצמצמות את כמות החשבון הנדרשת, אך הן יוצרות גם עומסי עבודה לא סדירים. אסימונים מנותבים למשקלי מומחים שונים, ומצבים מחזוריים הם מטבעם רציפים.

MLX-LM כבר בוחרת kernels ממוטבים לשלבי הסקה ולצורות עומס עבודה נפוצות, אך הפעולות הניתנות לשימוש חוזר שלה חייבות לתמוך בארכיטקטורות מודל רבות. מנוע המוקדש ל-Qwen יכול להתמחות ברמת המודל וסביבת הריצה, ולתאם בין kernels, תנועת נתונים ותזמון סביב המבנה הקבוע של המודל.

לילה מטמיעה התמחות זו מקצה לקצה בתהליך יחיד. סביבת ריצה מבוססת Rust טוענת את נקודת הביקורת של המודל ומנהלת את מצב ההפעלה (session) ולולאת היצירה, ממשק תכנות יישומים (API) של צ'אט התואם ל-OpenAI מקבל בקשות ומזרים אסימונים, ו-kernels מותאמים של Metal מבצעים פעולות הספציפיות ל-Qwen. לא PyTorch ולא MLX נמצאים בנתיב הביצוע.

היכן ממוקמים הכלליות וההתמחות בשתי ערימות ההסקה (inference). ‏MLX-LM מתארת את המודל כפעולות מערך MLX הניתנות להרכבה, שאותן MLX מתזמנת באמצעות kernels הניתנים לשימוש חוזר. לעומת זאת, לילה ממקמת את מבנה המודל, תוכניות הביצוע הספציפיות לשלב ובחירת ה-kernel בסביבת ריצה (runtime) אחת של Rust המנוסחת סביב Qwen ושל Apple silicon.

אנו מדודים את ביצועי ההכנה והפענוח בנפרד. תפוקת ההכנה מודדת באיזו מהירות המנוע מעבד את ההנחיה; תפוקת הפענוח מודדת באיזו מהירות הוא מייצר אסימוני פלט.

אנו משווים את Qwen3.6-35B-A3B על MacBook Pro יחיד המופעל על ידי M5 Max עם GPU של 40 ליבות ו-128 GB של זיכרון מאוחד. לאורך עשרה אורכי prompt עבור prefill ועשרה אורכי הקשר עבור decode, מ-256 ועד 128K tokens ‏(K = 1,024), המנוע מגיע בממוצע ל-1.22× תפוקת ה-prefill של MLX-LM ול-1.32× תפוקת ה-decode שלו. ב-prompt באורך 4K tokens ובקשר decode באורך 4K tokens, המנוע המותאם אישית מגיע ל-5,749.9 tokens לשנייה ב-prefill ול-186.6 tokens לשנייה ב-decode, לעומת 4,737.5 ו-140.9 ב-MLX-LM. לאורך session מרובת פניות, חיסכוןי הזמן הללו מצטברים עם כל קריאה נוספת למודל.

תפוקת הממוצע האריתמטי על פני עשרה אורכים שווי-משקל מ-256 עד 128K tokens. Lily ממוצעת 4,135 tokens/s ב-prefill לעומת 3,383 עבור MLX-LM ‏(1.22×), ו-167.1 tokens/s ב-decode לעומת 126.9 ‏(1.32×). ה-prefill משתנה לפי אורך ה-prompt; ה-decode משתנה לפי אורך הקשר.

לאחר מכן, נסביר כיצד הארכיטקטורה של Qwen יוצרת הזדמנויות אופטימיזציה ספציפיות למודל ב-Apple silicon. לאחר מכן נעבור על שינויי ההכנה והפענוח הנובעים מכך. נסקור גם היכן אופטימיזציה נוספת מפסיקה להשתלם, ולבסוף נסגור בהשוואת מקצה לקצה מול MLX-LM.

הזדמנויות אופטימיזציה הספציפיות ל-Qwen ב-Apple silicon

Qwen יוצרת שלוש צורות עומס עבודה נפרדות

Qwen3.6-35B-A3B מכיל 35 מיליארד פרמטרים אך מפעיל רק כ-3 מיליארד עבור כל אסימון. נתב מעריך 256 תת-רשתות מומחים ובוחר שמונה, לצד מומחה משותף יחיד המעבד כל אסימון. תכנון MoE מדולל זה מפחית חישובים אך מייצר עבודה לא אחידה: מומחים מקבלים מספרים שונים של אסימונים, וכל אסימון דורש משקלים משילוב שונה של מומחים.

Qwen משלבת גם 10 שכבות קשב מלא עם 30 שכבות Gated DeltaNet. שני סוגי שכבות אלו משמרים מידע קודם בדרכים שונות.

שכבות הקשב משתמשות בקשב מבוסס שאילתות קבוצתיות (GQA). ל-Qwen יש 16 ראשי שאילתות ושני ראשי מפתח-ערך (KV), כאשר שמונה ראשי שאילתות חולקים כל ראש KV. שיתוף זה מקטין את מטמון ה-KV ומאפשר לעשות שימוש חוזר בנתונים המאוחסנים במטמון על פני ראשי שאילתות. המטמון עדיין שומר מפתחות וערכים חדשים עבור כל אסימון, כך שכל שלב פענוח קורא יותר נתונים ככל שההקשר גדל.

Gated DeltaNet ממריצה במקום זאת מידע קודם לתוך מצב מחזורי בגודל קבוע. שער שנלמד שולט בכמה מן המצב הקיים יש לשמור, בעוד עדכון דלתא משלב מידע מהאסימון הנוכחי. המודל מגדיר עדכונים אלו באופן מחזורי, כך שכל אסימון תלוי במצב שהופק על ידי האסימון שקדמו. עם זאת, במהלך שלב ההכנה, מנוע יכול להעריך את אותו חישוב בשתי דרכים. הוא יכול לסרוק את האסימונים ישירות תוך נשיאת המצב קדימה, או לארגן מחדש את העדכונים לבלוקים החושפים פעולות מטריצות נוספות ומקביליות ברמת האסימון. איזו גישה מהירה יותר תלויה בממדי המודל, בעומס העבודה ובחומרה.

יחד, מבנים אלו יוצרים שלושה דפוסים חישוביים: קבוצות מומחים לא אחידות, מנגנון קשב (attention) על מטמון גדל, ותבנית מחזוריות בגודל קבוע שניתן להעריך ישירות או בבלוקים.

Apple silicon מספקת נתיבים שונים עבור עומסי עבודה שונים

שלב ההכנה מעבד שורות אקטיבציה רבות של הנחיות בבת אחת. עומס העבודה המקומי הנשקל כאן מבצע בדרך כלל פענוח של בקשה אחת בכל פעם (batch 1) ומעבד שורה חדשה אחת לכל שלב. הבדל זה משנה את האופן שבו נעשה שימוש באותם משקלי מודל. שלב ההכנה יכול לעשות שימוש חוזר בכל בלוק משקלים על פני מאות או אלפי שורות. שלב הפענוח לרוב אינו יכול לעשות זאת, מכיוון שכל אסימון חדש דורש מעבר נוסף דרך המשקלים.

Apple silicon ממקמת את המעבד המרכזי והמעבד הגרפי מאחורי זיכרון מאוחד, מאגר זיכרון פיזי יחיד הנגיש לשניהם. דבר זה מאפשר למודל להישאר תושב מבלי לתחזק עותק נפרד במעבד הגרפי, אך הוא אינו הופך את תנועת הנתונים לחינמית. קריאת משקלים וערכי ביניים עדיין צורכת רוחב פס זיכרון, בעוד שרשרים ואחסון אחר על השבב מהירים הרבה יותר אך קטנים בהרבה.

המעבד הגרפי של M5 מספק גם נתיבי חישוב שונים. השורות הליניאריות של ההכנה משתמשות בכפל מטריצה-מטריצה כללי (GEMM), המחיל מטריצת משקלים על שורות רבות בבת אחת. GEMM תואמים יכולים להשתמש במאיץ העצבי (Neural Accelerator) בכל ליבת מעבד גרפי באמצעות פעולות טנזור של Metal 4. פענוח batch-1 משתמש במקום זאת בכפל מטריצה-וקטור כללי (GEMV), המחיל את אותם משקלים על שורה בודדת. עם שימוש חוזר מועט במשקלים, GEMV מוגבל בעיקר על ידי רוחב פס הזיכרון ומתאים יותר ליחידות הלוגיקה האריתמטית הווקטוריות (ALUs) של המעבד הגרפי מאשר למאיצים העצביים המיועדים לפעולות מטריצה עם שימוש חוזר רב יותר בנתונים.

נתיבי ביצוע אלו אינם ייחודיים ללילה. MLX פועלת על אותו זיכרון מאוחד ובוחרת מטריצות ממוטבות וkernels וקטוריים בהתאם לצורת עומס העבודה. מימוש Qwen של MLX-LM כבר מקבץ עבודת מומחים, מעריך את Gated DeltaNet באמצעות kernel מתכתי מחזורי מאוחד (fused recurrent Metal kernel), ומשתמש בקשב מודע-GQA. יכולות אלו מהוות נקודת מוצא משותפת להסקת Qwen יעילה על Apple silicon.

אסטרטגיית אופטימיזציה

ההיקף המצומצם יותר של לילה מאפשר לה לתאם נתיבי ביצוע משותפים אלו סביב הארכיטקטורה והממדים המדויקים של Qwen. היא משתמשת בנתיבי GPU ספציפיים לשלב, ממפה את עומסי העבודה של המומחים, המחזוריים והקשב של Qwen כדי לצמצם תנועת נתונים, ובוחרת kernels ופריסות לפי צורת עומס העבודה שנמדדה. לאסטרטגיה שלושה חלקים:

  1. התאם את נתיב המעבד הגרפי לשלב ההסקה. השתמש בביצוע המכוון למטריצות כאשר שלב ההכנה יכול לעשות שימוש חוזר במשקלים על פני שורות רבות, ובביצוע המכוון לווקטורים כאשר שלב פענוח ה-batch-1 מעבד שורה אחת בכל פעם.
  2. מפה את המבנה של Qwen על גבי המעבד הגרפי תוך מזעור תנועת הנתונים. שמור משקלים דחוסים עד לשימוש בהם, ארגן עבודת מומחים מנותבת בלי לחזור למעבד המרכזי, שמור את מצב Gated DeltaNet על השבב לאורך הסריקה המחזורית שלו, ועשה שימוש חוזר בנתוני ה-KV המשותפים לקשב מבוסס שאילתות קבוצתיות.
  3. התאם את ה-kernels לצורת עומס העבודה. בתוך כל שלב, בחר גדלי אריחים, פריסות ביצוע ונתיבי קשב מתוך ספירת השורות הזמינה, התפלגות השורות בין המומחים, ממדי הפעולה ואורך ההקשר הנוכחי.

הסעיפים הבאים מסבירים בחירות אלו. עבור אופטימיזציות שנבחנו באנליזות מותאמות על שבב M5 Max, אנו מעריכים את השפעותיהן על ידי השוואת תצורות מנוע זהות אחרת הנבדלות רק באופטימיזציה הנחקרת. מכיוון שניסויים אלו משווים גרסאות של המנוע שלנו מול עצמו, הם מסבירים מנגנונים במקום לנתח את התוצאות הסופיות מול MLX-LM.

הכנה: שימוש חוזר במשקלים ושמירת הניתוב על גבי המעבד הגרפי

שלב ההכנה חושף שורות אסימונים רבות בבת אחת, אך Qwen מנתבת שורות אלו בצורה לא אחידה בין מומחים ומעדכנת את המצב המחזורי דרך הרצף. האופטימיזציות שלו מתחלקות לשלוש קבוצות: ארגון עבודת המומחים המדולים סביב השורות המנותבות, שמירת סריקת Gated DeltaNet על השבב, וחלוקת הנחיות ארוכות למקטעים מוגבלים.

ביצוע ותושבות נתונים עבור מקטע הכנה מוגבל אחד דרך שכבת Qwen. מנגנון הקשב מרחיב את מטמון ה-KV, בעוד Gated DeltaNet נושא את מצבו המחזורי הפעיל באוכפים. מטא-דאטה של ניתוב המומחים נשאר על גבי המעבד הגרפי, משקלי Q4 נשארים ארוזים עד שהם עוברים די-קואנטיזציה בתוך ה-GEMM הקבוצתי, ואקטיבציות זמניות מוגבלות למקטע הנוכחי.

אופטימיזציה של חישובי מומחים מדוללים

ביצועה של די-קואנטיזציה (dequantization) למשקלים במהלך כפל מטריצות

נקודת הביקורת Qwen3.6-35B-A3B עושה שימוש בקוונטיזציה אפינית קבוצתית בת 4 סיביות. כל משקל מאוחסן כקוד שלם בן 4 סיביות, בעוד שכל קבוצה של 64 משקלים חולקת סולם bfloat16 והטיה המשמשים לשחזור הערכים שלה. דבר זה מצמצם את המודל בן 35 מיליארד הפרמטרים מ-70 ג'יגה-בייט של משקלי bfloat16 לכדי נקודת ביקורת בת 19.4 ג'יגה-בייט, מה שהופך את אחסון המודל כתושב במחשב ה-Mac למעשי.

פעולת הטרנזורים Metal 4 המשמשת לכפל מטריצות צורכת אופרנדים בפורמט bfloat16 ולא ייצוג ארוז בן 4 סיביות. לפני כפל, המעבד הגרפי חייב לשחזר את המשקלים בפורמט bfloat16. ה-GEMM הקבוצתי הממוטב בלילה מבצע המרה זו אריח משקל קטן אחד בכל פעם ומחזיק את התוצאה בזיכרון קבוצת השרשורים שעל השבב למשך זמן המספיק רק כדי להכפיל אותה בשורות האקטיבציה המנותבות. הצטברות משתמשת בנקודה צפה בת 32 סיביות, והפלט נכתב בפורמט bfloat16. מערך המשקלים המורחב המלא לעולם אינו נוצר בזיכרון המאוחד.

בתוך האנליזה החלופית, הדי-קואנטיזציה פועלת כפעולה נפרדת: היא מרחיבה את המשקלים בני 4 הסיביות למערך bfloat16 בזיכרון המאוחד, ולאחר מכן מטריצת המטריצה קוראת את המערך בחזרה. בפרומפט של 512 אסימונים, העברת הדי-קואנטיזציה לתוך ה-GEMM הקבוצתי הגדילה את תפוקת ההכנה מקצה לקצה ב-77.4% על ידי חיסול כתיבה וקריאה ביניים אלו.

שמירת ניתוב המומחים על גבי המעבד הגרפי

ה-GEMM הקבוצתי דורש ששורות האקטיבציה שהוקצו לכל מומחה יאוחסנו יחד. לאחר בחירת שמונה מומחים לכל אסימון, היסטוגרמה סופרת כמה הקצאות הגיעו לכל מומחה. סריקת קידומת הופכת ספירות אלו לקיזוזי התחלה, שלב פיזור (scatter) ממקם שורות בקבוצות המומחים שלהן, ומפת בלוקים מפרט את בלוקי המטריצות בעלי הגודל הקבוע שעל ה-GEMM הקבוצתי לעבד.

הנתיב הממוטב שומר את כל הרצף הזה בתוך מאגר פקודות (command buffer) יחיד – קבוצה מסודרת של פעולות מעבד גרפי – עבור כל מקטע הנחיה. באנליזה חלופית יש השהיה כדי שהמעבד המרכזי יוכל לבדוק את נתוני הביניים של הניתוב ולהגיש את הפעולה הבאה. שמירת ההיסטוגרמה וסריקת הקידומת במעבד הגרפי מוסיפה שני kernels אך מסירה סנכרון בין המעבד המרכזי למעבד הגרפי בתוך כל שכבת MoE.

בפרומפט של 512 טוקנים, הפעלת ניתוב שממוקם ב-GPU הגדילה את ה-prefill מקצה לקצה ב-89%. הדבר גם מראה מדוע ספירת הליבות לבדה עלולה להטעות: הנתיב המהיר יותר מפעיל יותר ליבות אך לעולם אינו ממתין ל-CPU בתוך השכבה.

התאמת גודל האריח לעומס המומחה

בהנחיה של 2K אסימונים, ניתוב כל אסימון לשמונה מתוך 256 מומחים מייצר 16,384 הקצאות אסימון-מומחה, או בממוצע 64 שורות אקטיבציה לכל מומחה. ההתפלגות בפועל אינה אחידה: חלק מהמומחים מקבלים שורות רבות, בעוד אחרים מקבלים מעט.

ה-GEMM הקבוצתי מחלק את הפלט של כל מומחה לאריחים, שהם בלוקים מלבניים קטנים של פלט כפל מטריצות. כל אריח מוקצה לקבוצת שרשורים אחת במעבד הגרפי. במעבדים הגרפיים של Apple silicon, קבוצת שרשורים מכילה קבוצת סימד אחת או יותר, שכל אחת מהן מורכבת מ-32 שרשורים המבצעים הוראות בצעד משולב.

אריחים (tiles) גדולים יותר מפיצים את עלות ההקמה על פני שורות רבות יותר וחושפים עבודה מקבילה רבה יותר, אך חלק מאריח גדול נותר לא פעיל כאשר מומחה מקבל שורות מעטות בלבד. לכן, גודל האריח וספירת קבוצות הסימד שלובים זה בזה.

אנליזה חלופית קובעת את גודל האריח על 16 שורות. מול בקרת אלו, הפעלת אריח בן 32 שורות עם ארבע קבוצות סימד שיפרה את ההכנה מקצה לקצה ב-13.2% בהנחיות של 2K אסימונים.

שמירת המצב המחזורי על גבי השבב

במהלך שלב ההכנה, כל שכבת Gated DeltaNet סורקת את ההנחיה לפי סדר תוך נשיאת מצבה המחזורי קדימה. כאשר תושבות האוכפים מנוטרלת, האנליזה החלופית משתמשת בסריקה לפי בלוקים. בהנחיה של 2K אסימונים, נתיב זה מעביר 256 MiB (מביבייט) של מצב לכל שכבה ועוצר שוב ושוב שרשורים משתפים במחסומים – נקודות סנכרון שבהן כל השרשורים המשתתפים חייבים להמתין זה לזה.

המצב המחזורי הוא מטריצה. ה-kernel הממוטב מקצה כל עמודה לקבוצת סימד אחת. קבוצת הסימד מחלקת את העמודה בין השרשורים (threads) שלה, טוענת את העמודה לתוך האוכפים (registers) שלהם פעם אחת, ומעבירה את המצב לאורך כל הסריקה. השרשורים מחליפים תוצאות ביניים באמצעות פעולות קבוצת סימד במקום זיכרון קבוצת שרשורים, שהוא אחסון על-גבי השבב המשותף לקבוצת שרשורים. המצב שהושלם נכתב בחזרה רק לאחר הסריקה.

המצב ושער שלו משתמשים בפורמט נקודה צפה בת 32 סיביות מכיוון ששגיאות עיגול קטנות מצטברות בעדכונים רציפים. אקטיבציות השאילתות והמפתח נשארות בפורמט bfloat16.

בפרומפט של 2K אסימונים, הפעלת הסריקה הממוקמת באוכפים שיפרה את ההכנה מקצה לקצה ב-5.6%. מטריצות GEMM של מומחים היו אחראיות לכ-90% מזמן ההכנה. הסריקה הרציפה אינה חושפת מספיק עבודת מטריצות הניתנת לשימוש חוזר כדי ליהנות מהמאיצים העצביים (Neural Accelerators).

הגבלת זיכרון זמני באמצעות חלוקת הנחיות למקטעים (chunking)

סביבת הריצה מעבדת הנחיה ארוכה כרצף של מקטעים מוגבלים במקום לשמור נתונים זמניים עבור כל אסימון הנחיה בזיכרון בבת אחת. משקלי המודל נשארים תושבים בזיכרון המאוחד, בעוד שהמצב המחזורי ומטמון ה-KV נושאים את ההקשר ממקטע אחד למשנהו. שום הקשר קודם אינו נזרק לפח.

ללא חלוקה למקטעים, מערכי אקטיבציה זמניים גדלים יחד עם ההנחיה המלאה ומתחרים עם משקלי המודל, המצב המחזורי ומטמון ה-KV על הזיכרון המאוחד. חלוקה למקטעים שומרת על ערכי הביניים של מקטע בודד כפעילים בכל רגע נתון, ואז משחררת או עושה שימוש חוזר באחסון זה לפני עיבוד המקטע הבא. פעולה זו מגבילה את זיכרון העבודה בשיא ומאפשרת למנוע לעבד הנחיות ארוכות יותר מבלי לשנות את פלט המודל.

הכנה המחולקת למקטעים נפוצה במנועים רבים והיא קריטית לשירות במסלולים ארוכי רב-שלבים בסביבות מוגבלות זיכרון אלו. זמן ההכנה הכולל עבור שכבות קשב נותר ריבועי ביחס לאורך ההנחיה, עם תוספת עומס מסוימת מטעינות KV חוזרות ונשנות של מקטעים קודמים.

פענוח: מזעור הבייטים המועברים לכל אסימון

פענוח batch-1 מעבד שורה חדשה אחת בכל פעם. עם שימוש חוזר מועט במשקלים, התפוקה שלו תלויה בעיקר בכמה בייטים המנוע מעביר עבור כל אסימון. שינויי הפענוח מתחלקים לארבע קבוצות: אופטימיזציה של נתיב המשקל בעל השורה הבודדת, שמירת כל שלב על גבי המעבד הגרפי, צמצום תעבורת ערכי הביניים והמצבים, וקריאה יעילה של מטמון הקשב.

זרימת נתונים עבור שלב פענוח batch-1 יחיד ושני מנגנונים המפחיתים זמן המתנה ותעבורת מטמון. (א) המעבד הגרפי מעביר משקלי Q4 ומצב מודל באמצעות מנגנון קשב, Gated DeltaNet, ניתוב ו-kernels מומחים מאוחדים, ולאחר מכן כותב את האסימון הנבחר ישירות לתוך חריץ הקלט של השלב הבא תוך שליחת עותק למעבד המרכזי. (ב) תזמון מודע-תלויות מאפשר ל-kernels בלתי תלויים לחפוף. (ג) אריזת GQA מאפשרת לארבעה ראשי שאילתות לחלוק כל טעינת שורת KV, ובכך מצמצמת שמונה בקשות נפרדות לשתי טעינות משותפות.

אופטימיזציה של נתיב המשקל בעל השורה הבודדת

MLX כבר מעבירה עבודה של שורה בודדת למטריצה-וקטור מותאמים kernels. מכיוון שלילי אינה משתמשת ב-MLX, סביבת הריצה המותאמת אישית חייבת לספק את אותה אסטרטגיה בסיסית. מטריצת ה-GEMV המקבילה לשורה שלנו תוכננה עבור שורת אקטיבציה אחת. קבוצת סימד משתפת פעולה בפלט תוך קריאת חלקים שונים של מטריצת המשקלים במקביל.

שמירת כל שלב פענוח על גבי המעבד הגרפי

שמירת מסירת האסימון על גבי המעבד הגרפי

כל שלב פענוח מסתיים בבחירת האסימון הבא; השלב הבא מתחיל באותו אסימון כקלט. שליחת הבחירה למעבד המרכזי ולאחר מכן בחזרה למעבד הגרפי מוסיפה נקודת סנכרון לכל אסימון. במקום זאת, סביבת הריצה שלנו מחליפה בין שני מאגרי פקודות ושני חריצי אסימונים התושבים במעבד הגרפי. המעבד הגרפי בוחר את האסימון בעל הציון הגבוה ביותר וכותב את מזהה האסימון שלו ישירות לתוך חריץ הקלט לשלב הפענוח הבא, בזמן שהמעבד המרכזי מכין את העבודה הבאה.

חפיפה של עבודת מעבד גרפי בלתי תלויה

בשלב decode של batch-1 אחד שתועד, יצירת טוקן הפעילה 795 ליבות GPU. התלויות ביניהן יצרו 555 שלבים רציפים, כך שנותרו ליבות מסוימות חופשיות לרוץ במקביל. אף על פי כן, מצב הביצוע הסדרתי של Metal הריץ כל ליבה לפי הסדר.

נתיב הפענוח הממוטב רושם את תלויות הנתונים בפועל במעבר Metal בו-זמני. הפעלות kernel בלתי תלויות יכולות לפעול בו-זמנית כאשר משאבי המעבד הגרפי מאפשרים זאת. מחסום מוכנס רק כאשר עבודה מאוחרת יותר דורשת תוצאה קודמת.

צמצום תעבורת ערכי הביניים והמצבים

Kernels נפרדים יוצרים לעיתים קרובות תוצאת ביניים: kernel אחד כותב תוצאה זמנית לזיכרון, והבא בתור קורא את התוצאה בחזרה. נתיב הפענוח הממוטב ממזג ארבעה שרשראות: שתי תחזיות הקלט של המומחים יחד עם האקטיבציה הממותגת שלהן; תחזית הפלט של המומחה יחד עם ציון הניתוב שלה ותוצאת המומחה המשותף; הכנת השאילתה והמפתח לפני מנגנון הקשב; והעדכון המחזורי יחד עם הנורמליזציה שלו. כל kernel ממוזג שומר ערכים זמניים באוכפים במקום לשלוח אותם דרך הזיכרון.

מיזוג גם מקצר את גרף התלויות: כאשר כתיבת ביניים נעלמת, כך נעלם גם המחסום שהגן על צרכן הנתונים שלה.

קריאה יעילה של מטמון הקשב

איחוד קריאות ממטמון הקשב

מנגנון הקשב קורא מפתחות וערכים ממטמון ה-KV במהלך כל שלב פענוח. באנליזה החלופית, שרשורים שכנים במעבד הגרפי אינם מבקשים תמיד בייטים שכנים, מה שמאלץ את מערכת הזיכרון לשרת עסקאות נפרדות רבות יותר. הפעלת טעינות מאוחדות גורמת לשרשורים סמוכים לבקש בייטים סמוכים כך שהחומרה תוכל לשלב את הקריאות שלהם.

בתצורת bfloat16, איחוד (coalescing) הגדיל את רוחב הפס של המפתחות מ-33.8 ל-47.9 ג'יגה-בייט בשנייה, הגדיל את רוחב הפס של הערכים מ-42.0 ל-61.8 ג'יגה-בייט בשנייה, ושיפר את הפענוח מקצה לקצה ב-2.1% בהקשר של 3,840 אסימונים.

אריזת ראשי שאילתות לשימוש חוזר בשורות KV

מנגנון קשב מבוסס שאילתות קבוצתיות (grouped-query attention) מאפשר לשמונה ראשי שאילתות חלוקה של ראש מפתח-ערך (KV) יחיד. באנליזה (ablation), כל ראש שאילתות פועל בקבוצת סימד (simdgroup) נפרדת, כך שכל השמונה מבקשים באופן בלתי תלוי את אותה שורת KV המאוחסנת במטמון. ה-kernel הממוטב אורז ארבעה ראשי שאילתות בקבוצת שרשורים (threadgroup) אחת, הטוענת כל שורת KV פעם אחת ומעושה בה שימוש חוזר על פני ארבעה חישובי קשב. קבוצת שרשורים שנייה מטפלת בארבעת הראשים הנותרים.

טכניקה זו, הנקראת בדרך כלל אריזת GQA, מבצעת את אותו חשבון ומייצרת בייטים של פלט זהים תוך צמצום שמונה בקשות KV בלתי תלויות לשתי טעינות משותפות. מול האנליזה הלא-ארוזה, היא שיפרה את תפוקת הפענוח מקצה לקצה ב-23.8% בהקשר של 32K אסימונים.

החלפת פריסות קשב בהקשרים ארוכים

כל שלב פענוח בשכבת קשב מלא סורק את מטמון ה-KV הקיים. פריסת בלוקים קבועה מחלקת מטמון זה לחלקים שווים שהמעבד הגרפי יכול לעבד במקביל. התזמון הנוסף שלה אינו משתלם כאשר המטמון קטן, אך פריסת הבלוקים הקבועה מאזנת את העבודה בצורה אחידה יותר ככל שההקשר גדל.

עבור מודל זה, סביבת הריצה שומרת על נתיב הקשב הכללי מתחת ל-32K אסימונים ומשתמשת בנתיב הבלוקים הקבועים ב-32K ומעלה. המעבר חל כאשר לכל ראש יש 256 ערכים ושמונה ראשי שאילתות חולקים ראש KV; צורות אחרות נשארות בנתיב הכללי. אנליזה חלופית מבטלת מעבר זה ומשתמשת תמיד בנתיב הכללי. הפעלת נתיב הבלוקים הקבועים שיפרה את הפענוח מקצה לקצה ב-7.7% ב-32K, ב-27.4% ב-64K וב-40.2% ב-128K.

גבולות של אופטימיזציה נוספת

חלק מהשינויים שיפרו פעולה מבודדת אך לא שיפרו את ההסקה מקצה לקצה.

פענוח ספקולטיבי, שמשתמש במודל קטן יותר כדי להציע טוקנים עבור המודל המלא לאימות, האט את batch-1 decode ב-18%. האימות עיבד קבוצות של שניים עד חמישה שורות, צורה לא יעילה לחומרה זו, והשורות בחרו לעיתים קרובות מומחים שונים, מה שהגדיל את כמות נתוני משקלי המומחים שנקראו. צמצום אוצר המילים של הפלט של מודל ה-drafter שיפר את תפוקת ה-drafter ב-4.7–5.1%, אך לא הפך את לולאת ה-speculative השלמה למהירה יותר. תוצאה זו תלויה בעומס העבודה: פריסת ה-Qwen שלנו על Blackwell משתמשת בפענוח ספקולטיבי בתנאים שונים.

ניסויים אחרים כללו צמצום הפעלות מעבד גרפי, חפיפה של שלבים שלמים, שימוש באריחי הכנה גדולים יותר, החלת מיזוג רחב יותר, האצת הנתב (router), ושילוב פרויקציית הפלט יחד עם בחירת האסימונים. אף אחד מהם לא שיפר את לולאת ההסקה המלאה.

מדידות של מגבלות החומרה הראו גם מעט מאוד מרווח נשימה שנותר בפעולות ההכנה והפענוח המרכזיות. פעולות ה-GEMM וה-GEMV של ה-MoE הגיעו ל-97.9% ול-90.3% מקצבי קריאת המשקלים המקיימים המהירים ביותר עבור דפוסי הגישה שלהם. הסרת החשבון מפעולת ה-GEMV המדוללת שינתה את התפוקה ב-0.2% בלבד, מה שמאשר שקריאות משקלים, ולא חישובים, היו המשאב המגביל. כפל המטריצות בשלב ההכנה הגיע באופן דומה ל-93% ממגבלת המטריצה התיאורטית בבידוד ול-80–86% בתוך המודלים שנבדקו.

ביצועים מקצה לקצה

ההשוואה מקצה לקצה טוענת בייטים זהים של נקודת ביקורת (checkpoint) בני 4 סיביות בשתי המנועים ומריצה בקשה אחת בכל פעם על שבב M5 Max יחיד בעל 40 ליבות ו-128 ג'יגה-בייט. בתוך כל סבב, שני המנועים פועלים בסדר מתחלף כדי לצמצם את ההטיה מעומס רקע ומשינויים בטמפרטורת השבב. אנו משווים מול נתיב היצירה הישירה המהיר ביותר של MLX-LM, ולא מול שרת ההגשה שלו, כך שהמדידה מתמקדת בביצוע המודל ולא בתוספת העומס של ניהול ההגשה.

הסריקה מכסה עשרה אורכי הנחיות להכנה ועשרה אורכי הקשר לפענוח, מ-256 ועד 128K אסימונים. תפוקת ההכנה עולה בתחילה ככל שהמנוע מפיץ את עלויות ההקמה הקבועות על פני אסימונים רבים יותר. ההכנה מגיעה לשיאה סביב הנחיה בת 4K אסימונים, ואז יורדת מכיוון שעשר שכבות הקשב המלאות מבצעות עבודה רבה יותר ככל שההנחיה גדלה. הפענוח נותר שטוח כמעט לחלוטין בהקשרים קצרים ויורד ברגע שקריאת מטמון ה-KV הגדל הופכת למשמעותית. המנוע המותאם מהיר יותר בכל אורך מתועד.

מכיוון שביצוע מותאם עשוי לשנות את סדר פעולות הנקודה הצפה, בדקנו גם את העקביות הנומרית מול MLX-LM. בהשוואה כפוית-מורה (teacher-forced), שתי המנועים ניבאו את האסימון הבא מאותה קידומת ייחוס בכל אחד מ-192 המיקומים, ובכך מנעו מהבדלים קודמים להשפיע על קלטים מאוחרים יותר. מידת אי-הוודאות (perplexity) של לילה הייתה גבוהה ב-0.04% בלבד, והיא בחרה את אותו אסימון מוביל ב-96.35% מהמיקומים שנבדקו.

תפוקת prefill לפי אורך ה-prompt ותפוקת decode לפי אורך הקשר עבור Qwen3.6-35B-A3B Q4, batch 1, על M5 Max יחיד עם 40 ליבות ו-128 GB. לאורך עשרה אורכים מ-256 עד 128K tokens, Lily מהירה יותר בכל נקודה שנמדדה: פי 1.13–1.50 מתפוקת ה-prefill של MLX-LM ופי 1.26–1.34 מתפוקת ה-decode שלו. ההשוואה משתמשת במסלול ה-direct-generation המהיר ביותר של MLX-LM. שני הצירים האופקיים משתמשים בסולמות לוגריתמיים; אף אחד מהצירים האנכיים אינו מתחיל מאפס.

נבנה עבור הפלטפורמה המקומית

Apple silicon אינו מעבד גרפי קטן של מרכז נתונים. זוהי פלטפורמת הסקה מקומית שלמה עם מאפייני חברה ותוכנה משלה. זיכרון מאוחד מעניק לצומת יחיד תקרה גבוהה מאוד לגבי כמות המודל והמצב שהוא יכול להכיל. המאיצים העצביים של M5 סופגים את עבודת המטריצות הצפופות בשלב ההכנה. יחידות ה-ALU הווקטוריות מטפלות ביתרה המוגבלת ברוחב פס ומעועטת השימוש החוזר בשלב הפענוח.

Qwen מוסיפה הזדמנויות נוספות להתמחות: שמירת ניתוב מומחים ומצב מחזורי על גבי המעבד הגרפי, חיסול ערכי ביניים מיותרים, חפיפה של עבודה בלתי תלויה, שימוש חוזר בנתוני KV משותפים, והתאמת kernels לצורת עומס העבודה.

עם אופטימיזציה ייעודית למודל ולפלטפורמה, מק אחד יכול להריץ ביעילות מודל sparse גדול. עבודה עתידית תרחיב את הכיסוי across models, chips, and serving workloads, ותהפוך את המנגנונים שאומתו כאן על קונפיגורציה אחת למדיניות זמן ריצה כללית יותר.

העיקרון הרחב יותר הוא להתאים את המנוע הן לארכיטקטורת המודל והן לנתיבי החישוב והזיכרון הספציפיים של החומרה. ככל שמודלי חזית פתוחי משקלים וחומרה מתפתחים, הסקה מקומית בעלת ביצועים גבוהים תה תלויה יותר ויותר במנועים המותאמים לשניהם, במקום בכאלו המפשטים את ההבדלים ביניהם.

ציטוט

BibTeX
@online{perplexity2026OptimizingOnDeviceInferenceForAppleSilicon,
  author = {{Perplexity} and Yibo Wu and Lequn Chen and Kevin Hu and Phi Hoang and Claire Beamer and Jeremy Yang and Denis Yarats},
  title = {{Optimizing on-device inference for Apple Silicon}},
  date = {2026-09-01},
  url = {https://www.perplexity.ai/hub/blog/optimizing-on-device-inference-for-apple-silicon}
}