אופטימיזציה של תוכניות

36
תתתתתתתתתתת תת תתתתתתת תתתתתתת תתתתת תתת: תתתתתתת תתתתת תתת: תתתתת- תתתתתתתתתתתת תת תתתתתת תתתת תתת תתתתת תתתתתתתתת 'תתתתת' תתתתת תתת תתתתתתת תתתתתתת תתתתתת תתתתתprofiling : תתתתת תתתתתת תתתתת תתתתת תתתת ללללל ללBryant & O’hallaron / Computer Systems: a programmer’s perspective

Upload: annona

Post on 27-Jan-2016

58 views

Category:

Documents


5 download

DESCRIPTION

אופטימיזציה של תוכניות. הנושאים במצגת זאת: אופטימיזציות לא תלויות-מכונה הזזת קוד החלפת אופרטורים 'יקרים' צירוף תתי ביטויים משותפים כוונון בעזרת profiling : זיהוי צווארי בקבוק בזמני ריצה. מבוסס על Bryant & O’hallaron / Computer Systems: a programmer’s perspective. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: אופטימיזציה של תוכניות

אופטימיזציה של תוכניות אופטימיזציה של תוכניות

הנושאים במצגת זאת:הנושאים במצגת זאת:אופטימיזציות לא תלויות-מכונה

הזזת קוד'החלפת אופרטורים 'יקריםצירוף תתי ביטויים משותפים

כוונון בעזרתprofiling:זיהוי צווארי בקבוק בזמני ריצה

Bryant & O’hallaron / Computer Systems: a programmer’s perspectiveמבוסס על

Page 2: אופטימיזציה של תוכניות

– 2 –

סיבוכיות: תיאוריה אל מול מציאות

סיבוכיות: תיאוריה אל מול מציאות

בדר"כ אנחנו מודדים סיבוכיות אסימפטוטית של אלגוריתמים.בדר"כ אנחנו מודדים סיבוכיות אסימפטוטית של אלגוריתמים.

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

! !ניתן לשפר בקבוע – גם זה חשובניתן לשפר בקבוע – גם זה חשוב

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

ולולאות.

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

Page 3: אופטימיזציה של תוכניות

– 3 –

סוגי אופטימיזציותסוגי אופטימיזציות

שתי משפחות של אופטימיזציות:שתי משפחות של אופטימיזציות:

)אופטימיזציות לא תלויות מכונה )הרצאה זאת(אופטימיזציות לא תלויות מכונה )הרצאה זאת

)אופטימיזציות תלויות מכונה )שעור הבא(אופטימיזציות תלויות מכונה )שעור הבאהאפקטיביות מאוד תלויה במבנה הספציפי של המעבד

Page 4: אופטימיזציה של תוכניות

– 4 –

מהדרים הם מתרגמים מרובי אופטימיזציות

מהדרים הם מתרגמים מרובי אופטימיזציות

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

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

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

חשש מmemory aliasing( "חשש מ "תופעות לוואיside-effects.של פרוצדורות )

Page 5: אופטימיזציה של תוכניות

– 5 –

מגבלות של מהדריםמגבלות של מהדריםנדרשים לעמוד במגבלות חמורות:נדרשים לעמוד במגבלות חמורות:

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

במקרים שלעולם לא קורים בפועל.

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

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

Page 6: אופטימיזציה של תוכניות

– 6 –

מגבלות של מהדריםמגבלות של מהדריםרוב הניתוח המבוצע על ידי המהדר נעשה בתוך הפרוצדורות רוב הניתוח המבוצע על ידי המהדר נעשה בתוך הפרוצדורות

ולא ביניהן.ולא ביניהן..ניתוח של כלל התוכנית הוא לא מעשי בגלל אילוצי זמן

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

חייב להיות שמרני!חייב להיות שמרני!

Page 7: אופטימיזציה של תוכניות

– 7 –

אופטימיזציות שאינן תלויות מכונהאופטימיזציות שאינן תלויות מכונה((code motioncode motion))הזזת קוד הזזת קוד

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

for (i = 0; i < n; i++) for (j = 0; j < n; j++) a[n*i + j] = b[j];

for (i = 0; i < n; i++) { int ni = n*i; for (j = 0; j < n; j++) a[ni + j] = b[j];}

Page 8: אופטימיזציה של תוכניות

– 8 –

הזזת קוד על ידי המהדרהזזת קוד על ידי המהדר בדר"כ מהדרים עושים עבודה טובה בטיפול במערכים ולולאות

פשוטות.

Code Generated by gccCode Generated by gccfor (i = 0; i < n; i++) for (j = 0; j < n; j++) a[n*i + j] = b[j];

multiply R1,R2 # i*n move 8(R3),R4 # a leal (R4,R2,4),R5 # p = a+i*n (scaled by 4)

# Inner Loop.L40: move 12(R3),R4 # b move (R4,R6,4),R2 # b+j (scaled by 4) move R2,(R5) # *p = b[j] add $4,R5 # p++ (scaled by 4) increment R6 # j++ compare R2 R6 jl .L40 # loop if j<n

for (i = 0; i < n; i++) { int ni = n*i; int *p = a+ni; for (j = 0; j < n; j++) *p++ = b[j];}

Page 9: אופטימיזציה של תוכניות

– 9 –

void lower(char *s){ int i; for (i = 0; i < strlen(s); i++) if (s[i] >= 'A' && s[i] <= 'Z') s[i] -= ('A' - 'a');}

Code Motionדוגמה נוספת ל Code Motionדוגמה נוספת ל Procedure to Convert String to Lower CaseProcedure to Convert String to Lower Case

את המקרה הזה, כפי שנראה, המהדר לא יצליח לפתור.את המקרה הזה, כפי שנראה, המהדר לא יצליח לפתור.

האחריות – על המתכנת...האחריות – על המתכנת...

Page 10: אופטימיזציה של תוכניות

– 10 –

Lower Case Conversion ביצועים של Lower Case Conversionביצועים של

.זמן ריבועי באורך המחרוזת

lower1

0.0001

0.001

0.01

0.1

1

10

100

1000

256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144

String Length

CP

U S

eco

nd

s

Page 11: אופטימיזציה של תוכניות

– 11 –

...gotoנתרגם לתוכנית ...gotoנתרגם לתוכנית

strlenמבוצע בכל איטרציה strlen 0'\ליניארי באורך המחרוזת: מחפש את'זמן ריבועי

void lower(char *s){ int i = 0; if (i >= strlen(s)) goto done; loop: if (s[i] >= 'A' && s[i] <= 'Z') s[i] -= ('A' - 'a'); i++; if (i < strlen(s)) goto loop; done:}

Page 12: אופטימיזציה של תוכניות

– 12 –

שיפור הביצועיםשיפור הביצועים

הוצא קריאה לstrlenמחוץ ללולאה .שהרי התוצאה אינה משתנה בין האיטרציות סוג שלcode motion

void lower(char *s){ int i; int len = strlen(s); for (i = 0; i < len; i++) if (s[i] >= 'A' && s[i] <= 'Z') s[i] -= ('A' - 'a');}

Page 13: אופטימיזציה של תוכניות

– 13 –

זמני ריצהזמני ריצה

זמן ריצה ריבועי לעומת ליניארי

0.000001

0.00001

0.0001

0.001

0.01

0.1

1

10

100

1000

256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144

String Length

CP

U S

eco

nd

s

lower1 lower2

Page 14: אופטימיזציה של תוכניות

– 14 –

החלפת אופרטורים 'יקרים'החלפת אופרטורים 'יקרים'

Shift, add instead of multiply or divide16*x --> x << 4

ההשפעה תלויות מכונה: בכמה עולה כפל וחילוק בפנטיוםII 4 כפל של מספר שלם צורך רק CPU cycles – חילוק .

הרבה יותר.

:זהה סדרה של הכפלות

for (i = 0; i < n; i++) for (j = 0; j < n; j++) a[n*i + j] = b[j];

int ni = 0;for (i = 0; i < n; i++) { for (j = 0; j < n; j++) a[ni + j] = b[j]; ni += n;}

קודם השתמשנו בכפל

(ni = n *i)

Page 15: אופטימיזציה של תוכניות

– 15 –

שימוש ברגיסטריםשימוש ברגיסטרים

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

נותן קדימות למשתנים זמניים נותן קדימות למשתנים המוגדרים על ידי המשתמש בעזרת המילה

register

Page 16: אופטימיזציה של תוכניות

– 16 –

בדר"כ מהדרים לא מנצלים ידע אריתמטי. בדר"כ מהדרים לא מנצלים ידע אריתמטי.

/* Sum neighbors of i,j */up = val[(i-1)*n + j];down = val[(i+1)*n + j];left = val[i*n + j-1];right = val[i*n + j+1];sum = up + down + left + right;

int inj = i*n + j;up = val[inj - n];down = val[inj + n];left = val[inj - 1];right = val[inj + 1];sum = up + down + left + right;

3 multiplications: i*n, )i–1(*n, )i+1(*n 1 multiplication: i*n

צרוף ביטויים משותפיםצרוף ביטויים משותפים

leal -1(R1),R2 # i-1 multiply R4,R2 # (i-1)*n leal 1(R1),R3 # i+1 multiply R4,R3 # (i+1)*n multiply R4,R1 # i*n

Page 17: אופטימיזציה של תוכניות

– 17 –

כלים חשובים:כלים חשובים:

מדידה:מדידה:חשב זמן ריצה הנצרך על ידי קטעי קוד מסויימים

לרב המעבדים יש מוני שעון ...לא קל להוציא מהם מידע שימושי

השימוש בprofiler :'מספר הקריאות לכל פונקציה, וכו

gcc –O2 –pg prog. –o prog

./progExecutes in normal fashion, but also generates file gmon.out

gprof progGenerates profile information based on gmon.out

visual studio 6.0: Project/settings/link: enable profiling

דר ה- -Build profile

Page 18: אופטימיזציה של תוכניות

– 18 –

profilingדוגמה ל profilingדוגמה ל המטרההמטרה

חשב תדירות של מלים במסמך טקסטהצג רשימה ממוינת מהמילה התדירה ביותר לנדירה ביותר

צעדים:צעדים: הפוך לlowercase( ּבּוב Vהפעל פונקציית גhash function .)

נתחיל עם סכום ערכיASCII.של המחרוזת

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

מיין תוצאות נפעיל אלגוריתם בשםinsertion-sort אלגוריתם זה יוצר רשימה( .

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

Page 19: אופטימיזציה של תוכניות

– 19 –

profilingדוגמה ל profilingדוגמה ל הקלט:הקלט:

Collected works of Shakespeare946,596 total words, 26,596 unique :שניות 9.2מימוש ראשוני

29,80129,801 thethe

27,52927,529 andand

21,02921,029 II

20,95720,957 toto

18,51418,514 ofof

15,37015,370 aa

14,01014,010 youyou

12,93612,936 mymy

11,72211,722 inin

11,51911,519 thatthat

Shakespeare’s

most frequent words

Page 20: אופטימיזציה של תוכניות

– 20 –

Profilingועכשיו :Profilingועכשיו: פונקציות למדידת זמן פונקציות למדידת זמןexecutableexecutableהוסף ל הוסף ל

.מחשב בקירוב זמן בתוך כל פונקציהשיטת החישוב

לערך( 10כל זמן מה msשולח פסיקה )קובע איזו פונקציה כרגע מבוצעת 10מעדכן את מונה הזמן בms

גם מעדכן מונה של מספר הקריאות לפונקציה

Page 21: אופטימיזציה של תוכניות

– 21 –

Profilingתוצאות ה- Profilingתוצאות ה-

סטטיסטיקת קריאותסטטיסטיקת קריאותמספר קריאות וסה"כ זמן בכל פונקציה

הבעיה בביצועים:הבעיה בביצועים::אלג' לא יעיל. המיון לוקח זמן רב מדי מזמן הריצה. 87%קריאה בודדת לוקחת

% cumulative self self total time seconds seconds calls ms/call ms/call name 86.60 8.21 8.21 1 8210.00 8210.00 sort_words 5.80 8.76 0.55 946596 0.00 0.00 lower1 4.75 9.21 0.45 946596 0.00 0.00 find_ele_rec 1.27 9.33 0.12 946596 0.00 0.00 h_add

Page 22: אופטימיזציה של תוכניות

– 22 –

אופטימיזציותאופטימיזציות

צעד ראשון: החלף פרוצדורת מיון נשתמש בפונקציית הספרייהqsort

0

1

2

3

4

5

6

7

8

9

10

Initial Quicksort Iter First Iter Last Big Table Better Hash Linear Lower

CP

U S

ec

s. Rest

Hash

Lower

List

Sort

Page 23: אופטימיזציה של תוכניות

– 23 –

אופטימיזציות נוספותאופטימיזציות נוספות

Iter first במקום פונקציה רקורסיבית – לולאה. מוסיף איבר חדש :לראש הרשימה.

מאט את הקוד

Iter last.כנ"ל, אבל הוסף איבר חדש לסוף הרשימה : .מלים נפוצות יותר יהיו קרוב לתחילת הרשימה

Big tableטבלת גיבוב גדולה יותר :Better hashפונקצית גיבוב טובה יותר :Linear lower הוצאת :strlen מהלולאה

0

0.2

0.4

0.6

0.8

1

1.2

1.4

1.6

1.8

2

Initial Quicksort Iter First Iter Last Big Table Better Hash Linear Lower

CP

U S

ec

s. Rest

Hash

Lower

List

Sort

Page 24: אופטימיזציה של תוכניות

– 24 –

Profilingמספר מלים על Profilingמספר מלים על

יתרונותיתרונותעוזר לזהות צווארי בקבוק בביצועים .שימושי בעיקר כשמדובר במערכת מורכבת עם רכיבים רבים

מגבלותמגבלותתלוי קלט למשל, הטכניקה שלlinear lower לא הראה את כוחו בגלל שרב

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

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

Page 25: אופטימיזציה של תוכניות

– 25 –

מדדי זמןמדדי זמן

זמן אבסולוטיזמן אבסולוטי :9–10בדר"כ ננו-שניות secסדר גודל מציאותי

Clock CyclesClock Cyclesטווח טיפוסי

100 MHz »108 cycles per second

»Clock period = 10ns2 GHz

»2 X 109 cycles per second

»Clock period = 0.5ns

Page 26: אופטימיזציה של תוכניות

– 26 –

Cycles Per Element )CPE(Cycles Per Element )CPE(דרך נוחה למדידת ביצועים במקרה של וקטור / רשימת נתונים

Length = n T = CPE*n + Overhead

0

100

200

300

400

500

600

700

800

900

1000

0 50 100 150 200

Elements

Cyc

les

vsum1Slope = 4.0

vsum2Slope = 3.5

vsum1, vsum2 שתי תוכניות עם הפרש ליניארי בביצועים.

Page 27: אופטימיזציה של תוכניות

– 27 –

חיבור איברי דוגמה:וקטור

חיבור איברי דוגמה:וקטור

ProceduresProceduresvec_ptr new_vec(int len)

Create vector of specified length

int get_vec_element(vec_ptr v, int index, int *dest)Retrieve vector element, store at *destReturn 0 if out of bounds, 1 if successful

int *get_vec_start(vec_ptr v)Return pointer to start of vector data

Similar to array implementations in Pascal, ML, JavaE.g., always do bounds checking

lengthdata

0 1 2 length–1

Page 28: אופטימיזציה של תוכניות

– 28 –

המשך דוגמההמשך דוגמה

מטרהמטרהחשב סכום איברי הוקטור שמור תוצאה בdest.

Pentium III Performance: Clock Cycles / ElementPentium III Performance: Clock Cycles / Element 42.06 )Compiled -g( 31.25 )Compiled -O2(

(-g: debug information, -O2 : 2 אופטימיזציות ברמה)

void combine1(vec_ptr v, int *dest){ int i; *dest = 0; for (i = 0; i < vec_length(v); i++) { int val; get_vec_element(v, i, &val); *dest += val; }}

Page 29: אופטימיזציה של תוכניות

– 29 –

לולאות...לולאות...

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

void combine1-goto(vec_ptr v, int *dest){ int i = 0; int val; *dest = 0; if (i >= vec_length(v)) goto done; loop: get_vec_element(v, i, &val); *dest += val; i++; if (i < vec_length(v)) goto loop done:}

1 iteration

Page 30: אופטימיזציה של תוכניות

– 30 –

אל מחוץ vec_length הוצא את ללולאה

אל מחוץ vec_length הוצא את ללולאה

אופטימיזציהאופטימיזציה הוצא אתvec_length .מהלולאה הפנימית

.הערך לא משתנהCode motion

CPE: from 31.25 down to 20.66 )Compiled -O2( vec_length.דורש זמן קבוע, אבל עם תקורה משמעותית

void combine2(vec_ptr v, int *dest){ int i; int length = vec_length(v); *dest = 0; for (i = 0; i < length; i++) { int val; get_vec_element(v, i, &val); *dest += val; }}

Page 31: אופטימיזציה של תוכניות

– 31 –

חוסמי אופטימיזציות: פונקציותחוסמי אופטימיזציות: פונקציות או את או את vec_lenvec_lenמדוע, בעצם, לא יכול המהדר להוציא את מדוע, בעצם, לא יכול המהדר להוציא את

strlenstrlen ? מחוץ ללולאה הפנימית ?מחוץ ללולאה הפנימית לפונקציות יכול להיותside effectsייתכן שהפונקציה משנה את המצב הגלובלי

.ייתכן שהיא מחזירה ערכים שונים עבור קריאה עם אותם ארגומנטים - ייתכן שלstrlen יש אינטראקציה עם lower.

vec_len,vec_len, strlenstrlenמדוע בעצם המהדר לא מסתכל על הקוד של מדוע בעצם המהדר לא מסתכל על הקוד של ??

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

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

'המהדר מתייחס לפונקציות כ- 'קופסה שחורה

Page 32: אופטימיזציה של תוכניות

– 32 –

עוד אופטימיזציות...עוד אופטימיזציות...

אופטימיזציותאופטימיזציותהימנע/י מקריאה לפונקציה כדי להביא את האלמנט הבא

מצא מצביע לתחילת הרשימה לפני הלולאה .בתוך הלולאה התייחס למצביע פחות מודולרי ומתאים ל( abstract data types)

CPE: 20.66 6.00קריאות לפונקציות הן יקרות .)הורדנו גם את זמן בדיקת האינדקס )בדיקה שהוא בגבולות המערך

void combine3(vec_ptr v, int *dest){ int i; int length = vec_length(v); int *data = get_vec_start(v); *dest = 0; for (i = 0; i < length; i++) { *dest += data[i];}

Page 33: אופטימיזציה של תוכניות

– 33 –

הקטן גישות לזיכרוןהקטן גישות לזיכרון

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

CPE: 6.00 2.00 )we started from 31.25(רון צורכת זמן רב.גישה לזיכ

void combine4(vec_ptr v, int *dest){ int i; int length = vec_length(v); int *data = get_vec_start(v); int sum = 0; for (i = 0; i < length; i++) sum += data[i]; *dest = sum;}

Page 34: אופטימיזציה של תוכניות

– 34 –

Memory חוסמי אופטימיזציות: Aliasing

Memory חוסמי אופטימיזציות: Aliasing

מדוע המהדר לא הפך את מדוע המהדר לא הפך את combine3combine3 ל ל combine4combine4 בעצמו?בעצמו?

:חשש מ חשש מ התשובה:התשובהAliasingAliasing)נּוי Vנּוי( )ִּכ Vִּכ( .שתי התייחסויות שונות לזיכרון מתייחסות לאותו מיקום

v: [2, 3, 6] combine3(v, get_vec_start(v)+2) -->

האיבר האחרון בווקטור עכשיו יאחסן את התוצאה.

[2,3,0] [2,3,2] [2,3,5] [2,3,10]

combine4(v, get_vec_start(v)+2) -->

התוצאה שונה.

[2,3,6] [2,3,6] [2,3,6] [2,3,11]

הן לא בהכרח זהות בנוכחות combine4ו combine3 מסקנה:כינויים.

Page 35: אופטימיזציה של תוכניות

– 35 –

Memory חוסמי אופטימיזציות: Aliasing

Memory חוסמי אופטימיזציות: Aliasing

נשים לב: ב C, aliasing.נפוץ

בגלל שניתן לבצעaddress arithmetic כלומר, חישוב מפורש של( כתובת(

.יש גישה ישירה למבנה המאחסן את הנתונים

כדאי להשתמש במשתנים לוקאלייםבעיקר בתוך לולאות כך המהדר יודע שהוא לא צריך לבדוקaliasing .

Page 36: אופטימיזציה של תוכניות

– 36 –

סיכום: אופטימיזציות שאינן תלויות מכונה.

סיכום: אופטימיזציות שאינן תלויות מכונה.((Code MotionCode Motionהזזת קוד )הזזת קוד )

מהדרים יודעים לעשות זאת במקרים מסוימים: מערכים פשוטיםולולאות פשוטות.

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

החלפת אופרטורים יקריםהחלפת אופרטורים יקריםShift, Add, instead of Multiply or Divide

.בדר"כ מהדרים מצליחים לעשות זאת לבד, אבל לא תמידבכל זאת, תלוי מכונה

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

איחוד ביטויים משותפים. איחוד ביטויים משותפים. .למהדרים יש יכולת אלגבראית מוגבלת