לדלג לתוכן

קורס תכנות GPU ו-CUDA

קורס שלוקח אתכם מהבנה של למה בכלל קיימים מעבדים גרפיים (GPU- כרטיס מסך) ואיך הם בנויים, ועד ליכולת לכתוב, לנתח ולייעל קוד GPU מקצועי בעצמכם. נתחיל מהשאלה למה מעבד רגיל לא מספיק, נבנה תמונה מדויקת של הgpu מבפנים - מ-GPC ו-SM ועד ל-Tensor Cores ולהיררכיית הזיכרון, נלמד את מודל התכנות של CUDA לעומק, נצלול לקימפול מ-CUDA C דרך PTX ל-SASS, נכיר את כל הstack התוכנתי של הgpu (drivers, runtime, ספריות), ונסגור עם שיפורי ביצועים: מודל ה-Roofline, occupancy, coalescing, וכתיבה ואופטימיזציה של kernels אמיתיים עד לניצול מלא של החומרה.

הקורס הזה הוא קורס מתקדם. הוא בנוי סביב הבנה עמוקה של החומרה, אבל כל מושג מתורגם מיד לקוד CUDA C++ שרץ על כרטיס אמיתי, עם מדידות. בסוף הקורס תוכלו לקחת kernel נאיבי, למדוד אותו, לזהות את צוואר הבקבוק, ולשפר אותו פי כמה וכמה - בדיוק כמו שעושים בעבודה אמיתית על מודלים של בינה מלאכותית, סימולציות מדעיות ועיבוד תמונה.

דרישות קדם

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

מה צריך כדי להריץ את הקוד

כדי לתרגל צריך גישה לכרטיס גרפי של NVIDIA. יש כמה אפשרויות:

  • כרטיס NVIDIA לוקלי (כל כרטיס מדור Maxwell ומעלה יעבוד, אבל Turing/Ampere ומעלה עדיפים בשביל Tensor Cores).
  • הGoogle Colab מציע גישה חינמית ל-GPU (T4) עם CUDA מותקן.
  • שירותי ענן שמשכירים GPU לפי שעה, למשל Modal, Lambda, או מכונות GPU ב-AWS/GCP.

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

תוכן הקורס

פרק 0 - הקדמה: עולם ה-GPU

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

פרק 1 - ארכיטקטורת חומרת ה-GPU

צלילה עמוקה לתוך הסיליקון. המבנה ההיררכי של הכרטיס - GPC, TPC ו-SM, מבנה ה-Streaming Multiprocessor והחלוקה שלו לתת-מחיצות, יחידות הביצוע (CUDA cores, SFU, LSU), ה-Warp Scheduler שמזין אותן, ה-Tensor Cores שמאיצים כפל מטריצות, וכל היררכיית הזיכרון בחומרה מ-register file ועד ל-HBM. כאן בונים את המודל המנטלי שכל השאר מסתמך עליו.

פרק 2 - מודל התכנות של CUDA

איך מתרגמים את החומרה למודל תכנותי. threads ו-warps ומודל ה-SIMT, ההיררכיה של blocks ו-grids ואיך היא ממופה לחומרה, כתיבת kernel עם אינדוקס נכון ו-launch configuration, סנכרון ו-cooperative groups, ומושג ה-compute capability שקובע אילו יכולות זמינות בכל דור ארכיטקטורה.

פרק 3 - זיכרון: היררכיה, shared memory וניהול

הזיכרון הוא לב האופטימיזציה ב-GPU. היררכיית הזיכרון הלוגית וההיקפים (registers, shared, global, local, constant), ניהול זיכרון מהמארח (cudaMalloc, pinned memory, unified memory ו-streams), שימוש חכם ב-shared memory לטכניקת tiling, וסוגי הזיכרון המיוחדים - constant ו-texture.

פרק 4 - שפות הביניים: PTX, SASS והקומפיילר

מה קורה בין הקוד שכתבנו לחומרה. PTX - שפת האסמבלי הווירטואלית של NVIDIA וה-JIT, SASS - האסמבלי האמיתי של החומרה ואיך קוראים אותו, המהדר nvcc ותהליך ה-fatbin, הידור בזמן ריצה עם nvrtc, וכלי הבינארי שמאפשרים לפרק ולנתח כל artifact.

פרק 5 - מחסנית התוכנה במארח

כל מה שרץ על ה-CPU כדי לשלוט ב-GPU. ההבדל בין ה-driver API ל-runtime API והרעיון של context, הדרייבר עצמו (nvidia.ko ו-libcuda), ה-runtime ו-libcudart, ניטור וניהול עם NVML ו-nvidia-smi, ו-CUDA Graphs שמצמצמים את ה-overhead של הרצת הרבה kernels קטנים.

פרק 6 - ספריות ביצועים

בעבודה אמיתית לא כותבים הכל מאפס. cuBLAS לאלגברה לינארית ו-GEMM, cuDNN ל-primitives של רשתות עמוקות, CUTLASS לבניית GEMM מותאם בתבניות C++, ו-CuTe וה-CuTe DSL - הבסיס המודרני לתכנות עם layouts ו-tiles שמאחורי הספריות המהירות ביותר היום.

פרק 7 - תיאוריית הביצועים

לפני שמייעלים, צריך לדעת מה אפשרי. מודל ה-Roofline שמראה את הגבול העליון של הביצועים, ההבחנה בין kernel שחסום על חישוב לכזה שחסום על זיכרון ומושג ה-arithmetic intensity, רוחבי הפס ו-peak rate של החומרה, ומושגי ה-overhead, latency hiding וחוק Little שמסבירים כמה עבודה מקבילה צריך כדי להסתיר latency.

פרק 8 - מדדי ביצועים ואופטימיזציה

כאן הופכים תיאוריה למעשה. occupancy ומצבי ה-warp, ניצול יחידות הביצוע (SM utilization, pipe utilization, issue efficiency), הבעיות של warp divergence ו-scoreboard stalls, הטכניקה הקריטית של memory coalescing והימנעות מ-bank conflicts, וניהול register pressure. כל מושג מלווה בקוד לפני ואחרי ובמדידה שמראה את השיפור.

פרק 9 - פרופיילינג ופרויקטים

לסגור את הלולאה. כלי הפרופיילינג המקצועיים (CUPTI, Nsight Systems ו-Nsight Compute), מתודולוגיה מסודרת של אופטימיזציה מקצה לקצה, ושני פרויקטים גדולים: אופטימיזציה של כפל מטריצות (GEMM) צעד אחר צעד מ-kernel נאיבי ועד לניצול Tensor Cores, ומימוש ואופטימיזציה של reduction, scan ו-softmax - האבני בניין של כל עומס עבודה מודרני.