המשקולות של Qwen3.8-27B הגיעו בבוקר, והיום אותו יום התחלתי הרפתקה עם Kimi K3 רץ במצב high-thinking. יזמתי את הכול עם שאלה אחת: האם 27B רענן צפוף — בקלות המודל הפתוח החזק ביותר בגודלו — יכול לשרת את סוכני הקוד שלי במהירות אמיתית על Mac Studio עם M1 Ultra, 20 ליבות CPU, 128 GB זיכרון מאוחד, ו-800 GB/s רוחב פס זיכרון? ידע נפוץ אומר שמודלים צפופים מדקודים לאט על Apple Silicon מכיוון שהם תלויים ברוחב פס זיכרון, ורציתי לגלות אם RAM ורוחב פס כזה יכולים לשבור את הדפוס. משקולות MLX של 4-bit הגיעו ל15 GB, המסגרת הייתה עדכנית, לא רצה דבר נוסף על ה-box, והמספר הראשון היה 12.1 tokens per second. הרגשתי שזה שגוי.
הייתי מסתובב סביב סוג זה של ניסוי כבר זמן מה. בחודש מרץ, בעבודה עם AI נוסף במעבדת השיפור האוטונומית שלי, עקבנו קיר של 20 tok/s עבור מודלים 30B על M4 Max ל-starvation של רוחב פס מה-OS-level paging — והחקירה הזו השאירה playbook: powermetrics ראשון, sampling לפי cluster, pinning זיכרון לפני אשמה. הריצה הזו התחילה מתוך סקרנות טהורה: שמעתי על האופטימיזציות של Qwen3.8, ורציתי לדעת אם זה ירוץ מהר מידי ה-box על מכשיר זה עם RAM כזה. רק באמצע הניסוי הריאליות המוגבלת ברוחב פס הרגישה את עצמה. מה שאחריו היה ריצה של ניסויים מבוקרים שאפיינו יחד — Kimi ניסח את ההיפותזות וקרא counters החומרה לצידי בעוד אני שומר את הידיים על המתכת. כל ניסוי נבנה כדי להוכיח או להאשים שכבה אחת של ה-stack. הניצחונות הגיעו מ2 מקומות שהfolklore של inference מקומי מתערער: hints של scheduler CPU ו-speculative decoding. החלופות המודרניות של 2 — build GGUF שמופעל על ידי llama.cpp, ומודל mixture-of-experts שנראה בלתי מנוצח על נייר — גם הם הפסידו על מדידה. מאמר זה הוא המסלול המלא של הוכחות שבנינו יחד, כי השיטה התבררה כיותר חשובה מכל מספר יחיד.

רשת העברת הנתונים והשרת היו החשודים הראשונים, ושניהם היו חפים מפשע

נתיב השירות כלל 3 קפיצות: סבב העבודה שלי, רשת ביצוע מבוססת SSH, ושרת המודל בלופבק של הסטודיו. אשמה ברשת הייתה פשוטה, אז למדנו אותה תחילה. זמני השרת עצמו אמרו 12.1 טוק/שנייה פענוח; מדד יצירה בתהליך גולמי, ללא שרת וללא רשת בכלל, יצר 11.5 טוק/שנייה. הובלת התעבורה כללה כ-25% דרך עלויות חיבור, והמודל עצמו היה השכבה האיטית.
תקלה בתעבורה הייתה שווה לתקן בכל מקרה, והיא סוג של פרט שמוציא שעות אם אי פעם לא ראית: רשת Python TCP שמשתמשת ב-read(65536) מאוחסן תורמת בלוקינג נגד פרוטוקול מקומי שיחה, מכיוון שהקריאה המאוחסנת מחכה למלא את הבופר או EOF לפני החזרה. מעבר ל-read1(), שמחזיר לאחר קריאה בסיסית אחת, גרם לרשת להתנהג. הסימפטום נראה כמו עצירה ברשת; הסיבה הייתה סמנטיקה של stdio.
עם תעבורה נקייה, עבדנו דרך שכבת sysctl הרגילה. העלאת מגבלת זיכרון קווי GPU (iogpu.wired_limit_mb) לא שינתה דבר עם 128 ג״ב RAM פנוי, אז חזרנו לזה. תהליך Python היה מקורי arm64, MLX דיווח על GPU כ-מכשיר ברירת המחדל שלו, ו-powermetrics הציג את GPU ב-54-62% פעילות עם 20-23 ו׳ במהלך פענוח. כל חשוד בתור הזה הלך חופשי — שזה בעצמו התוצאה המועילה, מכיוון שזה כיוון את החקירה ל-CPU.

המתזמן סגר את החיזוי על ליבות היעילות

קריאת powermetrics לכל אשכול CPU במקום לכל מכונה חשפה את הממצא האמיתי הראשון. במהלך פענוח, אשכולות היעילות רצו ב-75-93% מלא בעוד אשכולות הביצועים היו ריקים ב-1-12%. כל מה שמופעל מעל SSH יורש מחלקת איכות-שירות שהמערכת macOS קוראת כעבודה בעלת עדיפות נמוכה, והמתזמן כבד את רמז זה על ידי שמירת עומס קריטי לזמן על ליבות האיטיות.
התיקון היה 1 שורת ctypes, שהופעלה לפני טעינת משקולות המודל:
python
import ctypes
ctypes.CDLL("libSystem.B.dylib").pthread_set_qos_class_self_np(0x21, 0) # QOS_CLASS_USER_INTERACTIVE
הפין הזה, יחד עם טעינת מגדל הטקסט של המודל דרך mlx-lm במקום המלא של stack הראייה, העביר את פענוח הגולמי מ-11.5 ל-15.1 tok/s — רווח של 31% ממיקום המתזמן ומטעין דק, ללא שינוי במודל. מאוחר יותר למעננו שההיקף של הפין מוגבל: הוא מעביר את התהליך המופעל, ו-MLX שומר על מחלקת מתזמן משלו. עבור המודל הזה, התהליך הראשי נשא מספיק עבודה כדי להיות משמעותי.

פענוח ספקולטיבי סיפק את הקפיצה שלא יכול sysctl

הניצחון הגדול ביותר הגיע מאופציה שהמודל הבסיסי כבר הבעלים של. Qwen3.8 נשלח עם ראש חיזוי רב-טוקן — מודול עזר קטן שמסמן כמה טוקנים קדימה — והמרכיב MLX שומר בשקט את הטנסורים 15 אלה במהלך המרה. חבילת קהילה מחזירה את הראש כ-253 קופץ MB עצמאי, שהאפשר לי לשלב אותו חזרה עם המודל שהוכשר יחדיו.
דפוס השירות הוא קופץ-אחר-אימות: הקופץ מציע כמה טוקנים, המודל המלא בודק אותם ב1 מעבר, והטוקנים המקובלים נחשבים כולם. עם --draft-model ו---draft-kind mtp בשרת, קבלת קופץ נמדדה ב-94% על קידוד מציאותי והצעות שיחה, ופענוח עבר מ-15.1 ל-20.3 טוק/שׁ בצד השרת — 13.4 טוק/שׁ מקצה-ל-קצה דרך הריליי, מ-9.0. ה-GPU סיפק את הסיפור המאשר: 77% תושבות פעילה, הכל ב1296 MHz מלא, משיכת 48 W, עם אשכול הביצועים 97% תפוסה. Prefill השתפר באותו שדרוג, מ-14.7 טוק/שׁ ל-18-55 בהתאם לצורת הבקשה.
Decode speed by configuration (tok/s, M1 Ultra, 27B-4bit)
Chart data
tokens per second
MLX stackllama.cpp Q4_K_M
raw stack11.59.2
+ text tower13.6
+ QoS pin15.1
+ MTP drafter20.312.2

האתגר GGUF הפסיד ב40%

פוסטים קהילתיים מציבים את llama.cpp עם draft ספקולטיבי ב25-32 tok/s עבור מחלקת מודל זו ב-M1 Ultra, בנוחות לפני מספר MLX שלנו, לכן הענקנו לאתגר אתגר סבול: ה-Q4_K_M GGUF הרשמי, מודל draft רק MTP תואם, ובנייה נוכחית של llama.cpp עם 加速 Metal מאושרת פעילה. שורת GGUF מדידה 9.2 tok/s בסיס ו12.2 עם draft — כ-40% מאחורי מחסנית MLX שנועד להדחוף.
llama.cpp נשארת מהנדסת מצוינת; הפער כנראה נמצא איך כל קנים Metal של runtime מטפלים בcheckpoint זה על שבב זה. הלימוד הקבוע הוא פשוט יותר: מספר שמישהו אחר מדיד במכונה שלו, הבנייה שלו, והcheckpoint שלו הוא השערה על שלך. ה-18 GB של משקולות האתגר עזבו את המכונה באותו אחר הצהריים, וה-50 MB של binary llama.cpp נשארו למתחרויות עתידיות. כתבתי על כלל זה לפני כ-benchmark-driven development — הוא נושא את SEOReport from heuristics to a product — וכאן זה חוסך מיגרציה.

3B-פעיל MoE אמור היה לזכות, ומדידת GPU הסבירה את האובדן

המתמודד האחרון היה בעל התיאוריה החזקה ביותר — הידע המשותף אותו קבענו לבדוק בתחילת. מודלים צפופים מפענחים לאט על Apple Silicon מכיוון שכל טוקן מיוצר משלם לקרוא כמעט את כל המשקולות; מודל תערובת מומחים עם 35B פרמטרים סה"כ מפעיל רק כ-3B לכל טוקן, לכן במכונה מוגבלת רוחב פס הפענוח שלו אמור לרוץ כמה פעמים מהר יותר ממודל צפוף 27B — כל טוקן קורא כ-11% מהמשקולות. הורדנו את MoE 4-bit ואת טיוטת MTP התואמת, חממנו את השרת, ומדדנו 14.7 tok/s גולמי: אותו מהירות כמו המודל הצפוף שהייתה אמורה להטריד. עם פענוח ספקולטיבי הגיע ל19 tok/s על פקודות מציאותיות ו26.3 על טקסט בעל צפוי גבוה — שוויון מול 20.3 של המודל הצפוף, ללא טיעון איכות לשבור את הדילמה.
powermetrics זיהה את הרגימה ב-1 דוגמה. במהלך פענוח MoE GPU נשאר ב-0-3% רישוי פעיל בעוד קבוצות היעילות נרדו ב-60-90%. המודל משקיע את תקציבו לכל טוקן בעבודה בצד CPU, והזמן ברמת פעולה הראה למה: כל פעולה שנשלחת עולה 50-100 מיקרו-שניות עלויות, והארכיטקטורה היברידית הזו — GatedDeltaNet תשומת לב ליניארית ועוד 256 מומחים מאחורי מצב נסתר קטן 2048-רחב — מייצרת כ-78 פעולות לכל שכבה ב-40 שכבות. בגודל תור 1, ה-GPU מסיים כל קרנל קטן לפני שה-CPU יכול להמתין את הבא. המכונה הייתה מוגבלת בשליחת פעולות, והעומסים המוגבלים בשליחת פעולות אינם רוכשים דבר מקריאת משקולות פחות לכל טוקן.
Diagram source
graph TB
    A[פענוח איטי  
בגודל תור 1] --> B{GPU עסוק  
במהלך פענוח?}
    B -->|כן| C[מוגבל רוחב פס  
פחות בתים מנצלים]
    B -->|לא| D[מוגבל בשליחת פעולות  
פחות פעולות מנצלים]
    C --> E[MoE עוזר  
כמות קטנה עוזרת]
    D --> F[פענוח ספקולטיבי  
עוזר ביותר]

    style E fill:transparent,stroke:#10B981,stroke-width:2px
    style F fill:transparent,stroke:#3B82F6,stroke-width:2px
לסגור את הלולאה, הוכחנו שהנתיב של GPU עצמו בריא עם חיית סינתטית: לולאת כפל מטריצה 8192³ הגיעה ל-10.8 TFLOPS ב-bfloat16 עם GPU ב-97-100% רישוי ו-68 W. ראיות חיצוניות הסכימו עם האבחון המקומי — הערכות עצמאיות מציבות את מחלקת MoE זו בסביבות 21.7 tok/s על M2 Ultra, ו-OpenVINO מסמך את אותו מודל מאבד מול מודל צפוף 8B ב-backends עם נתיבים שליחת פעולות חלשים יותר. הדחף הצפוף 27B עם המעצבת MTP שמירה על חריץ הייצור, ו-38.5 GB של משקולות MoE נמחקו באותו ערב.
GPU active residency during decode (powermetrics, %)
Chart data
GPU active residency (%)
dense 27B + MTP77
MoE 35B-A3B2
matmul hog test100

מה שנותרו של ניסויים מבוקרים 5

המכונה כעת מספקת Qwen 3.8-27B ב-20.3 טוק/שׁ ניתוב בצד השרת, שיפור של 68% מהיום שהתחל, והפרי העמיד יותר הוא רשימת בדיקה שנשמש בה בכל קופסה עתידית:
  • פענוח בגודל תור 1 יש שני מצבים, מוגבל רוחב פס ומוגבל משלוח, ו-2 שניות powermetrics דוגמה מזהות את שלך לפני שתוציא הורדה על תיקון שגוי.
  • פענוח ספקולטיבי הוא כפתור השירות בעל ההשפעה הגבוהה ביותר עבור קופסה של משתמש יחיד. הוא הוסיף 34% כאן ומתרבה עם כל אופטימיזציה אחרת, מכיוון שקבוצות אימות עובדים את ה-GPU בעוד המעצבת סופגת את הפערים הריקים.
  • מתזמן QoS הוא פרמטר אמיתי של ניבוי ב-macOS. כל דבר שמופעל מעל SSH צריך להציב את תהליכיו בכוונה, והשפעת ההצבה ניתנת לאימות לפי אשכול ולא לפי תחושות.
  • טענות throughput קהילתיות נוסעות רע במעבר בין נקודות ביקורת, בניות, ומעבדים. מדד מקומי זול יותר מההעברה.
  • מחיקה היא חלק מהזרימה. כל אתגר שהפסיד השאיר את הכונן במהלך היום, שמירה את הניסוי הבא כנה והמכונה דקה.
החלק המרשים של הרפתקה זו הוא שהשאלות היו כלולות במונה החומרה, מחכות למישהו לשאול שאלות מדויקות — והפעם שאלנו יחד. מודל מקומי שהמדדת הוא יקר יותר ממודל גדול שהשערת עליו — אותו תשואה מתרחבת שאני מקבל מטיפול local AI gains as infrastructure במקום טריוויה. יזמתי את הכול בבוקר שהמשקולות נחתו, ו-Kimi K3 נשארת במאבק לכל ניסוי, לכל קריאת מונה, ולכתיבה זו מההערות המעבדה של אותו ערב. הניסוי הבא כבר בתור: גרפים מפוענחים משולבים מבטיחים לכבות את עלות המשלוח לכל פעולה שהחליטה את ההחלטה MoE, וכאשר שחרור MLX נופל אחד, ההתאמה תיקח אחר הצהריים והורדה אחת.