1.43k likes | 1.56k Views
סמינר במדעי המחשב. תלויות בקרה. (Control Dependence). מבוסס על פרק 7 בספר של Allen and Kennedy. מבוא. בהרצאות הקודמות ראינו כיצד מבצעים טרנפורמציות ללולאות, ומקבלים במקומם הוראות ווקטוריות או מקביליות המנצלות את היכולות של המעבדים המודרנים.
E N D
סמינר במדעי המחשב תלויות בקרה (Control Dependence) מבוסס על פרק 7 בספר של Allen and Kennedy
מבוא • בהרצאות הקודמות ראינו כיצד מבצעים טרנפורמציות ללולאות, ומקבלים במקומם הוראות ווקטוריות או מקביליות המנצלות את היכולות של המעבדים המודרנים. • למדנו למצוא תלויות מידע בין הוראות בתוך גוף הלולאה ע"י בניית גרף התלויות, ולמדנו להסיק מהגרף מתי ואלו אופטימיזציות מותר לבצע. • עד עתה התעלמנו לחלוטין מתלויות בקרה, הנגרמות מהוראות של control (כמו קפיצות מותנות) העלולות להופיע בגוף הלולאה.
נתבונן למשל בקטע הקוד הבא: DO 100 I = 1, N S1 IF (A(I-1) > 0) GOTO 100 S2 A(I) = A(I) + B(I)*C 100 CONTINUE -1 S1 S2 מבוא • אם נתבונן בתלויות המידע בקוד בלבד, נקבל את גרף התלויות: ולכן בהתייחס לתלויות מידע בלבד ניתן לבצע אופטימיזציה ולקבל: P
S2 A(1:N) = A(1:N)+ B(1:N)*C DO 100 I = 1, N S1 IF (A(I-1) > 0) GOTO 100 100 CONTINUE קוד לא שקול - בקוד שקיבלנו S2 מבוצע ללא תנאי! מבוא DO 100 I = 1, N S1 IF (A(I-1) > 0) GOTO 100 S2 A(I) = A(I) + B(I)*C 100 CONTINUE
איפה טעינו? • אנו התייחסנו רק לתלויות מידע, ופספסנו תלות אחרת בין S1 ל-S2שהיתה יוצרת מעגל בגרף התלויות ומונעת מאיתנו להחליף את סדר ההוראות. ? S1 S2 -1 • תלות זו היא תלות בקרה – Control dependent.
התמודדות עם תלויות בקרה • ניתן כמובן פשוט להחליט שאנו לא מבצעים אופטימיזציות על לולאות עם הוראות בקרה בתוכם, אך הוראות בקרה בלולאות זה דבר נפוץ וההפסד יהיה גדול מאוד. • אנו נראה שני דרכים לטיפול בתלויות בקרה: א. If conversion – בדרך זו ננסה להחליף את כל תלויות הבקרה בתלויות מידע רגילות, בכך שננסה להחליף את כל הוראות הקפיצה המותנית בהוראות if. ב. CDG (control dependence graph) – בדרך זו נכניס את כל תלויות הבקרה לגרף (בדומה לגרף תלויות המידע) ונסיק מהגרף אלו אופטימיזציות מותר לבצע.
נתבונן בקטע הקוד הבא. האם ניתן למקבלו? DO 100 I = 1, N S1 IF (A(I-1) > 0) GOTO 100 S2 A(I) = A(I) + B(I)*C S3 B(I) = B(I) + A(I) 100 CONTINUE דוגמא לחיזוק האינטואיציה • אם נצליח להיפטר מהוראה S1 נקבל קוד המכיל תלויות מידע בלבד – אותו אנו כבר יודעים לנתח. • ברור כי לא ניתן להוציא "סתם" את ההוראה – בתוכנית המקורית הוראות S2, S3 מתבצעות רק כאשר A(I-1) גדול מאפס.
דוגמא לחיזוק האינטואיציה (המשך) • נתבונן בקטע הקוד הבא. האם ניתן למקבלו? DO 100 I = 1, N S1IF (A(I-1) > 0)GOTO 100 S2 A(I) = A(I) + B(I)*C S3 B(I) = B(I) + A(I) 100 CONTINUE • לכן נרצה להוסיף תנאי (if) להוראות S2, S3, שיבטיח כי הן יתבצעו רק אם היא הן היו מתבצעות בתוכנית המקורית. • נקבל את הקוד השקול הבא (הפעם ללא תלויות בקרה):
דוגמא לחיזוק האינטואיציה (המשך) • נתבונן בקטע הקוד הבא. האם ניתן למקבלו? DO 100 I = 1, N S1IF (A(I-1) > 0)GOTO 100 S2 A(I) = A(I) + B(I)*C S3 B(I) = B(I) + A(I) 100 CONTINUE DO 100 I = 1, N IF (A(I-1) >= 0) A(I) = A(I) + B(I)*C IF (A(I-1) >= 0) B(I) = B(I) + A(I) 100 CONTINUE
דוגמא לחיזוק האינטואיציה (המשך) DO 100 I = 1, N S3 IF (A(I-1) >= 0) A(I) = A(I) + B(I)*C S4 IF (A(I-1) >= 0) B(I) = B(I) + A(I) 100 CONTINUE • נשם לב כי הערכים של A(I) ו-B(I) בהוראות S3 ו-S4 נקבעים עתה כפונקציה של A(I-1) (בנוסף לתלויות המקוריות האחרות). • קיבלנו לולאה עם תלויות מידע רגילות, שהגרף שלהם הוא: S3 S4
ולכן ניתן למקבל את S4 ולקבל: DO 100 I = 1, N S3 IF (A(I-1) >= 0) A(I) = A(I) + B(I)*C 100 CONTINUE S4 WHERE (A(0:N-1) <= 0) B(1:N) = B(1:N)+A(1:N) דוגמא לחיזוק האינטואיציה (המשך) DO 100 I = 1, N S3 IF (A(I-1) >= 0) A(I) = A(I) + B(I)*C S4 IF (A(I-1) >= 0) B(I) = B(I) + A(I) 100 CONTINUE
קפיצות מותנות – הפרדה לסוגים נהוג לחלק את הקפיצות המותנות שיכולות להופיע בתוכנית לשלושה סוגים: א) Forward Branch– קפיצה מנקודה אחת בלולאה,קדימה לנקודה אחרת בלולאה (אותה רמת קינון). ב) Backward Branch - קפיצה מנקודה אחת בלולאה,אחורה לנקודה אחרת בלולאה (אותה רמת קינון). ג) Exit branch – קפיצה מגוף הלולאה אל מחוץ ללולאה (לפני הלולאה או אחריה). ד) שיקוצים שונים - קפיצות לתוך לולאות, assign gotos...
Forward branch Backward branch Exit branch סוגי קפיצות מותנות – דוגמאות DO 100 I = 1, N H: IF (A(I-1) > 0) GOTO L A(I) = A(I) + B(I)*C IF (A(I) < 0) GOTO H L: B(I) = B(I) + A(I) IF (B(I) > 0) GOTO R 100 CONTINUE R: C = C + D; P P P
הגיע זמן להגדרה... הגדרה – guard של הוראה בתוכנית הוא תנאי לוגי, כך שההוראה מבוצעת אם ורק אם ערך ה-guard שלה (כאשר השליטה בתוכנית מגיעה אליה) מוערך ל-true. מטרתנו: להוציא מהתוכנית את כל הקפיצות המותנות, ובמקומם להתנות (IF) ביצוע כל הוראה בסיפוק ה-guard שלה.
שקף לחיזוק האינטואיציה S5 (G5) S6 (G6) S7 (G7) S8 (G8) S9 (G9) S10 (G10) S11 (G11) S12 (G12) S13 (G13) G5=G6=G7=G8 G9=(G8 AND NOT(M1)) G10=G11=G9 G12=(G8 AND M1) OR G11 M1 G13=G12 P P P P P
קפיצות קדימה – המקרה הקל ביותר • עוברים על קוד התוכנית, הוראה אחרי הוראה ע"פ סדר ביצוע. • בכל שלב נחזיק בזיכרון: א. ביטוי לוגי נוכחי (Current) שיבטא את התנאי הדרוש כדי שנגיע להוראה ישירות מההוראה הקודמת. ב. לכל הוראה נשמור ביטוי לוגי נוסף (פרטי שלה) שיציין התנאים להגיע אל ההוראה ע"י קפיצות אליה. • ה-currentיאותחל ל-true (הוראה ראשונה מבוצעת תמיד) וכל הביטויים הפרטיים של ההוראות יאותחלו ל-false. P P P
קפיצות קדימה – המקרה הקל ביותר • ה-guard המתאים לכל הוראה יחושב ע"י ביצוע OR בין ה-current לבין הביטוי הפרטי הנוכחי שלה. נעדכן ערך ה-currentבהתאם. אינטואיציה: ההוראה מבוצעת אם הגענו אליה ישירות מההוראה הקודמת (אז ה-current יתקיים) או אם קפצנו אליהמקפיצה שהיא כתובתה (אז אחד התנאים הפרטיים של ההוראה יתקיימו).
קפיצות קדימה – המקרה הקל ביותר • ה-guard המתאים לכל הוראה יחושב ע"י ביצוע OR בין ה-current לבין הביטוי הנוכחי שלה. נעדכן ערך ה-current בהתאם. • אם ההוראה הנוכחית היא קפיצה מותנית לכתובת L:* עדכן התנאי הפרטי של הוראה L ע"י ביצוע OR לוגי בין התנאי הפרטי לתנאי שהקפיצה תתרחש. תנאי להתרחשות הקפיצה: AND לוגי בין ה-CURRENT(תנאי להתרחשות הוראת הקפיצה) לבין תנאי הקפיצה.
קפיצות קדימה – המקרה הקל ביותר • ה-guard המתאים לכל הוראה יחושב ע"י ביצוע OR בין ה-current לבין הביטוי הנוכחי שלה. נעדכן ערך ה-current בהתאם. • אם ההוראה הנוכחית היא קפיצה מותנית לכתובת L:* עדכן התנאי הפרטי של הוראה L ע"י ביצוע OR לוגי בין התנאי הפרטי לתנאי שהקפיצה תתרחש. * עדכן ה-current ע"י ביצוע AND לוגי עם ערך ה-NOT של תנאי הקפיצה. זהו התנאי לביצוע ההוראה הבאה
כמעט קפיצות קדימה – המקרה הקל ביותר • ה-guard המתאים לכל הוראה יחושב ע"י ביצוע OR בין ה-current לבין הביטוי הנוכחי שלה. נעדכן ערך ה-current בהתאם. • אם ההוראה הנוכחית היא קפיצה מותנית לכתובת L:* עדכן התנאי הפרטי של הוראה L ע"י ביצוע OR לוגי בין התנאי הפרטי לתנאי שהקפיצה תתרחש. * עדכן ה-current ע"י ביצוע AND לוגי עם ערך ה-NOT של תנאי הקפיצה. * החלף הוראת הקפיצה המותנית במשתנה בוליאני ייחודי המקבל את תנאי הקפיצה. • לפני כל הוראה, הוסף תנאי IF המכיל את CURRENT. P
(current) קפיצות קדימה – דוגמא C = C + 1 DO 100 I = 1, N IF (A(I) > 10) GOTO 60 20 A(I) = A(I) + 10 IF (B(I) > 10) GOTO 80 40 B(I) = B(I) + 10 60 A(I) = B(I) + A(I) 80 B(I) = A(I) - 5 100 CONTINUE C = C + D; true guard: שורה 80 מתבצעת תמיד
קפיצות קדימה – דוגמא IF (true) C = C + 1 DO 100 I = 1, N IF (A(I) > 10) GOTO 60 A(I) = A(I) + 10 IF (B(I) > 10) GOTO 80 40 B(I) = B(I) + 10 60 A(I) = B(I) + A(I) 80 B(I) = A(I) - 5 100 CONTINUE C = C + D; true guard: לפני הוראות לולאה לאמוסיפים תנאים (IF) P
קפיצות קדימה – דוגמא IF (true) C = C + 1 DO 100 I = 1, N IF (A(I) > 10) GOTO 60 A(I) = A(I) + 10 IF (B(I) > 10) GOTO 80 40 B(I) = B(I) + 10 60 A(I) = B(I) + A(I) 80 B(I) = A(I) - 5 100 CONTINUE C = C + D; true guard:
קפיצות קדימה – דוגמא if (true) C = C + 1 DO 100 I = 1, N IF (A(I) > 10) GOTO 60 A(I) = A(I) + 10 IF (B(I) > 10) GOTO 80 40 B(I) = B(I) + 10 60 A(I) = B(I) + A(I) 80 B(I) = A(I) - 5 100 CONTINUE C = C + D; IF (A(I) > 10) GOTO 60 -> m1=(A(I)>10) guard: לתנאי הפרטי של שורה 60 יש להוסיף את הביטוי לקפיצה "מוצלחת" P
קפיצות קדימה – דוגמא IF (true) C = C + 1 DO 100 I = 1, N IF (true) m1 = (A(I) > 10) A(I) = A(I) + 10 IF (B(I) > 10) GOTO 80 40 B(I) = B(I) + 10 60 A(I) = B(I) + A(I) 80 B(I) = A(I) - 5 100 CONTINUE C = C + D; guard:
קפיצות קדימה – דוגמא IF (true) C = C + 1 DO 100 I = 1, N IF (true) m1 = (A(I) > 10) IF (true AND NOT (m1)) A(I)=A(I)+10 IF (B(I) > 10) GOTO 80 40 B(I) = B(I) + 10 60 A(I) = B(I) + A(I) 80 B(I) = A(I) - 5 100 CONTINUE C = C + D; guard:
קפיצות קדימה – דוגמא IF (true) C = C + 1 DO 100 I = 1, N IF (true) m1 = (A(I) > 10) IF (true AND NOT (m1)) A(I)=A(I)+10 IF (B(I) > 10) GOTO 80 -> m2 = (B(I)>10) 40 B(I) = B(I) + 10 60 A(I) = B(I) + A(I) 80 B(I) = A(I) - 5 100 CONTINUE C = C + D; guard: לתנאי הפרטי של שורה 80 יש להוסיף את הביטוי לקפיצה מוצלחת
קפיצות קדימה – דוגמא IF (true) C = C + 1 DO 100 I = 1, N IF (true) m1 = (A(I) > 10) IF (true AND NOT (m1)) A(I)=A(I)+10 IF (true AND NOT (m1)) m2 = (B(I)>10) 40 B(I) = B(I) + 10 60 A(I) = B(I) + A(I) 80 B(I) = A(I) - 5 100 CONTINUE C = C + D; guard:
קפיצות קדימה – דוגמא IF (true) C = C + 1 DO 100 I = 1, N IF (true) m1 = (A(I) > 10) IF (true AND NOT (m1)) A(I)=A(I)+10 IF (true AND NOT (m1)) m2 = (B(I)>10) 40 IF (true AND NOT (m1) AND NOT (m2)) B(I)=B(I)+10 60 A(I) = B(I) + A(I) 80 B(I) = A(I) - 5 100 CONTINUE C = C + D; guard: התנאי הפרטי של שורה 60 אינו FALSE ולכן הוא יש להוסיפו ב-OR ל-guard הנוכחי. P
קפיצות קדימה – דוגמא IF (true) C = C + 1 DO 100 I = 1, N IF (true) m1 = (A(I) > 10) IF (true AND NOT (m1)) A(I)=A(I)+10 IF (true AND NOT (m1)) m2 = (B(I)>10) 40 IF (true AND NOT (m1) AND NOT (m2)) B(I)=B(I)+10 60 A(I) = B(I) + A(I) 80 B(I) = A(I) - 5 100 CONTINUE C = C + D; guard:
קפיצות קדימה – דוגמא IF (true) C = C + 1 DO 100 I = 1, N IF (true) m1 = (A(I) > 10) IF (true AND NOT (m1)) A(I)=A(I)+10 IF (true AND NOT (m1)) m2 = (B(I)>10) 40 IF (true AND NOT (m1) AND NOT (m2)) B(I)=B(I)+10 60 IF (… OR (true AND m1)) A(I) = B(I) + A(I) 80 B(I) = A(I) - 5 100 CONTINUE C = C + D; guard: הביטוי גדול מכדי להיכנס למצגת! שוב תנאי פרטיאינו FALSE P
קפיצות קדימה – דוגמא IF (true) C = C + 1 DO 100 I = 1, N IF (true) m1 = (A(I) > 10) IF (true AND NOT (m1)) A(I)=A(I)+10 IF (true AND NOT (m1)) m2 = (B(I)>10) 40 IF (true AND NOT (m1) AND NOT (m2)) B(I)=B(I)+10 60 IF (… OR (true AND m1)) A(I) = B(I) + A(I) 80 IF (… OR (true AND NOT(m1) AND m2)) B(I)=A(I)-5 100 CONTINUE C = C + D; guard: ה-guard שקול לוגית ל-true נימנע מלהוסיף תנאי לפני CONTINUE (טעות קומפילציה) P
קפיצות קדימה – דוגמא IF (true) C = C + 1 DO 100 I = 1, N IF (true) m1 = (A(I) > 10) IF (true AND NOT (m1)) A(I)=A(I)+10 IF (true AND NOT (m1)) m2 = (B(I)>10) 40 IF (true AND NOT (m1) AND NOT (m2)) B(I)=B(I)+10 60 IF (… OR (true AND m1)) A(I) = B(I) + A(I) 80 IF (… OR (true AND NOT(m1) AND m2)) B(I)=A(I)-5 100 CONTINUE C = C + D; guard:
קפיצות קדימה – דוגמא IF (true) C = C + 1 DO 100 I = 1, N IF (true) m1 = (A(I) > 10) IF (true AND NOT (m1)) A(I)=A(I)+10 IF (true AND NOT (m1)) m2 = (B(I)>10) 40 IF (true AND NOT (m1) AND NOT (m2)) B(I)=B(I)+10 60 IF (… OR (true AND m1)) A(I) = B(I) + A(I) 80 IF (… OR (true AND NOT(m1) AND m2)) B(I)=A(I)-5 100 CONTINUE IF (…) C = C + D; guard:
צא בחוץ!! קפיצות החוצה
קפיצות החוצה – מתחיל להסתבך אינטואיציה: המקרה של קפיצה החוצה מסובך יותר שכן מרגע שהקפיצה מתרחשת הלולאה מפסיקה להתבצע: DO I = 1, N S1 IF (p(I)) GOTO 100 S2 END 100 S3 בפרט במקרה זה גם ביצוע S1, שלא בטווח הקפיצה, תלוי בתוצאת הקפיצה המותנת.
תחילה נטפל בשתיהקפיצות החוצה בלולאה הפנימית קפיצות החוצה – דוגמא DO 200 I = 1, 100 50 S1 DO 100 J = 1, 100 S2 IF (X(I,J) > 300) GOTO 300 S3 IF (Y(I,J) < 50) GOTO 50 S4 100 CONTINUE S5 200 CONTINUE 300 S6 P
קפיצות החוצה – דוגמא DO 200 I = 1, 100 50 S1 Ex1 = TRUE Ex2 = TRUE DO 100 J = 1, 100 S2 IF (X(I,J) > 300) GOTO 300 S3 IF (Y(I,J) < 50) GOTO 50 S4 100 CONTINUE S5 200 CONTINUE 300 S6 הוספת משתנים בוליאנים מתאימים לקפיצות
קפיצות החוצה – דוגמא DO 200 I = 1, 100 50 S1 Ex1 = TRUE Ex2 = TRUE DO 100 J = 1, 100 IF (Ex1 AND Ex2) S2 IF (Ex1 AND EX2) IF (X(I,J) > 300) GOTO 300 IF (Ex1 AND Ex2) S3 IF (Ex1 AND Ex2) IF (Y(I,J) < 50) GOTO 50 IF (Ex1 AND Ex2) S4 100 CONTINUE S5 200 CONTINUE 300 S6 קביעת תלות בין ביצוע כל הוראות הלולאה למשתנים הללו
קפיצות החוצה – דוגמא DO 200 I = 1, 100 50 S1 Ex1 = TRUE Ex2 = TRUE DO 100 J = 1, 100 IF (Ex1 AND Ex2) S2 IF (Ex1 AND EX2) Ex1 = NOT (X(I,J) > 300) IF (Ex1 AND Ex2) S3 IF (Ex1 AND Ex2) Ex2 = NOT (Y(I,J) < 50) IF (Ex1 AND Ex2) S4 100 CONTINUE S5 200 CONTINUE 300 S6 שינוי הוראות הקפיצה המקוריות להוראות שיבטיחו שהמשתנים יקבלו FALSE ברגע שהקפיצה התרחשה.
קפיצות החוצה – דוגמא DO 200 I = 1, 100 50 S1 Ex1 = TRUE Ex2 = TRUE DO 100 J = 1, 100 IF (Ex1 AND Ex2) S2 IF (Ex1 AND EX2) Ex1 = NOT (X(I,J) > 300) IF (Ex1 AND Ex2) S3 IF (Ex1 AND Ex2) Ex2 = NOT (Y(I,J) < 50) IF (Ex1 AND Ex2) S4 100 CONTINUE IF (NOT Ex1) GOTO 300 IF (NOT Ex2) GOTO 50 S5 200 CONTINUE 300 S6 העברת הקפיצות אל מחוץ ללולאה
קפיצות החוצה – דוגמא מוסיפים משתנה עזר ש-"יזכור" באיזה איטרציה קפצנו החוצה על מנת שנוכל לשחזר את המשתנה האיטרציה המקורי כשהקפיצה "התרחשה". DO 200 I = 1, 100 50 S1 Ex1 = TRUE Ex2 = TRUEJ’ = 1 DO 100 J = 1, 100IF (Ex1 AND Ex2) J’ = J IF (Ex1 AND Ex2) S2 IF (Ex1 AND EX2) Ex1 = NOT (X(I,J) > 300) IF (Ex1 AND Ex2) S3 IF (Ex1 AND Ex2) Ex2 = NOT (Y(I,J) < 50) IF (Ex1 AND Ex2) S4 100 CONTINUEJ = J’ IF (NOT Ex1) GOTO 300 IF (NOT Ex2) GOTO 50 … עתה ניתן לחזור על התהליך עבור הלולאההחיצונית ולהוציא גם ממנה את הקפיצות החוצה P
קפיצות החוצה – סקירת האלגוריתם עבור כל הוראת קפיצה החוצה: • נגדיר משתנה בוליאני חדש שיאותחל ל-true. • נתנה את ביצוע הוראות הלולאה בכך שערכו של המשתנה הוא true. • נחליף את הוראת הקפיצה בהשמה של ה-NOTשל תנאי הקפיצה אל המשתנה. בכך נבטיח כיהמשתנה יקבלfalse בפעם הראשונה שהקפיצה אמורה להתרחש. • את הוראת הקפיצה נעביר לאחרי הלולאה, והיא תתבצע בתלות במשתנה החדש שהוספנו.
קפיצות החוצה – סקירת האלגוריתם • ייתכן כי קוד מחוץ ללולאה עושה שימוש במשתנה האיטרציה, ולכן להוסיף הוראה שתשחזר את ערכו ברגע שהקפיצה היתה אמורה להתבצע (ע"י שימוש במשתנהזמני(.
קפיצות החוצה – נקודות חשובות • תהליך הוצאת קפיצות החוצה מלולאה נקרא Branch Relocation. • תוצר התהליך כפי שאנחנו יצרנו אותו "רע למיקבול" – יצרנו משתנה סקלרי (Ex1) המופיע בכל קוד הלולאה ולכן יוצר תלויות לאורך כל הקוד. • פתרון – Scalar Expansion.
קפיצות החוצה – נקודות חשובות • לדוגמא הקוד: DO J = 1, M DO I = 1, N A(I,J) = B(I,J) + X IF (L(I,J)) GOTO L C(I,J) = A(I,J) + Y ENDDO D(J) = A(N,J)L: F(J) = C(10,J) ENDDO
קפיצות החוצה – נקודות חשובות • יהפוך ל: מערך חדש נוסף, האיבר ה-i בו הוא הערך של Ex1באיטרציה ה-i ואיברו הראשון מאותחל ל-true. DO J = 1, M am(0,J) = TRUE DO I = 1, N IF (lm(I-1, J)) A(I,J) = B(I,J) + X IF (lm(I-1, J)) m1 = NOT(L(I,J)) am(I, J) = am(I-1, J) AND m1 IF (lm(I,J)) C(I,J) = A(I,J) + Y ENDDOIF (NOT)am(I,J)) goto L D(J) = A(N,J)L: F(J) = C(10,J) ENDDO m1 משתנה זמני המקבל את NOT של תנאי הקפיצה(זהו התנאי שלא קפצנו) מרגע הקפיצה הראשונה, כל אברי המערך יקבלו false P P P
קפיצות החוצה – נקודות חשובות • עתה כל ההוראות בלולאה תלויות בחישוב המערך (תלות לא מעגלית) ולכן ניתן לווקטר ולקבל: DO J = 1, M lm(0,J) = TRUE DO I = 1, N IF (lm(I-1, J)) m1 = NOT(L(I,J)) lm(I, J) = lm(I-1, J) AND m1 IF (lm(I,J)) C(I,J) = A(I,J) + Y ENDDO ENDDOWHERE (lm(0:N-1, 1:M)) A(1:N,1:M)=B(1:N,1:M)+X WHERE (lm(0:N-1, 1:M)) C(1:N,1:M)=A(1:N,1:M)+Y WHERE (lm(N,1:M)) D(1:M) = A(N, 1:M) F(1:M) = C(10, 1:M)