מה חדש ב-WebGPU (Chrome123)

François Beaufort
François Beaufort

ב-WGSL יש תמיכה בפונקציות מובנות של DP4a

DP4a (המכפלה של 4 אלמנטים וצבירה) מתייחס לקבוצה של הוראות ל-GPU שמשמשים להסקת למידה עמוקה (Deep Learning) לצורך קוונטיזציה. הוא מבצע ביעילות מוצרי נקודות עם מספרים שלמים של 8 ביט כדי להאיץ את החישוב של מודלים מסוג int8. היא יכולה לחסוך (עד 75%) מרוחב הפס של הזיכרון והרשת ולשפר את הביצועים של כל מודל למידת מכונה בהסקה, בהשוואה לגרסת f32 שלהם. לכן נעשה בו שימוש נרחב במסגרות פופולריות רבות של AI.

כשתוסף השפה "packed_4x8_integer_dot_product" של WGSL מופיע ב-navigator.gpu.wgslLanguageFeatures, עכשיו אפשר להשתמש בסקלרים שלמים של 32 ביט שאורזים וקטורים של מספרים שלמים ב-8 ביט כקלט להוראות המוצר המנוקדות בקוד של תוכנת ההצללה (shader) של WGSL באמצעות הפונקציות המובנות dot4U8Packed ו-dot4I8Packed. אפשר גם להשתמש בהוראות האריזה והפריסה, עם וקטורים של 4 רכיבים דחוסים של מספרים שלמים של 8 ביט עם פונקציות מובנות של pack4xI8, pack4xU8, pack4xI8Clamp, pack4xU8Clamp, unpack4xI8 ו-unpack4xU8 WGSL.

מומלץ להשתמש בערך requires-directives כדי לציין את הפוטנציאל לאי-ניידות באמצעות requires packed_4x8_integer_dot_product; בחלק העליון של הקוד של תוכנת ההצללה (shader) של WGSL. בדוגמה הבאה אפשר לראות את גוון הבעיה:1497.

if (!navigator.gpu.wgslLanguageFeatures.has("packed_4x8_integer_dot_product")) {
  throw new Error(`DP4a built-in functions are not available`);
}

const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();

const shaderModule = device.createShaderModule({ code: `
  requires packed_4x8_integer_dot_product;

  fn main() {
    const result: u32 = dot4U8Packed(0x01020304u, 0x02040405u); // 42
  }`,
});

תודה מיוחדת לצוות הגרפיקה באינטרנט של Intel בשנחאי על שהניע את המפרט והיישום עד הסוף!

פרמטרים של מצביע ללא הגבלה ב-WGSL

תוסף השפה של WGSL "unrestricted_pointer_parameters" מצמצם את ההגבלות לגבי העברת מצביעים לפונקציות WGSL:

  • נקודות הציון של הפרמטרים storage, uniform ו-workgroup מרחבי כתובות המפנות לפונקציות שהוצהרו על ידי המשתמש.

  • העברת מצביעים למבנה של חברים ורכיבי מערכים בפונקציות שהוצהרו על ידי המשתמש.

מידע נוסף זמין במאמר מצביעים כפרמטרים של פונקציות | סיור ב-WGSL.

אפשר לזהות את התכונה הזו באמצעות navigator.gpu.wgslLanguageFeatures. מומלץ תמיד להשתמש בתג requires-directive כדי לציין את הפוטנציאל לאי-ניידות באמצעות requires unrestricted_pointer_parameters; בחלק העליון של קוד ההצללה של WGSL. עיין בדוגמה הבאה, שינויים במפרט WGSL וגוון הבעיה:2053.

if (!navigator.gpu.wgslLanguageFeatures.has("unrestricted_pointer_parameters")) {
  throw new Error(`Unrestricted pointer parameters are not available`);
}

const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();

const shaderModule = device.createShaderModule({ code: `
  requires unrestricted_pointer_parameters;

  @group(0) @binding(0) var<storage, read_write> S : i32;

  fn func(pointer : ptr<storage, i32, read_write>) {
    *pointer = 42;
  }

  @compute @workgroup_size(1)
  fn main() {
    func(&S);
  }`
});

תחביר סוכר להפחתת אזכור של רכיבים ב-WGSL

כשתוסף השפה של WGSL "pointer_composite_access" נמצא ב-navigator.gpu.wgslLanguageFeatures, קוד ההצללה של WGSL תומך עכשיו בגישה לרכיבים של סוגי נתונים מורכבים שמתבססים על אותה תחביר של נקודה (.), גם כשעובדים ישירות עם הנתונים וגם עם מצביעים אליהם. ככה זה עובד:

  • אם foo הוא מצביע: קל יותר לכתוב (*foo).bar באמצעות foo.bar. בדרך כלל משתמשים בכוכבית (*) כדי להפוך את הסמן ל "הפניה" שאפשר להתעלם ממנה, אבל עכשיו גם המצביעים וגם ההפניות דומים מאוד וכמעט ניתנים להחלפה.

  • אם foo הוא לא מצביע: אופרטור הנקודה (.) פועל בדיוק כמו שהיית רגיל לגישה ישירה לחברים.

באופן דומה, אם pa הוא מצביע ששומר את כתובת ההתחלה של מערך, אז השימוש ב-pa[i] נותן גישה ישירה למיקום הזיכרון שבו מאוחסן הרכיב 'i' של המערך הזה.

מומלץ להשתמש בערך requires-directives כדי לציין את הפוטנציאל לאי-ניידות באמצעות requires pointer_composite_access; בחלק העליון של הקוד של תוכנת ההצללה (shader) של WGSL. עיין בדוגמה הבאה וגוון הבעיה:2113.

if (!navigator.gpu.wgslLanguageFeatures.has("pointer_composite_access")) {
  throw new Error(`Pointer composite access is not available`);
}

const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();

const shaderModule = device.createShaderModule({ code: `
  requires pointer_composite_access;

  fn main() {
    var a = vec3f();
    let p : ptr<function, vec3f> = &a;
    let r1 = (*p).x; // always valid.
    let r2 = p.x; // requires pointer composite access.
  }`
});

מצב קריאה בלבד נפרד להיבטים של שבלונה ועומק

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

עדכונים בשעות השחר

הקריאה החוזרת (callback) על השגיאה שלא תועדה שהוגדרה עם wgpuDeviceSetUncapturedErrorCallback() מופעלת עכשיו מיד כשהשגיאה מתרחשת. זה מה שהמפתחים מצפים לו ורוצים בניפוי באגים באופן עקבי. למידע נוסף, אפשר לעיין במאמר שינוי שחר:173620.

השיטה wgpuSurfaceGetPreferredFormat() מ-webgpu.h API הוטמעה. לעיון בעלות השחר:1362.

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

מה חדש ב-WebGPU

רשימה של כל מה שמכוסה בסדרה מה חדש ב-WebGPU.

Chrome 125

Chrome 124

Chrome 123

גרסה 122 של Chrome

גרסה 121 של Chrome

Chrome 120

גרסה 119 של Chrome

גרסה 118 של Chrome

גרסה 117 של Chrome

גרסה 116 של Chrome

Chrome 115

Chrome 114

גרסה 113 של Chrome