WebGPU: ביטול הנעילה של גישת GPU מודרנית בדפדפן

איך WebGPU מאפשרת לכם לנצל את מלוא העוצמה של ה-GPU כדי לשפר את הביצועים של למידת המכונה ואת רינדור הגרפיקה?

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

הקשר ב-WebGPU

WebGL הגיע ל-Chrome בשנת 2011. WebGL מאפשר לאפליקציות אינטרנט לנצל את היתרונות של מעבדי GPU, וכך מאפשר חוויות מדהימות באינטרנט – החל מ-Google Earth ועד לסרטוני מוזיקה אינטראקטיביים, סיורים וירטואליים בנכסי נדל"ן בתלת-ממד ועוד. WebGL מבוסס על משפחת ממשקי ה-API של OpenGL, שפותחה לראשונה בשנת 1992. זה היה לפני הרבה זמן! אפשר רק לדמיין כמה התפתחה חומרת ה-GPU מאז.

כדי לעמוד בקצב ההתפתחות הזה, פיתחנו סוג חדש של ממשקי API כדי ליצור אינטראקציה יעילה יותר עם חומרת GPU מודרנית. ממשקי API כמו Direct3D 12,‏ Metal ו-Vulkan. ממשקי ה-API החדשים האלה תמכו בתרחישי שימוש חדשים ומאתגרים לתכנות ב-GPU, כמו ההתפתחות המהירה של למידת המכונה והפיתוחים באלגוריתמים של עיבוד תמונה. WebGPU הוא יורשו של WebGL, והוא מביא לאינטרנט את השיפורים של הסוג החדש הזה של ממשקי API מודרניים.

WebGPU מאפשר הרבה אפשרויות חדשות לתכנות GPU בדפדפן. הוא משקף טוב יותר את אופן הפעולה של חומרת GPU מודרנית, וגם מאפשר להניח יסודות ליכולות מתקדמות יותר של GPU בעתיד. ממשק ה-API נמצא בפיתוח בקבוצה GPU for the Web של W3C מאז 2017, והוא תוצר של שיתוף פעולה בין חברות רבות כמו Apple,‏ Google,‏ Mozilla,‏ Microsoft ו-Intel. עכשיו, אחרי 6 שנים של עבודה, אנחנו שמחים להכריז שאחד מהתוספים הגדולים ביותר לפלטפורמת האינטרנט זמין סוף סוף!

WebGPU זמין עכשיו ב-Chrome 113 ב-ChromeOS, ב-macOS וב-Windows, ובקרוב יהיה זמין בפלטפורמות נוספות. תודה רבה לתורמים אחרים של Chromium ול-Intel במיוחד, שעזרו לנו להשיג את זה.

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

מקבלים גישה לעומסי עבודה חדשים של GPU לעיבוד

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

בסרטון הבא מוצג האלגוריתם marching cubes שמשמש ליצירת משולשויות על פני השטח של המטא-כדורים האלה. ב-20 השניות הראשונות של הסרטון, כשהאלגוריתם פועל ב-JavaScript, הוא מתקשה לעמוד בקצב של הדף שפועל רק במהירות של 8 פריימים לשנייה, וכתוצאה מכך התנועה באנימציה קטועה. כדי לשמור על הביצועים ב-JavaScript, נצטרך להפחית משמעותית את רמת הפרטים.

ההבדל בין שתי השיטות הוא עצום כשאנחנו מעבירים את אותו אלגוריתם ל-compute shader, כפי שרואים בסרטון אחרי 20 שניות. הביצועים השתפרו באופן משמעותי, והדף פועל עכשיו במהירות חלקה של 60FPS, ועדיין יש הרבה מקום לביצועים טובים יותר עם אפקטים אחרים. בנוסף, הלולאה הראשית של JavaScript בדף תהיה פנויה לחלוטין למשימות אחרות, וכך תבטיח שהאינטראקציות עם הדף יהיו תגובה מהירה.

הדגמה של metaballs

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

הדגמה של האוקיינוס

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

הסקת מסקנות מהירה יותר בלמידת מכונה

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

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

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

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

עיבוד שגיאות (compute shaders) הוא התכונה החדשה העיקרית של WebGPU, והוא מסיר את נקודות החולשה האלה. פונקציות Compute Shaders מציעות מודל תכנות גמיש יותר שמנצל את המבנה המקביל האדיר של המעבדים הגרפיים, בלי להיות מוגבל על ידי המבנה המחמיר של פעולות הרינדור.

השיפורים השונים ביעילות של שגיאות מחשוב ב-WebGPU, כולל עומסי זיכרון משותפים, חישובים משותפים וכתיבה גמישה בזיכרון.
יעילות של WebGPU compute shader.

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

דוגמה לשיפור היעילות שאפשר להשיג: יצירת גרסת פורט ראשונית של מודל של דיפוזיה של תמונה ב-TensorFlow.js מראה שיפור של פי 3 בביצועים במגוון חומרות כשעוברים מ-WebGL ל-WebGPU. בחלק מחומרת הבדיקה, התמונה עברה רינדור תוך פחות מ-10 שניות. וכיוון שזו הייתה גרסה מוקדמת, אנחנו מאמינים שאפשר לבצע עוד שיפורים ב-WebGPU וב-TensorFlow.js. מה חדש ב-Web ML בשנת 2023? סשן ב-Google I/O.

אבל WebGPU לא רק מאפשר להשתמש בתכונות של GPU באינטרנט.

תוכנן בראש ובראשונה ל-JavaScript

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

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

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

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

גילינו גם שלעיתים קרובות, העלות הנוספת של ביצוע יותר מדי קריאות ל-JavaScript היא צוואר בקבוק באפליקציות WebGL מורכבות. כתוצאה מכך, ה-API של WebGPU פחות מדבר, כך שתוכלו להשיג יותר עם פחות קריאות לפונקציות. אנחנו מתמקדים בבדיקות אימות כבדות מראש, כדי שהלולאה הקריטית של תהליך ההצגה תהיה יעילה ככל האפשר. בנוסף, אנחנו מציעים ממשקי API חדשים כמו Render Bundles, שמאפשרים להקליט מראש כמויות גדולות של פקודות ציור ולנגן אותן מחדש בקריאה אחת.

כדי להמחיש את ההבדל המשמעותי שאפשר להשיג באמצעות תכונה כמו חבילות רינדור, הנה דוגמה נוספת מ-Babylon.js. המרת ה-WebGL 2 יכולה לבצע את כל הקריאות ל-JavaScript כדי להציג את הסצנה של גלריית האמנות כ-500 פעמים בשנייה. זה נתון די טוב!

גלריית האמנות

עם זאת, ה-renderer של WebGPU מאפשר תכונה שנקראת 'רינדור של קובץ snapshot'. התכונה הזו מבוססת על חבילות רינדור של WebGPUs, ומאפשרת לשלוח את אותה סצנה במהירות גבוהה פי 10. הפחתת העלויות הנלוות באופן משמעותי מאפשרת ל-WebGPU ליצור עיבוד תמונה של סצנות מורכבות יותר, וגם מאפשרת לאפליקציות לבצע יותר פעולות ב-JavaScript במקביל.

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

לכך יש השפעה חיובית: קל ללמוד את WebGPU ולהשתמש בו. התג מסתמך על תכונות קיימות בפלטפורמת האינטרנט לפעולות כמו טעינה של תמונות וסרטונים, ומשתמש בתבניות JavaScript מוכרות כמו Promises לפעולות אסינכרוניות. כך אפשר לצמצם את כמות הקוד הסטנדרטי שנדרש. אפשר להציג את המשולש הראשון במסך בפחות מ-50 שורות קוד.

<canvas id="canvas" width="512" height="512"></canvas>
<script type="module">
  const adapter = await navigator.gpu.requestAdapter();
  const device = await adapter.requestDevice();

  const context = canvas.getContext("webgpu");
  const format = navigator.gpu.getPreferredCanvasFormat();
  context.configure({ device, format });

  const code = `
    @vertex fn vertexMain(@builtin(vertex_index) i : u32) ->
      @builtin(position) vec4f {
       const pos = array(vec2f(0, 1), vec2f(-1, -1), vec2f(1, -1));
       return vec4f(pos[i], 0, 1);
    }
    @fragment fn fragmentMain() -> @location(0) vec4f {
      return vec4f(1, 0, 0, 1);
    }`;
  const shaderModule = device.createShaderModule({ code });
  const pipeline = device.createRenderPipeline({
    layout: "auto",
    vertex: {
      module: shaderModule,
      entryPoint: "vertexMain",
    },
    fragment: {
      module: shaderModule,
      entryPoint: "fragmentMain",
      targets: [{ format }],
    },
  });
  const commandEncoder = device.createCommandEncoder();
  const colorAttachments = [
    {
      view: context.getCurrentTexture().createView(),
      loadOp: "clear",
      storeOp: "store",
    },
  ];
  const passEncoder = commandEncoder.beginRenderPass({ colorAttachments });
  passEncoder.setPipeline(pipeline);
  passEncoder.draw(3);
  passEncoder.end();
  device.queue.submit([commandEncoder.finish()]);
</script>

סיכום

אנחנו שמחים לראות את כל האפשרויות החדשות ש-WebGPU מביא לפלטפורמת האינטרנט, ונשמח לראות את כל תרחישי השימוש החדשים והמעניינים שתמצאו ל-WebGPU!

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

Babylon.js,‏ Construct 3,‏ Google Earth,‏ Google Meet,‏ PlayCanvas,‏ Sketchfab,‏ Three.JS,‏ TensorFlow.js ו-Unity.
מסגרות, אפליקציות וספריות עם יציאות WebGPU שהושלמו או שנמצאות בתהליך.

הגרסה הראשונה ב-Chrome 113 היא רק ההתחלה. הגרסה הראשונית שלנו מיועדת ל-Windows, ל-ChromeOS ול-macOS, אבל אנחנו מתכננים להוסיף את WebGPU לפלטפורמות הנותרות, כמו Android ו-Linux, בעתיד הקרוב.

וגם לא רק צוות Chrome עבד על השקת WebGPU. אנחנו גם עובדים על הטמעות ב-Firefox וב-WebKit.

בנוסף, כבר מתכננים ב-W3C תכונות חדשות שאפשר לחשוף כשהן יהיו זמינות בחומרה. לדוגמה: בקרוב אנחנו מתכננים להפעיל ב-Chrome תמיכה במספרים של 16 ביט עם נקודה צפה בשכבות הגדרת התאורה (shaders) ואת סוג ההוראות DP4a, כדי לשפר עוד יותר את הביצועים של למידת המכונה.

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

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