כשמשתמשים ב-Dataflow להסקת מסקנות של ML, מומלץ להשתמש בטרנספורמציה RunInference. לשימוש בטרנספורמציה הזו יש כמה יתרונות, כולל:
- ניהול חכם של זיכרון המודל שעבר אופטימיזציה עבור עובד (worker) של Dataflow כשמבצעים היקש מקומי.
- חבילות דינמיות שמשתמשות במאפייני צינור עיבוד הנתונים ובאילוצים שהוגדרו על ידי המשתמש כדי לשפר את הביצועים.
- תכונות קצה עורפי של Dataflow שמבוססות על למידת מכונה, שיכולות לספק תפוקה וחביון טובים יותר.
- מנגנונים חכמים של השהיה לפני ניסיון חוזר והתאמה אוטומטית לעומס כשמגיעים למכסות של היקש מרחוק.
- מדדים ותכונות תפעוליות שמוכנים לשימוש בסביבת ייצור.
כשמשתמשים בפרמטר RunInference, חשוב לקחת בחשבון את הדברים הבאים:
ניהול זיכרון
כשאתם טוענים מודל ML בינוני או גדול, יכול להיות שייגמר הזיכרון במחשב. Dataflow מספק כלים שיעזרו לכם להימנע משגיאות של חוסר זיכרון (OOM) כשאתם טוענים מודלים של למידת מכונה (ML).
כדי לבצע אופטימיזציה יעילה של צינור הנתונים, חשוב להבין את יחידות החישוב השונות ב-Dataflow:
- VM: המכונה הווירטואלית (סוג המכונה), כמו
n1-standard-8. במסמכי Dataflow, המונח הזה נקרא לפעמים worker. - תהליך: תהליך עובד של Python SDK. כברירת מחדל, מערכת Dataflow מפעילה תהליך אחד לכל vCPU במכונה הווירטואלית.
- שרשור: משימה אחת שניתנת להרצה ופועלת בתוך תהליך. כל שרשור מבצע
DoFn.
זיכרון המודל לעומת זיכרון הנתונים
שגיאות OOM בדרך כלל נחלקות לשתי קטגוריות:
- בעיות בזיכרון שקשורות למודל: מתרחשות כשהמודל של ה-ML גדול מדי ולא ניתן להכניס כמה עותקים שלו לזיכרון.
- בעיות בזיכרון שקשורות לנתונים: מתרחשות כשעיבוד של כמויות גדולות של נתונים (שלא קשורות לגודל המודל) חורג מהזיכרון הזמין.
הטבלה הבאה תעזור לכם להבין איזו גישה מתאימה לתרחיש שלכם.
| תרחיש | פתרון |
|---|---|
| המודלים קטנים מספיק כדי להיכנס לזיכרון. |
להשתמש בהמרת RunInference בלי הגדרות נוספות. הטרנספורמציה RunInference משתפת את המודלים בין השרשורים. אם אפשר להריץ מודל אחד לכל ליבת CPU במחשב, אפשר להשתמש בהגדרת ברירת המחדל של צינור העיבוד. הפעולה הזו טוענת עותק אחד של המודל לכל תהליך.
|
| כמה מודלים שאומנו בצורה שונה מבצעים את אותה משימה. | שימוש במפתחות לכל מודל. מידע נוסף מופיע במאמר בנושא הפעלת הסקה של למידת מכונה באמצעות כמה מודלים שאומנו בצורה שונה. |
| מודל אחד נטען לזיכרון, וכל התהליכים במכונה וירטואלית חולקים את המודל הזה. |
שימוש ב- אם אתם יוצרים handler של מודל בהתאמה אישית, במקום להשתמש בפרמטר |
| צריך להגדיר את המספר המדויק של המודלים שנטענו במחשב. |
כדי לשלוט בדיוק בכמות המודלים שנטענים לכל מכונה וירטואלית, מגדירים את הערך של אם אתם יוצרים handler של מודל בהתאמה אישית, צריך להגדיר מחדש את הפרמטר |
| הזיכרון עומד להיגמר בגלל עיבוד הנתונים, ולא בגלל גודל המודל (הנתונים חורגים מהזיכרון). |
נסו את האפשרויות הבאות לפי הסדר:
|
מידע נוסף על ניהול הזיכרון ב-Dataflow זמין במאמר בנושא פתרון שגיאות של חוסר זיכרון ב-Dataflow.
הוספה לקבוצה
יש הרבה דרכים לבצע אצווה ב-Beam, אבל כשמבצעים הסקה, מומלץ להשתמש בטרנספורמציה RunInference כדי לטפל באצווה. אם המודל שלכם מניב את הביצועים הכי טובים עם גודל אצווה ספציפי, כדאי להגביל את פרמטרים של גודל האצווה של RunInference. רוב הפונקציות לטיפול במודלים חושפות את הגודל המקסימלי והמינימלי של אצווה כפרמטרים. לדוגמה, כדי לשלוט בגודל אצווה שמוזנת לצינור של HuggingFace, אפשר להגדיר את המטפל במודל הבא:
mh = HuggingFacePipelineModelHandler('text-classification', min_batch_size=4, max_batch_size=16)
הטרנספורמציה RunInference תמיד מכבדת את גודל האצווה המקסימלי. גודל האצווה המינימלי הוא יעד, אבל לא מובטח שהוא יכובד בכל המקרים. לדוגמה, אפשר לעיין בשליחת בקשות בקבוצות בקטע הבא.
חבילות של קבוצות
Dataflow מעביר נתונים לטרנספורמציות בחבילות. גודל החבילות האלה משתנה בהתאם לשיטות ההיוריסטיות שמוגדרות ב-Dataflow. בדרך כלל, חבילות בצינורות עיבוד באצ' גדולות למדי (O(100s) אלמנטים), בעוד שבצינורות עיבוד סטרימינג הן יכולות להיות קטנות למדי (כולל גודל 1).
כברירת מחדל, RunInference יוצר קבוצות מכל חבילה ולא יוצר קבוצות בין חבילות. כלומר, אם הגודל המינימלי של אצווה הוא 8, אבל נשארו רק 3 רכיבים בחבילה, RunInference ישתמש בגודל אצווה של 3. ברוב
הפונקציות לטיפול במודלים יש פרמטר max_batch_duration_secs שמאפשר
לשנות את ההתנהגות הזו. אם המדיניות max_batch_duration_secs מוגדרת, RunInference
היא מחלקת את החבילות לקבוצות. אם הטרנספורמציה לא יכולה להשיג את גודל האצווה המקסימלי שלה עם חבילה אחת, היא ממתינה לכל היותר max_batch_duration_secs לפני שהיא יוצרת אצווה. לדוגמה, כדי להפעיל קיבוץ באצווה של קריאות בין חבילות כשמשתמשים בצינור (pipeline) של HuggingFace, אפשר להגדיר את המטפל במודל הבא:
mh = HuggingFacePipelineModelHandler('text-classification', min_batch_size=4, max_batch_size=16, max_batch_duration_secs=3)
התכונה הזו שימושית אם אתם נתקלים בגודלי אצווה נמוכים מאוד בצינור העיבוד. אחרת, בדרך כלל לא כדאי להשתמש בעלות הסנכרון כדי להעביר נתונים בין חבילות, כי זה עלול לגרום לערבוב יקר.
טיפול בכשלים
טיפול בשגיאות הוא חלק חשוב בכל תהליך ייצור. Dataflow מעבד רכיבים בחבילות שרירותיות ומנסה שוב את כל החבילה אם מתרחשת שגיאה ברכיב כלשהו בחבילה. אם לא תפעילו טיפול נוסף בשגיאות, Dataflow ינסה שוב ארבע פעמים חבילות שכוללות פריט שנכשל, כשהוא פועל במצב אצווה. הצינור נכשל לחלוטין אם חבילה אחת נכשלת ארבע פעמים. כשמפעילים את Dataflow במצב סטרימינג, המערכת מנסה שוב ושוב לעבד חבילה שכוללת פריט שנכשל, ולכן יכול להיות שצינור הנתונים ייעצר לתמיד.
RunInference מספקת מנגנון מובנה לטיפול בשגיאות באמצעות הפונקציה with_exception_handling.
כשמחילים את הפונקציה הזו, כל הכשלים מנותבים ל-failure נפרד
PCollection יחד עם הודעות השגיאה שלהם. כך תוכלו לעבד אותם מחדש. אם
משייכים פעולות של עיבוד מוקדם או עיבוד אחרי למטפל במודל, RunInference המערכת מעבירה גם אותן לאוסף הכשלים. לדוגמה, כדי לאסוף את כל הכשלים ממטפל במודל עם פעולות של עיבוד מקדים ועיבוד פוסט, משתמשים בלוגיקה הבאה:
main, other = pcoll | RunInference(model_handler.with_preprocess_fn(f1).with_postprocess_fn(f2)).with_exception_handling()
# handles failed preprocess operations, indexed in the order in which they were applied
other.failed_preprocessing[0] | beam.Map(logging.info)
# handles failed inferences
other.failed_inferences | beam.Map(logging.info)
# handles failed postprocess operations, indexed in the order in which they were applied
other.failed_postprocessing[0] | beam.Map(logging.info)
חסימות זמניות
כשמשתמשים בתכונה with_exception_handling של RunInference, אפשר גם להגדיר פסק זמן לכל פעולה, והוא נספר לכל אצווה. כך אפשר למנוע מצב שבו מסקנה תקועה אחת גורמת לצינור כולו לא להגיב. אם מתרחש זמן קצוב לתפוגה, הרשומה שחל עליה זמן קצוב לתפוגה מנותבת אל הכשל PCollection, כל מצב המודל מנוקה ונוצר מחדש, והרצה רגילה נמשכת.
# Timeout execution after 60 seconds
main, other = pcoll | RunInference(model_handler).with_exception_handling(timeout=60)
החל מגרסה Beam 2.68.0, אפשר גם לציין פסק זמן באמצעות אפשרות הצינור --element_processing_timeout_minutes. במקרה כזה, פסק זמן גורם לניסיון חוזר של פריט עבודה שנכשל עד שהוא מצליח, במקום להפנות את ההיקש שנכשל אל תור של הודעות שלא נמסרו.
עבודה עם מאיצים
כשמשתמשים במאיצים, להרבה מטפלים במודלים יש הגדרות ספציפיות למאיצים שאפשר להפעיל. לדוגמה, כשמשתמשים ב-GPU ובצינורות של Hugging
Face, מומלץ להגדיר את הפרמטר device ל-GPU:
mh = HuggingFacePipelineModelHandler('text-classification', device='GPU')
אם אתם טוענים יותר מעותק אחד של המודל שלכם ל-GPU יחיד (לדוגמה, באמצעות model_copies > 1), מומלץ להפעיל את NVIDIA Multi-Process Service (MPS). ה-MPS מאפשר לכמה תהליכים לשתף משאבי GPU בו-זמנית, מה שיכול לשפר באופן משמעותי את קצב העברת הנתונים ואת המקביליות. מידע נוסף מופיע במאמר שיפור הביצועים ב-GPU משותף באמצעות NVIDIA MPS.
מומלץ גם להתחיל עם מופע מכונה וירטואלית יחיד ולהריץ בו את צינור העיבוד באופן מקומי. כדי לעשות את זה, פועלים לפי השלבים שמפורטים במדריך לפתרון בעיות ב-GPU. כך אפשר לקצר משמעותית את הזמן שנדרש להפעלת צינור. הגישה הזו יכולה לעזור לכם להבין טוב יותר את ביצועי המשרה.
מידע נוסף על שימוש במאיצים ב-Dataflow זמין במסמכי התיעוד של Dataflow בנושא GPU ו-TPU.
ניהול יחסי תלות
צינורות ML כוללים לעיתים קרובות תלויות גדולות וחשובות, כמו PyTorch או TensorFlow. כדי לנהל את התלות הזו, מומלץ להשתמש במאגרי תגים בהתאמה אישית כשפורסים את העבודה בסביבת הייצור. כך אפשר לוודא שהעבודה תתבצע בסביבה יציבה בכמה הרצות, ולפשט את תהליך איתור הבאגים.
מידע נוסף על ניהול יחסי תלות זמין בדף בנושא ניהול יחסי תלות ב-Python ב-Beam.
המאמרים הבאים
- כדאי לעיין בקובצי ה-notebook של Dataflow ML כדי לראות דוגמאות מעשיות.
- מידע מפורט על שימוש בלמידת מכונה (ML) עם Apache Beam זמין במאמר בנושא צינורות עיבוד נתונים של AI/ML.
- מידע נוסף על
RunInferenceAPI - מידע נוסף על המדדים
שבהם אפשר להשתמש כדי לעקוב אחרי
RunInferenceהשינוי. - בדף About Dataflow ML (מידע על למידת מכונה ב-Dataflow) יש סקירה כללית של יכולות למידת המכונה של Dataflow.