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

29
לללללללללללל לללללל ללללל לל ללללללל ללללל ללBryant & O’hallaron / Computer Systems: a programmer’s perspective

Upload: kolya

Post on 19-Jan-2016

62 views

Category:

Documents


0 download

DESCRIPTION

אופטימיזציות תלויות מכונה של תוכניות. מבוסס על Bryant & O’hallaron / Computer Systems: a programmer’s perspective. עד עתה. 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++) - PowerPoint PPT Presentation

TRANSCRIPT

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

אופטימיזציות תלויות מכונה של תוכניותאופטימיזציות תלויות מכונה של תוכניות Bryant & O’hallaron / Computer Systems: a programmer’s perspectiveמבוסס על

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

– 2 –

עד עתה...עד עתה...

המטרההמטרהחשב את סכום איברי הוקטורVector represented by C-style abstract data typeAchieved CPE of 2.00

CPE = Cycles per element

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 3: אופטימיזציות תלויות מכונה של תוכניות

– 3 –

נהפוך את הקוד ליותר כללינהפוך את הקוד ליותר כללי

טיפוסיםטיפוסים נשתמש בהגדרות שונות

data_tבשביל intfloatdouble

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

פעולותפעולות נשתמש בהגדרות שונות

IDENT ו OPבשביל + / 0 * / 1

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

– 4 –

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

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

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

במשתנה זמני... מדוע ? נובע ממוזרות מסוימת בIA32

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

Integer Floating Point Method + * + *

Abstract -g 42.06 41.86 41.44 160.00 Abstract -O2 31.25 33.25 31.25 143.00 Move vec_length 20.66 21.25 21.15 135.00 data access 6.00 9.00 8.00 117.00 Accum. in temp 2.00 4.00 3.00 5.00

התוצאה משתנה!

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

– 5 –

שימוש במצביעיםשימוש במצביעים

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

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

void combine4p(vec_ptr v, int *dest){ int length = vec_length(v); int *data = get_vec_start(v); int *dend = data+length; int sum = 0; while (data < dend) { sum += *data; data++; } *dest = sum;}

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

– 6 –

ארכיטקטורה של מעבד מודרני

ארכיטקטורה של מעבד מודרני

ExecutionExecution

FunctionalUnits

Instruction ControlInstruction Control

Integer/Branch

FPAdd

FPMult/Div

Load Store

InstructionCache

DataCache

FetchControl

InstructionDecode

Address

Instrs.

Operations

PredictionOK?

DataData

Addr. Addr.

GeneralInteger

Operation Results

RetirementUnit

RegisterFile

RegisterUpdates

Control Unit (CU)

Arithmetic Logic Unit

(ALU)

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

– 7 –

Pentium IIIהיכולות של Pentium IIIהיכולות של ניתן להריץ במקביל:ניתן להריץ במקביל:

1 load 1 store 2 integer (one may be branch) 1 FP Addition 1 FP Multiplication or Division

Some Instructions Take > 1 Cycle, but Can be Some Instructions Take > 1 Cycle, but Can be PipelinedPipelined Instruction Latency Cycles/Issue Load / Store 3 1 Integer add 1 1 Integer Multiply 4 1 Integer Divide 36 36 Double/Single FP Multiply 5 2 Double/Single FP Add 3 1 Double/Single FP Divide 38 38

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

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

– 8 –

Loop אופטימיזציה: פרישת לולאות (Unrolling(

Loopאופטימיזציה: פרישת לולאות (Unrolling(

אופטימיזציה:אופטימיזציה: צרף מספר איטרציות לתוך

גוף הלולאה..חוסך תקורה של הלולאהpipelining של פקודת load –

פעולות.3עד .קשור קצוות' בסוף'Measured CPE = 1.33

בנוסף:בנוסף::בלוק בסיסי עם יותר פעולות

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

:ביצוע במקביל של למשלפעולות בסיסיות אם הן בלתי

תלויות.

void combine5(vec_ptr v, int *dest){ int length = vec_length(v); int limit = length-2; int *data = get_vec_start(v); int sum = 0; int i; /* Combine 3 elements at a time */ for (i = 0; i < limit; i+=3) { sum += data[i] + data[i+1] + data[i+2]; } /* Finish any remaining elements */ for (; i < length; i++) { sum += data[i]; } *dest = sum;}

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

– 9 –

loadשל ) pipelining(הצנרה loadשל ) pipelining(הצנרה מן

הזר

צי

Loadפעולות 3 קיבלנו מחזורי שעון5תוך

add

add

add

Lo

ad

Lo

ad

Lo

ad

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

– 10 –

Unrollingההשפעה של Unrollingההשפעה של

בדוגמה שלנו עוזר רק לחיבורintegers במקרים האחרים האלמנט הדומיננטי הוא הlatency של הפעולות

(שקף הבא).

.ההשפעה היא לא ליניארית או מונוטונית.גורמים רבים משפיעים על השיבוץ בפועל של הפעולות

Unrolling DegreeUnrolling Degree 11 22 33 44 88 1616

IntegerInteger SumSum 2.002.00 1.501.50 1.331.33 1.501.50 1.251.25 1.061.06

IntegerInteger ProductProduct 4.004.00

FPFP SumSum 3.003.00

FPFP ProductProduct 5.005.00

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

– 11 –

load של ) pipelining( הצנרה load של ) pipelining( הצנרה מן

הזר

צי כאן הצנרה לא עוזרת...

Lo

ad

Lo

ad

Lo

ad

Mu

ltip

ly

Mu

ltip

ly

Mu

ltip

ly

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

– 12 –

חישוב סדרתיחישוב סדרתיחישובחישוב

((((((((((((1 * x0) * x1) * x2) * x3) * x4) * x5) * x6) * x7) * x8) * x9) * x10) * x11)

ביצועיםביצועים N elements, D cycles/operation N*D cycles

*

*

11 xx00

xx11

*

xx22

*

xx33

*

xx44

*

xx55

*

xx66

*

xx77

*

xx88

*

xx99

*

xx1010

*

xx1111

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

– 13 –

אופטימיזציה: פרישת לולאות Parallel Loop Unrolling מקבילית

אופטימיזציה: פרישת לולאות Parallel Loop Unrolling מקבילית

גרסה: הכפלת שלמיםגרסה: הכפלת שלמים

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

בלתי תלויות..ניתן לביצוע במקביל

.הכפל אותם בסוף

ביצועים:ביצועים: CPE = 2.0

המהירות הוכפלה (עבור) intמכפלת

void combine6(vec_ptr v, int *dest){ int length = vec_length(v); int limit = length-1; int *data = get_vec_start(v); int x0 = 1; int x1 = 1; int i; /* Combine 2 elements at a time */ for (i = 0; i < limit; i+=2) { x0 *= data[i]; x1 *= data[i+1]; } /* Finish any remaining elements */ for (; i < length; i++) { x0 *= data[i]; } *dest = x0 * x1;}

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

– 14 –

חישוב שתי מכפלות במקבילחישוב שתי מכפלות במקבילחישוב:חישוב:

((((((1 * x0) * x2) * x4) * x6) * x8) * x10) *

((((((1 * x1) * x3) * x5) * x7) * x9) * x11)

ביצועים:ביצועים: N elements, D cycles/operation (N/2+1)*D cycles ~2X performance improvement

*

*

11 xx11

xx33

*

xx55

*

xx77

*

xx99

*

xx1111

*

*

*

11 xx00

xx22

*

xx44

*

xx66

*

xx88

*

xx1010

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

– 15 –

דרישות ליצירת ריצה מקביליתדרישות ליצירת ריצה מקבילית

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

.מכפלת שלמים – בסדר לא תמיד נכון עבורfloating-point

בסדר ברוב האפליקציות.«

דרישות מהחומרה:דרישות מהחומרה:Pipelined functional units+ המעבד צריכים להיות מסוגלים לזהות את האפשרות המהדר

למקביליות מתוך הקוד. נקראout-of-order execution.

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

– 16 –

כיצד נוצרת ריצה מקבילית ?כיצד נוצרת ריצה מקבילית ?

ב בIA-32IA-32 אין פקודות מפורשות שאומרות למעבד איזה אין פקודות מפורשות שאומרות למעבד איזה פקודות ניתן לבצע באופן בלתי תלוי.פקודות ניתן לבצע באופן בלתי תלוי.

בIA-64.דווקא יש

1010למעבד יש יכולת מסוימת להסתכל קדימה – על למעבד יש יכולת מסוימת להסתכל קדימה – על ~ ~הפקודות הבאות. הפקודות הבאות.

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

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

– 17 –

Optimization Results for CombiningOptimization Results for Combining

Integer Floating Point Method + * + *

Abstract -g 42.06 41.86 41.44 160.00 Abstract -O2 31.25 33.25 31.25 143.00 Move vec_length 20.66 21.25 21.15 135.00 data access 6.00 9.00 8.00 117.00 Accum. in temp 2.00 4.00 3.00 5.00 Pointer 3.00 4.00 3.00 5.00 Unroll 4 1.50 4.00 3.00 5.00 Unroll 16 1.06 4.00 3.00 5.00 2 X 2 1.50 2.00 2.00 2.50 4 X 4 1.50 2.00 1.50 2.50 8 X 4 1.25 1.25 1.50 2.00 Theoretical Opt. 1.00 1.00 1.00 2.00 Worst : Best 39.7 33.5 27.6 80.0

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

– 18 –

#2Parallel Unrollingשיטה #2Parallel Unrollingשיטה גירסת קוד: הכפלת גירסת קוד: הכפלת

שלמיםשלמים

אופטימיזציהאופטימיזציה הכפל זוגות, ואז עדכן

והשלם תוצאה.“Tree height

reduction”

PerformancePerformance CPE = 2.5

void combine6aa(vec_ptr v, int *dest){ int length = vec_length(v); int limit = length-1; int *data = get_vec_start(v); int x = 1; int i; /* Combine 2 elements at a time */ for (i = 0; i < limit; i+=2) { x *= (data[i] * data[i+1]); } /* Finish any remaining elements */ for (; i < length; i++) { x *= data[i]; } *dest = x;}

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

– 19 –

#2שיטה #2שיטה חישוב:חישוב:

((((((1 * (x0 * x1)) * (x2 * x3)) * (x4 * x5)) * (x6 * x7)) * (x8 * x9)) * (x10 * x11))

ביצועים:ביצועים: N elements, D cycles/operation Should be (N/2+1)*D cycles

CPE = 2.0

Measured CPE worse

*

*

11

*

*

*

*

*

xx11xx00

*

xx33xx22

*

xx55xx44

*

xx77xx66

*

xx99xx88

*

xx1111xx1010UnrollingUnrolling CPE CPE

(measured)(measured)CPE CPE

(theoretical)(theoretical)

22 2.502.50 2.002.00

33 1.671.67 1.331.33

44 1.501.50 1.001.00

66 1.781.78 1.001.00

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

– 20 –

מקביליותמקביליות

CPE = 4.00מכפלות מבוצעות באופן סדרתי

/* Combine 2 elements at a time */ for (i = 0; i < limit; i+=2) { x = x * (data[i] * data[i+1]); }

/* Combine 2 elements at a time */ for (i = 0; i < limit; i+=2) { x = (x * data[i]) * data[i+1]; }

CPE = 2.50חלק מהמכפלות - במקביל

*

*

11 xx00

xx11

*

xx22

*

xx33

*

xx44

*

xx55

*

xx66

*

xx77

*

xx88

*

xx99

*

xx1010

*

xx1111

*

*

11 xx00

xx11

*

xx22

*

xx33

*

xx44

*

xx55

*

xx66

*

xx77

*

xx88

*

xx99

*

xx1010

*

xx1111

*

*

11

*

*

*

*

*

xx11xx00

*

xx33xx22

*

xx55xx44

*

xx77xx66

*

xx99xx88

*

xx1111xx1010

*

*

11

*

*

*

*

*

xx11xx00

*

xx11xx00

*

xx33xx22

*

xx33xx22

*

xx55xx44

*

xx55xx44

*

xx77xx66

*

xx77xx66

*

xx99xx88

*

xx99xx88

*

xx1111xx1010

*

xx1111xx1010

data[2]*data[3]במקביל ל X * (data[0]*data[1])

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

– 21 –

מגבלות של ביצוע מקבילימגבלות של ביצוע מקבילי

דרושים רגיסטרים רביםדרושים רגיסטרים רבים.כדי להחזיק תוצאות של מכפלות / סכומים רגיסטרים שמישים ל - 6יש רק Integers

.'דרושים גם בשביל מצביעים, תנאי לולאה, וכו

8 רגיסטרים ל floating-point – כשאין מקום ברגיסטרים, המידע מועבר לזיכרון הראשי (ל

stack .( נקראregister-spilling.מבטל את האפקטיביות של האופטימיזציה

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

– 22 –

כום: hתוצאות על סPentium III כום: hתוצאות על סPentium III

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

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

– 23 –

דומה לPentium 3.למרות שהמבנה הפנימי והמהדר שונים לחלוטין

Alphaתוצאות על מחשב סכום: Alphaתוצאות על מחשב סכום:

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

– 24 –

Pentium 4תוצאות עבור Pentium 4תוצאות עבור

2.0מהירות שעון גבוהה יותר GHz לא נוצרת הבעיה בגלישה שלFP.

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

– 25 –

הסתעפויותהסתעפויות

בעיהבעיה הCU חייב להיות לפני ה ALU או ה) execution unit כדי לייצר (

ינוצל באופן מקסימלי.ALUמשימות מספיק מהר כך ש ה

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

העלות של חיזוי שגוי:העלות של חיזוי שגוי: עלpentium III: ~14 clock cycles

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

– 26 –

לעתים ניתן להימנע מהסתעפויות...לעתים ניתן להימנע מהסתעפויות...'שימוש ב'מסכות

הרעיון הוא לנסות למנועbranch prediction:במקומות בהם נקרא הרבה פעמים אין עדיפות לכיוון מסוים של הif לכן בדר"כ לא רלבנטי ללולאות שם)

גבוהה מדי.branch missיש עדיפות). העלות של

int bmax(int x, int y){ int mask = -(x>y); return (mask & x) | (~mask & y);}

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

– 27 –

לעתים ניתן להימנע מהסתעפויות...לעתים ניתן להימנע מהסתעפויות...'שימוש ב'מסכות

במקרה הספציפי הזהgcc הופך את זה חזרה ל if... ניתן לפתור על ידי הכרזתvolatile int mask.

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

:22תקורה clock cycles.

int bmax(int x, int y){

volatile int t = (x>y);int mask = -t; return (mask & x) | (~mask & y);

}

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

– 28 –

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

Loop UnrollingLoop Unrollingחלק מהמהדרים עושים זאת אוטומטיתבדר"כ באופן ידני ניתן לעשות טוב יותר

))Instruction-Level ParallelismInstruction-Level Parallelismמקביליות (מקביליות (מאוד תלוי מכונה

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

– 29 –

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

שמרו על איזון בין יעילות לקריאות ויכולת תחזוקהשמרו על איזון בין יעילות לקריאות ויכולת תחזוקה

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

.כך תאפשרו למהדר לעשות את העבודה שלו

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

להאצה.