רגע של קוד

jellymean

New member
רגע של קוד

שני מקרים שנפרדים בפקודה אחת ושאר הקוד משותף....
switch(.... )
case a: doA();
case b: doB();
case a || b : shared code....
break;
האם הייתם מעדיפים פתרון של הוצאת הקוד המשותף לפונקציה?
נ.ב
תודה לעוזרים ולעונים.
הפרס לפותרים, דו שיח עם באסמה או ויני...
 

luis13

New member
תלוי מקרה ותלוי גישה.

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

jellymean

New member
בשפת C

אפשר להחליף קריאות לפונקציות (עדיף קטנות) בקוד שלהן ע"י הגדרתן inline
 

BravoMan

Active member
רגע האכלת טרולים:

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

fellow1

New member
זה תלוי באיזו רמת אופטימיזציה מקמפלים את הקוד.

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

C היא בכלליות שפה נורא בעייתית, כדי להשתמש בה כמו שצריך חייבים לשכפל קוד: הקריאה של הinline היא במקום הלא נכון, אני רוצה שברוב הקוד שלי הפונקציה תמזער את חתימת הcache והזיכרון ולא תורץ inline ובמקומות שאני צריך תגובה מהירה שהקומפיילר יעתיק אותה inline. אין דרך לעשות זאת בלי לשכפל קוד או להשתמש בפתרון עם design מחורבן.
 

ipv6

Member
inline זאת המלצה\רמז לקומפיילר

לא מובטח לך שהקומפיילר באמת יתייחס לזה. יכול מאד שיתגנרט קוד של פונקציה רגילה (כלומר call / jmp).

האמירה שלו שקומפיילר מודרני הוא 'חכם' ויודע לייצר קוד טוב בעצמו היא ולידית. יש מעט מקרים שבהם באמת נדרשות אופטימזציות ברמה הזאת אבל בטח לא בכל פרויקט Low level.

לא הבנתי מה ניסית להגיד ב-"ני רוצה שברוב הקוד שלי הפונקציה תמזער את חתימת הcache והזיכרון ולא תורץ inline ובמקומות שאני צריך תגובה מהירה שהקומפיילר יעתיק אותה inline" אבל יש לך בתור מתכנת שליטה מסוימת על חתימת הזכרון שלך, בלי קשר לקומפיילר.
 

fellow1

New member
כשיש לך איזור קוד אסמבלי גדול יותר שעולה לRAM

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

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

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

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

BravoMan

Active member
למיטב ידיעתי שום שפה לא חזקה מספיק כדי לשלוט בקאש של המעבד

בצורה ישירה ע"י המתכנת.
רוב, אם לא כל מעבדים מודרניים עושים זאת בעצמם ולא משאירים את זה פתוח למפתחים.
(תקן אותי אם אני טועה, אלי אין לי מספיק ידע low level באסמבלי, אבל מעולם לא ראיתי פקודות ניהול קאש).
&nbsp
אם תיקח בחשבון ריבוי ליבות, וריבוי נימים, וחיזוי ענפים (brunch prediction) שעושים מעבדים מודרניים, מאוד מאוד קשה לדעת מה יעלה לקאש ומתי.
&nbsp
אגב, אני בספק רב שמישהו עושה אלגוטריידינג מהבית.
&nbsp
חברות שמרוויחות מהשיטה הזו הן בד"כ מתוקצבות טוב עד כדי כך שיכולות לבנות מגדלי מיקרוגל משלהן כדי לחסוך כמה חלקיקי שניה בתקשורת, ומרכזי הנתונים שלהן יושבות פיזית קרוב לבורסות כדי "להתעלק" על הצינור לפני כולם.
&nbsp
יצא לי קצת לקרוא על הנושא, אני לא מתיימר להיות מומחה, אבל לפי מה שלמדתי, שום שיפור שתעשה ל-IP stack של מחשב ביתי עם קו ביתי לא שינה בשימושים כמו אלגורטריידינג.
 

ipv6

Member
אפשר לתת hints לקומפיילר

למשל likely / unlikely בהקשר של branch prediction.

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

יש מה שנקרא cache friendly development כלומר להכיר איך המטמון עובד ולפתח ככה שלמעבד יהיה קל לנצל אותו בצורה מיטבית. זה יכול לתת אפקט גדול במקרים מסוימים ולמתכתנת יש שליטה גדולה על מה שקורה. הדוגמא הקלאסית היא לקחת מטריצה שהאורך\רוחב שלה גדול בהרבה מגודל ה-2/cache L1 (או סתם גדולה מספיק) ולסרוק אותה. פעם אחת לפי שורות ופעם אחת לפי עמודות ולראות איך הזמן הסריקה משתנה בין 2 השיטות כשסורקים את אותה המטריצה בדיוק.
 

fellow1

New member
לזה התכוונתי

ושוב עבדתי עכשיו כמעט חצי שנה על דרייבר של ETHERNET בקרנל של לינוקס במעגל מהמשפחה של הRaspberry Pi שתפקידו היה להזרים וידאו כמה שיותר מהר והיה שם לא מעט שימוש בlikely/unlikely ובinline כדי לענות על הצרכים של הבורד.

וכן אני מתכנת low level ויצא לי לעבוד לא מעט קרוב לחומרה עם מעבדים של ARM ומה שנקרא bare metal אבל דווקא במקרה הזה זה לא היה כך כי הקוד הורץ דווקא בשכבה יותר גבוהה בקרנל כי הDMA טיפל בעיקר בתקשורת עצמה והמעבד פשוט היה צריך לטפל בפאקטות כמה שיותר מהר.

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

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

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

ipv6

Member
כל מה שאני כתבתי

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

אלוגטריידינ זה מושג רחב וכללי. מה שאתם מדברים פה מתייחס לחברות HFT שרובן המוחלט כותבות ב-C++ 'מודעות למשאבים' עושים אופטימיזציות לרמה של 'כתיבת קוד חכם', הרב המכריע של החברות לא מגיע להעסקות עם datasheets במטרה להשפיע על ה-caching. אולי בודדים עושים את זה וגם לא ברור כמה ערך זה באמת נותן. בדיוק כמו ש99.9% לא מקים אנטנות\תחנות שידור..למרות שזה מה שתמיד מספרים לכולם.

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

2 הפרגמות שציונו בשרשור (inline and likely) הן בגדר הסטנדרטי.

https://www.youtube.com/watch?v=NH1Tta7purM
זאת הרצה מכנס, שמן הסתם מציגים בה את הדברים היותר 'מגניבים' ומעניינים. המציאות עוד יותר אפורה.
 

d70

Well-known member
במערכות שהביצועים נדרשים צריך להכיר את הנושא
במקרה יצא לי בעבר לנהל בlow level את הקאש של ארכיטקטורה מסוימת. למי שמשתמש באותו איזור זיכרון גם עם DMA וגם עם קאש, כבר עלולות להיווצר בעיות "חוסר מתאם" (Cache coherence). ללא הבנה של מתי ואיך לבצע invalidate או fulsh לקאש, אתה עלול לקבל זבל בתוצאות ולא להבין מאיפה זה מגיע. ולמי שממש מתחשק, היו אפילו מעין פקודות דיבאג שאפשרו למפתח "לחטט" במודול של הקאש כדי להבין מה קורה שם.
אספקט נוסף שעלה בשירשור בנוגע ל inline , גם אני קראתי שבד"כ מדובר בהמלצה לקומפיילר, אולם בכל הקומפיילרים (לפחות של ה low level) שעבדתי איתם, קיימות פקודות לקומפיילר(פרגמות) שמאפשרות למתכנת לעשות המון אופטימיזציות. יצא לי להשתמש בפרגמה שהורתה לקומפיילר באופן חד משמעי לטפל בפונקציה מסוימת כ inline או הפוך,כלמור להחריג פונקציה מסוימת מלהתממש inline למרות הגדרת אופטימזציה. ולמי שתוהה למה? כי היתה לי פונקציה שלאחר אופטימיזציה, חזרה והשתכפלה זיליון פעם בתוך הקוד, ומימוש ה inline שלה (אופטימיזצית מהירות) סתם לנו את כל הפלאש.
 

הפרבולה

New member
יש מעבדים שבהם הקוד יכול לרוץ גם מה ROM ( פלש)

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

BravoMan

Active member
לא מעבדים, מערכות

כל מעבד יכול להריץ קוד מכל שבב שמקבל כתובת ומחזיר נתונים, בין אם זה DRAM, SRAM, EPROM, EEPROM, NAND, NOR וכו'.
&nbsp
גם במחשב השולחני או בשרת המצוי האתחול מתחיל מ-"ROM" כלשהו, שמכיל את ה-BIOS או UEFI, ושם יושב הקוד שטוען ל-RAM את מה שצריך להמשך ריצה.
&nbsp
כמובן, במערכות משובצות ולוחות מבוססים מיקרו בקרים כל הקוד לרוב יושב על FLASH או EEPROM ולעולם לא נטען ל-RAM, אבל כשיש לך 2K RAM זה די מובן שלא תרצה לבזבז אותו על שכפול בתים של קוד.
&nbsp
היצורים המעניינים בנוף הם לרוב טלפונים, טאבלטים -ו-SBC (דוגמת raspbery pie), שאומנם עושים הפרדה פורמלית בין אזור bootloader, מערכת הפעלה, ואחסון משתמש, אבל בפועל משתמשים באחסון FLASH שטוח לחלוטין, כאשר הקביעה מה ממנו זה "ROM" היא ברמת הרשאות קבצים בלבד.
 

BravoMan

Active member
אני מניח שאם אתה כותב לרכיב bare metal שמריץ איזה ARM

עם כמה עשרות MHZ של מהירות שעון וכמה K של RAM, אתה צודק לגמרי.
&nbsp
אבל כשזה מגיע ליישומים שנועדו לרוץ על חומרת שרתים או תחנות עבודה, עם מעבדים בעלי 3 רמות קאש, הוראות מיוחדות שמזרזות תהליכים מסוימים, ביצוע לא לינארי (non sequential execution) ועוד כל מיני התחכמויות, למתכנת יישומים לרוב אין את הידע הדרוש לניצול מיטבי של החומרה, וגם לא הגיוני שיהיה לו.
&nbsp
אתה יודע למי יש?
לכותבי הקומפיילרים. הם כנראה האנשים היחידים (להוציא אולי כמה מפתחי ליבות), שטורחים לקרוא את אלפי העמודים של תיעוד המעבדים שיוצאים לשוק.
(למיטב זכרוני, תיעוד של Intel ל-P4 הוותיק הוא מעל 6000 עמודים).
&nbsp
אז עם כל הכבוד לטענה שלך, יש לי יותר ביטחון בקומפיילר כמו GCC או LLVM, מאשר ביכולת שלי, ושל רוב מפתחי אפליקציות לבצע אופטימיזציות ברמה של קריאה מול שכפול קוד.
&nbsp
אגב, לפני שנים כשלמדתי אסמבלי ניסיתי לראות אם יש לי דרך לממש העתקת מערך יותר מהר באסמבלי ממה שהקומפיילר של C יעשה ברמת אופטימיזציה מהירות גבוהה ביותר.
&nbsp
גיליתי, שגם תוך שימוש בפקודות מכונה מיוחדות להעתקה מהירה של טווחי זיכרון, לא כ"כ קל להרוויח.
&nbsp
נזכיר אגב, שאופטימיזציות מהירות ואופטימיזציות זיכרון לא פעם מתנגשות אחת עם השנייה, והמפתח תמיד צריך להתפשר כדי למצוא את הפתרון המיטבי לסיטואציה.
 

luis13

New member
זה אפשרי בהרבה שפות אבל זו לא הנקודה.

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