קוד שגיאה: E2003

קטגוריה: זמן הידור: התאמה לא מוכחת של גישה לזיכרון ב-Mosaic

השגיאה הזו מתרחשת כשהקומפיילר מנתח פעולת גישה לזיכרון (כמו vector.load, vector.store, tpu.load או tpu.store) ולא יכול להוכיח באופן סטטי שהאינדקס הדינמי שמשמש למאפיין ספציפי הוא כפולה של גודל הריצוף הנדרש.

הודעות שגיאה לדוגמה:

INTERNAL: Mosaic failed to compile TPU kernel: cannot statically prove that index in dimension 1 is a multiple of 128

at location: ...

The MLIR operation involved:
  %14372 = "vector.load"(%14371, %93, %14363) : (memref<4x256xf32, #tpu.memory_space<vmem>>, index, index) -> vector<1x32xf32>

XLA Backends: TPU

סקירה כללית

כשליבת ה-Kernel טוענת או מאחסנת וקטור, כתובת הזיכרון (שמחושבת מתוך מצביע הבסיס בתוספת האינדקס הדינמי) צריכה להיות מיושרת עם גודל ה-tiling של הווקטור בחומרה. לדוגמה, אם ממדים מחולקים ל-128 רכיבים, האינדקס הדינמי שמשמש לגישה אליהם חייב להיות 0, 128, 256 וכו'. שימו לב שלפעולות רבות (כמו טעינה ואחסון של וקטורים) אין דרישות כאלה לגבי אינדקסים סטטיים.

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

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

לכן השגיאה הזו יכולה להתרחש כש

  1. משתמשים במשתנה זמן ריצה (אינדקס דינמי) כדי לגשת לזיכרון.
  2. לוגיקת החישוב של האינדקס מורכבת מדי בשביל שהקומפיילר יוכל לנתח אותה.
  3. האינדקס תקף מבחינה מתמטית, אבל אין הוכחה מפורשת בקוד.
  4. ניתוח סטטי קובע אם יש 'חוסר התאמה מוכח'.

ניפוי באגים

כדי לפתור את השגיאה, אפשר לנסות את האפשרויות הבאות:

1. הצהרה על התאמה באופן מפורש

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

2. שימוש בטעינות מיושרות ובסיבוב

בתרחישים שבהם חוסר ההתאמה הוא מכוון, במקום לטעון קטע וקטורי קטן ולא מיושר:

  • לטעון משבצת גדולה יותר שמוצמדת באופן מלא, ואז לסובב את הערכים בסכום דינמי כדי להזיז את הנתונים הרצויים למיקום (כי לא ניתן להשתמש בפרוסות וקטוריות עם אינדקסים דינמיים של התחלה). או
  • משנים את הצורה של הטנסור או מוסיפים לו ריפוד כדי שהנתונים יתחילו באינדקס 0 והצעד בין הגישות יתאים ליישור החומרה.
    • דוגמה: אם מבצעים איטרציה על מקטעים בגודל 32 החל מההיסט 1, ההיסטים הם 1, 33, 65... (לא מיושר).
    • תיקון: אריזה מחדש של הנתונים לטנסור חדש שבו המקטע הראשון הוא 0 והממד מרופד ל-128. ההיסטים שלכם יהיו 0, 128, 256..., מה שיעמוד בדרישת היישור.

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