שיטות מומלצות להסקת מסקנות באצווה ב-GKE

במסמך הזה מוסברות שיטות מומלצות להרצה של עומסי עבודה של הסקת מסקנות באצווה ב-Google Kubernetes Engine‏ (GKE). הסקת מסקנות (inference) באצווה היא תהליך שבו משתמשים במודל של למידת מכונה כדי ליצור תחזיות לגבי מערכי נתונים גדולים. בתהליך הזה, המטרה היא להשיג תפוקה גבוהה וחיסכון בעלויות, ולא לספק תשובות מיידיות עם זמן אחזור נמוך.

במדריך הזה אנחנו מבחינים בין הסקת מסקנות באצווה לבין בקשות באצווה (או אצווה דינמית) – שיטה בצד השרת במנועים כמו vLLM או SGLang שמקבצת בקשות מקבילות בזמן אמת כדי לשפר את היעילות של המאיץ. אפשר להשתמש באפשרות 'בקשות באצווה' כדי להריץ עומסי עבודה של הסקת מסקנות באצווה.

השיטות המומלצות במדריך הזה מתייחסות לשני סוגים נפוצים של דפוסי הסקה באצווה:

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

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

בחירת תבנית ארכיטקטונית לעיבוד של הסקת מסקנות באצווה

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

שימוש בהסקת מסקנות באצווה כמעט בזמן אמת לעומסי עבודה עם שיאים

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

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

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

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

  • זמן אחזור: אפשר לצפות לזמן עד לטוקן הראשון שנע בין עשרות שניות לדקות.
  • מקורות נתונים: בדרך כלל מעבדים מערכי נתונים בגודל של מגה-בייט עד גיגה-בייט, כמו הודעות מ-Pub/Sub או קבצים מ-Cloud Storage שנצברו בחלון זמן קצר.
  • דפוס שימוש ב-Compute: התשתית שלכם צריכה לתמוך בשירות רציף שמטפל בפרצי עבודה תכופים.
  • אופטימיזציה של העלויות: התבנית הזו מציעה איזון בין הסקה בזמן אמת עם השהיה נמוכה לבין עיבוד אופליין עם תפוקה גבוהה.

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

הוספה של משימות לרשימת ההמתנה במצב אופליין מתאימה למשימות גדולות שמתבצעות מדי פעם, שיכולות לסבול עיכובים של שעות או ימים, כמו המשימות הבאות:

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

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

כשמטמיעים הסקת מסקנות אופליין בקבוצות, חשוב לקחת בחשבון את המאפיינים הבאים:

  • זמן אחזור: זמן האחזור של התחלת עומס עבודה נע בדרך כלל בין דקות לימים, כי לעיתים קרובות העבודות מתוזמנות לשעות שבהן העומס נמוך.
  • מקורות נתונים: אתם מעבדים מערכי נתונים גדולים, מגיגה-בייט ועד פטה-בייט, שבדרך כלל מאוחסנים ב-Cloud Storage או בטבלאות BigQuery.
  • דפוס מחשוב: אתם משתמשים במשימות אפיזודיות ואינטנסיביות שמתחילות, מעבדות את הנתונים ואז מסתיימות.
  • אופטימיזציה של עלויות: אפשר לבצע אופטימיזציה של הדפוס הזה באמצעות מודל של תשלום לפי שימוש. מכיוון שלמשימות אופליין יש חלונות השלמה גמישים, מומלץ להשתמש במכונות וירטואליות מסוג Spot כדי להפחית את העלויות.

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

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

שימוש במכונות VM מסוג Spot כדי לצמצם את עלויות החישוב

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

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

שיפור גודל האצווה של עומס העבודה וגודל האצווה של הבקשה

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

כוונון גודל האצווה של עומס העבודה

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

כדי לקבוע את גודל אצווה האופטימלי של עומס העבודה, משתמשים בגבולות הבאים:

  • חישוב גודל האצווה המינימלי: מוודאים שגודל האצווה של עומס העבודה גדול לפחות כמו גודל האצווה של הבקשה. לדוגמה, שליחת פריט אחד לשרת שיכול לעבד 256 פריטים בו-זמנית תגרום לניצול חלקי בלבד של השרת. כדי למצוא את הגודל המינימלי, בודקים את ההגדרה של שרת ההסקה, כמו הארגומנט max_num_seqs ב-vLLM. אתם יכולים להגדיר את הלוגיקה של הלקוח כך שתקבץ כמה פריטים לבקשה אחת, או לפצל את הנתונים כך שכל משימה תקבל כמות מינימלית של נתונים שעומדת בדרישות של גודל אצווה הבקשות או עולה עליהן.
  • חישוב הגודל המקסימלי של אצווה: מוודאים שגודל האצווה של עומס העבודה מאפשר ל-Pod לסיים לפני שמגיעים לזמן הקצוב לתפוגה activeDeadlineSeconds שמוגדר בKubernetes Job. כדאי להעריך את הזמן שנדרש לעיבוד של קבוצת בקשות אחת ולהגדיר את גודל עומס העבודה כך שה-Pod יסיים את העיבוד הרבה לפני המועד האחרון. לדוגמה, אם activeDeadlineSeconds הוא 3,600 שניות, והתקורה של האתחול היא 600 שניות, צריך לוודא שזמן הביצוע המקסימלי מאפשר ל-Pod להסתיים תוך פחות מ-3,000 שניות.

אם גודל האצווה של עומס העבודה קטן מדי, המשימה תבזבז זמן על תקורה של הפעלת ה-Pod (הורדת משקלים, הקצאת משאבים, הפעלת המאיץ). אם גודל האצווה גדול מדי, קיים סיכון שהמשימה תופסק על ידי GKE בגלל פסק הזמן של activeDeadlineSeconds, מה שיגרום לכך שהמשימה תיכשל וההתקדמות שלה תאבד.

שינוי גודל האצווה של הבקשות

גודל אצווה הבקשות הוא מספר הבקשות בו-זמניות ששרת ההסקה מעבד בו-זמנית במאיץ. כדי לבצע אופטימיזציה של הפרמטר הזה, צריך לשנות את ההגדרות של דגלים ספציפיים לשרת בהגדרות של שרת ההסקה (לדוגמה, הדגל --max-num-seqs ב-vLLM).

המטרה היא למקסם את השימוש ב-GPU בלי להפעיל שגיאות של חוסר זיכרון (OOM). אם גודל אצווה של הבקשות לא מכויל, המערכת תשתמש במאיץ בצורה לא יעילה או שהשרת של המודל יקרוס. ב-vLLM, אפשר להשתמש בכלים כמו סקריפט auto_tune של vLLM כדי למצוא את הערכים הכי טובים להגדרות max_num_seqs ו-max_num_batched_tokens עבור החומרה הספציפית שלכם. מידע נוסף זמין במאמר אופטימיזציה של ההגדרה של שרת ההסקה במדריך סקירה כללית של שיטות מומלצות להסקה ב-GKE.

הטמעה של רכיבים אסינכרוניים לאיגום כמעט בזמן אמת

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

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

בתרשים מוצג התהליך מ-Pub/Sub למנויים, לשער היקש ולשרת היקש, כשהתוצאות נשמרות ב-AlloyDB וההודעות שנכשלו נשלחות לנושא להודעות ללא מוצא.

פלטפורמת הסקת מסקנות באצווה כמעט בזמן אמת ב-GKE.

הארכיטקטורה מורכבת מהרכיבים הבאים:

  • נושא Pub/Sub: משמש כמאגר זמני קבוע להודעות שמגיעות מהלקוח, עם תקופת שמירה של 7 עד 31 ימים.
  • רכיב Subscriber: רכיב שקורא חבילות של הודעות, שולח בקשות לשרת ההסקה ומאשר את העיבוד.
  • Subscriber HPA: scales the subscriber deployment based on the num_undelivered_messages metric (the number of unacknowledged messages).
  • אחסון: שמירת תוצאות ההסקה באמצעות מסד נתונים (כמו AlloyDB) או אחסון אובייקטים (כמו Cloud Storage) .
  • Inference Gateway: חושף את עומסי העבודה של ההסקות למנוי.
  • שרת הסקה: מעבד את בקשות ההסקה באצווה (לדוגמה, vLLM).
  • Server HPA: שינוי קנה המידה של מנוע ההסקה על סמך מדדים ספציפיים למנוע, כמו vllm:num_requests_waiting.
  • נושא להודעות ללא מוצא: כולל הודעות שלא ניתן לעבד אחרי מספר מסוים של ניסיונות חוזרים עם השהיה מעריכית לפני ניסיון חוזר (exponential backoff).

מידע נוסף זמין ביישום לדוגמה ב-GitHub.

בקשות לאגירה ולשמירה זמנית

כדי לנהל את זרימת הבקשות:

  • שימוש ב-Pub/Sub כמאגר נתונים זמני עמיד: הטמעה של Pub/Sub לאחסון עמיד של בקשות הסקה. ההגדרה הזו פועלת כמאגר FIFO שמכיל בקשות עד שלצרכן יש את היכולת לעבד אותן, וכך מונעת עומס יתר על השרת במהלך תנועה גבוהה.
  • שימוש במינויים מסוג pull עם בקרה על זרימת נתונים בצד הלקוח: הגדרת מודל מינוי מסוג Pull. כך אפליקציית המנוי יכולה לבקש הודעות רק כשיש לה יכולת לעבד אותן, ואתם מקבלים שליטה מלאה על קצב הצריכה.
  • צריך לצבור הודעות כדי למלא את גודל האצווה של השרת: לא מומלץ לשלוח הודעת Pub/Sub אחת כבקשת הסקה אחת. במקום זאת, המנוי צריך לאגד כמה הודעות בבקשת Batch אחת שתואמת לגודל אצווה האופטימלי של שרת ההיקש (לדוגמה, תואם להגדרות max_num_seqs ב-vLLM). הגישה הזו עוזרת לוודא שההאצות מגיעות לרוויה מלאה וממקסמת את קצב העברת הנתונים. באופן ספציפי, צריך להגדיר את הגדרת המשיכה של המנוי למספר שהוא כפולה של max_messages כדי להבטיח שכל העברה קדימה של המודל תהיה רוויה לחלוטין.max_num_seqs

הגדלה אוטומטית של מספר המנויים והשרתים

כדי להסיק מסקנות יעילות לגבי קבוצות של נתונים, צריך לשנות את קנה המידה של המשתמשים הרשומים (מוגבלים על ידי CPU) באופן שונה משינוי קנה המידה של שרתי ההסקה (מוגבלים על ידי GPU או TPU).

  • התאמת מספר המנויים בהתאם לעומס העבודה: הגדרת HorizontalPodAutoscaler‏ (HPA) לפריסת המנויים בהתאם למדד num_undelivered_messages מ-Pub/Sub. מידע נוסף זמין במאמר בנושא אופטימיזציה של שינוי גודל אוטומטי של Pod על סמך מדדים. כדי לחשב את מספר הרפליקות שרוצים להשתמש בהן, משתמשים במשוואה הבאה:

    \[ desiredReplicas = \frac{num\_undelivered\_messages}{target\_latency\_seconds \times throughput\_per\_replica} \]

  • התחשבות במכסות של התשתית: הגבלת מספר הרפליקות המקסימלי של המנויים על ידי הגדרת ההגדרה maxReplicas ב-HPA. אל תגדילו את מספר המנויים מעבר למכסת ה-GPU או ה-TPU של שרתי ההסקה. הקצאת יתר של מנויים תגרום לצוואר הבקבוק לעבור לשרת ההסקה, ותגדיל את התחרות על המשאבים בלי להגדיל את קצב העברת הנתונים.

  • התאמת גודל השרתים של ההסקה על סמך מדדי המנוע: התאמת גודל הפריסה של שרת ההסקה על סמך מדדים שמיוצאים ישירות על ידי מנוע ההסקה (לא רק דרך CPU/זיכרון). לדוגמה, אפשר להשתמש בהגדרה vllm:num_requests_waiting של vLLM, שמודדת ישירות את העומס של העיבוד ברמת שרת המודל. מידע נוסף מופיע במאמר בנושא שינוי אוטומטי של גודל ה-Pods.

טיפול בשגיאות ובפסק זמן

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

  • הארכת מועדים לאישור באופן יזום: הגדרת המנוי להארכת המועד לאישור (ack) של Pub/Sub באופן יזום עבור הודעות שעוברות עיבוד, כדי למנוע לולאות של מסירה חוזרת ועיבוד כפול. הגישה הזו נדרשת כי משימות הסקה לרוב אורכות יותר מחלונות הזמן הקצובים שמוגדרים כברירת מחדל. ככלל, כדאי להגדיר את תקופת ההארכה כך שתהיה ארוכה יותר מזמן ההסקה של אצווה במקרה הגרוע ביותר.
  • בידוד כשלים באמצעות נושא להודעות ללא מוצא: הפעלה של נושא להודעות ללא מוצא מאפשרת לבודד באופן אוטומטי הודעות פגומות שלא נמסרו שוב ושוב. הגישה הזו מונעת מהודעות מסוג "כדור רעל" לחסום את התור ולהפסיק את כל הצינור.
  • הטמעת אסטרטגיות השהיה לפני ניסיון חוזר: אם שרת ההסקה מחזיר שגיאות 429 (יותר מדי בקשות) או 503 (השירות לא זמין), המנוי צריך לזהות את השגיאות האלה ולהטמיע אסטרטגיית השהיה מעריכית לפני ניסיון חוזר, ולהשהות באופן זמני את הצריכה מ-Pub/Sub עד שהשרת יחזור לפעולה.

תיאום של עבודות אופליין בכמות גדולה

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

שימוש ב-JobSet להסקת מסקנות מבוזרת בכמה צמתים

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

‫JobSet הוא API מקורי של Kubernetes שמנהל קבוצות של משימות כיחידה אחת, ומספק את היתרונות הבאים להסקת מסקנות באצווה:

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

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

כשמשתמשים ב-JobSet, צריך להגדיר את ReplicatedJob לשימוש בהגדרה completionMode: Indexed. ההגדרה הזו מחדירה באופן אוטומטי משתנה סביבה JOB_COMPLETION_INDEX לכל Pod. קוד ההסקה יכול להשתמש באינדקס הזה כדי לבחור באופן דטרמיניסטי נתח נתונים ייחודי לעיבוד.

לדוגמה, אם יש לכם קטגוריית Cloud Storage עם 100,000 תמונות ואתם פורסים JobSet עם מקביליות של 10, כל אחד מ-10 ה-Pods קורא את האינדקס שלו (0-9) בהפעלה. לאחר מכן, Pod 0 יכול לחשב שהוא צריך לעבד את התמונות 0 עד 9,999, בעוד ש-Pod 1 מעבד את התמונות 10,000 עד 19,999. הגישה הזו מצמצמת את הצורך בשירות נפרד של תור משימות.

שימוש בתבנית sidecar לשיפור ביצועים של שרתים

כדי למקסם את השימוש במאיץ, צריך להגדיר את ה-Pods של JobSet עם שני קונטיינרים באמצעות תבנית sidecar:

  • שרת הסקה: שרת שעבר אופטימיזציה (כמו vLLM) שמתמקד כולו בחישובים של GPU או TPU.
  • מנהל התקן של הלקוח: מאגר לוגיקה ששולח באופן אסינכרוני נפח גבוה של בקשות לשרת במארח המקומי.

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

סיכום רשימת המשימות

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