לדלג לתוכן

Driver API מול Runtime API ב-CUDA - שתי דרכים לדבר עם אותה חומרה

כשמתחילים ללמוד CUDA, כמעט תמיד נתקלים בפונקציות שמתחילות ב-cuda, כמו cudaMalloc או cudaMemcpy. זו רק חצי מהתמונה. מתחת לשכבה הזו יושבת שכבה נמוכה יותר, עם פונקציות שמתחילות רק ב-cu, שנותנת שליטה עדינה הרבה יותר. שתי השכבות האלה נקראות Runtime API ו-Driver API, וכדאי להבין את ההבדל ביניהן גם אם אתם משתמשים כמעט תמיד רק באחת.

Runtime API - השכבה שכולם מכירים

Runtime API היא הממשק ברמה גבוהה שרוב הקוד וכל המדריכים למתחילים משתמשים בו. פונקציות עם קידומת cuda, כמו cudaMalloc להקצאת זיכרון או cudaLaunchKernel להרצת kernel, דואגות מאחורי הקלעים לפרטים רבים בשבילכם - יצירת context, טעינת מודולים, ניהול מכשירים. התחביר קרוב יותר לכתיבת קוד C או C++ רגיל, ואפשר לשגר kernel פשוט עם תחביר הסוגריים המשולשים המוכר.

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

Driver API - השכבה שנותנת שליטה

Driver API היא ממשק ברמה נמוכה יותר, עם פונקציות שמתחילות בקידומת cu, כמו cuMemAlloc או cuModuleLoad. השכבה הזו לא עושה שום דבר "אוטומטית" בשבילכם - אתם צריכים ליצור context במפורש, לטעון מודולים של קוד מקומפל בעצמכם, ולנהל את כל מחזור החיים באופן ידני.

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

אז מה בעצם ההבדל המהותי

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

נקודה מעניינת היא שקוד שנכתב ב-Runtime API וקוד שנכתב ב-Driver API יכולים לפעמים להתקיים באותה תוכנית, אם כי זה דורש זהירות כדי לוודא שהם לא מתנגשים בניהול המשאבים.

מתי בכלל צריך לרדת ל-Driver API

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

חשוב לדעת שהיא קיימת, גם אם רוב הקריירה שלכם בתכנות GPU תעבור דרך Runtime API. זה עוד חלק מלהבין את התמונה המלאה של איך CUDA בנויה משכבות.

חלק מהתמונה השלמה

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

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

לסיכום

Runtime API ו-Driver API הן שתי דרכים שונות לדבר עם אותה חומרה - האחת נוחה ומהירה להתחיל איתה, השנייה נותנת שליטה מדויקת במחיר של מורכבות נוספת. רוב הפרויקטים ישתמשו ב-Runtime API כל הדרך, אבל הידיעה שיש חלופה נמוכה יותר היא חלק מהבשלות של מתכנת CUDA.

בואו תלמדו את שתי השכבות, עם קהילה שכבר שם.

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