לדלג לתוכן

תכנות מולטי-GPU מוסבר - כשכרטיס אחד כבר לא מספיק

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

למה בכלל צריך יותר מכרטיס אחד

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

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

שתי אסטרטגיות חלוקה בסיסיות

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

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

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

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

האתגר האמיתי - תקשורת בין כרטיסים

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

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

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

למה זה קריטי לאימון מודלים גדולים

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

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

לסיכום

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

מי שמבין את הדינמיקה הזו, מבין למעשה איך בנויה כל תשתית ה-AI המודרנית מאחורי הקלעים.

הצטרפו לקהילה בדיסקורד