כיצד להאיץ את הקוד באמצעות מטמונים במעבד

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

איך מטמני מעבד עובדים

למעבדים מודרניים יש בדרך כלל שלוש רמות של מטמון, שכותרתו L1, L2 ו- L3, המשקף את הסדר בו המעבד בודק אותם. למעבדים יש לעיתים קרובות מטמון נתונים, מטמון הוראות (לקוד) ומטמון מאוחד (לכל דבר). הגישה למטמון זה מהירה בהרבה מגישה ל- RAM: בדרך כלל מטמון L1 מהיר פי 100 מה- RAM לגישה לנתונים, ומטמון L2 מהיר פי 25 מזיכרון RAM לגישה לנתונים.

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

הקוד שלך לא יכול לציין היכן נמצאים נתונים ונתונים - חומרת המחשב עושה זאת - כך שלא תוכל להכריח אלמנטים מסוימים למטמון המעבד. אבל אתה יכול לייעל את הקוד שלך כדי לאחזר את גודל המטמון L1, L2 או L3 במערכת שלך באמצעות Windows Management Instrumentation (WMI) כדי לייעל כאשר היישום שלך ניגש למטמון ובכך לביצועים שלו.

מעבדים לעולם אינם ניגשים לבסיס מטמון בתים. במקום זאת, הם קוראים את הזיכרון בשורות מטמון, שהם נתחי זיכרון בגודל 32, 64 או 128 בתים.

רישום הקוד הבא ממחיש כיצד ניתן לאחזר את גודל המטמון של מעבד L2 או L3 במערכת שלך:

uint static public GetCPUCacheSize (cacheType string) {נסה {באמצעות (ManagementObject managementObject = new ManagementObject ("Win32_Processor.DeviceID = 'CPU0'")) {return (uint) (managementObject [cacheType]); }} לתפוס {להחזיר 0; }} ריק ריק סטטי (מחרוזת [] טענות) {uint L2CacheSize = GetCPUCacheSize ("L2CacheSize"); uint L3CacheSize = GetCPUCacheSize ("L3CacheSize"); Console.WriteLine ("L2CacheSize:" + L2CacheSize.ToString ()); Console.WriteLine ("L3CacheSize:" + L3CacheSize.ToString ()); Console.Read (); }

למיקרוסופט יש תיעוד נוסף על מחלקת ה- WMI של Win32_Processor.

תכנות לביצוע: קוד לדוגמא

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

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

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

קטע הקוד הבא מיישם תוכנית פשוטה המדגימה את היתרונות של שימוש ב- struct על פני כיתה:

 struct RectangleStruct {רוחב אינטל ציבורי; גובה אינטימי ציבורי; } class RectangleClass {public int breedth; גובה אינטימי ציבורי; }

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

ריק סטטי Main (string [] args) {const int size = 1000000; var structs = RectangleStruct חדש [גודל]; מחלקות var = RectangleClass חדש [גודל]; var sw = שעון עצר חדש (); sw.Start (); עבור (var i = 0; i <size; ++ i) {structs [i] = RectangleStruct new (); סטרוקטות [i]. רוחב = 0 סטרוקטות [i]. גובה = 0; } var structTime = sw.ElapsedMilliseconds; sw.Reset (); sw.Start (); עבור (var i = 0; i <size; ++ i) {מחלקות [i] = RectangleClass חדש (); שיעורים [i]. רוחב = 0; כיתות [i] .height = 0; } var classTime = sw.ElapsedMilliseconds; sw.Stop (); Console.WriteLine ("הזמן שנדרש לפי מערך המחלקות:" + classTime.ToString () + "אלפיות השנייה."); Console.WriteLine ("הזמן שנדרש לפי מערך סטרוקטורות:" + structTime.ToString () + "אלפיות השנייה."); Console.Read (); }

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

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

כללי אצבע לשימוש טוב יותר במטמון המעבד

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

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