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

חוק Moore ומגבלותיו
לאורך ההיסטוריה של המחשוב הפכו המערכות לבעלות יכולות מחשוב רבות יותר, קיבולת רבה ומהירה יותר, וממדים פיסיים קטנים יותר. במהלך הזמן, היו גם קפיצות מדרגה כגון המעבר משפופרות לטרנזיסטורים ולאחר מכן למעגלים המשולבים. כבר בשנת 1965 נמצאה תבנית לגידול ביכולת עם חוק Moore החוזה הכפלה במורכבות המעגלים המשולבים מדי שנה (לאחר איסוף נקודות נוספות בגרף, התחזית תוקנה להכפלה מדי שנתיים). המשמעות היא שאפשר היה ליצור מעבדי מחשבים בעלי יכולת גדלה, הפועלים בקצבים גדלים בצד הקטנת המרחקים בין השערים הלוגיים, שאפשרו ייצור מערכות משובצות רבות יכולת. כך, טלפונים ניידים ספרתיים שיכלו בתחילת שנות ה–90 לטפל בקול ובמסרונים בלבד, יכולים כיום לספק וועידת וידיאו, גלישה באינטרנט, הורדה וניגון וידיאו ומוסיקה, חיבור תמידי לדוא”ל ולשרות הודעות, וכן טיפול במשימות עמוסות מחשוב כגון ניהול לוחות זמנים ורשימות קשר.
נראה שלחוק Moore עדיין יש תוקף, אך אין הוא ישים עוד לכל תחומי המחשוב. למשל, הנפח של הכוננים הקשיחים ממשיך לעלות, אך מהירויות הגישה גדלות באיטיות יחסית בשל המגבלה המעשית בהגדלת מהירות הסיבוב. מהירות המעבדים שהתפתחה במידה עצומה במהלך השנים הובילה לעליה בצריכת ההספק שלהם וזו יצרה בעיה בפיזור ההספק, ושימוש בקירור פעיל גורם לתוספת בצריכת ההספק (ולעתים לרעש נוסף). לדוגמה, Pentum 4 של Intel מגיע למהירות של 3.8 ג’יגה–הרץ אבל צורך 115 וואט בזמן פעולה!
תכנון מחדש של היע”מ (CPU) או מעבר לארכיטקטורה יעילה יותר כמו RISC, יכולים לשנות את המצב רק לזמן קצר אך אינם פותרים את הבעיה היסודית. כמו כן קיימת אי התאמה חמורה בין מהירות המעבד ומהירות הגישה לזיכרון, שאותה אפשר לפתור רק באופן חלקי בעזרת זיכרון מטמון גדול באותו השבב או באותו מארז, וכתוצאה מכך המעבד מחכה לתגובת זיכרון RAM. התקנים משובצים שמורכבותם גדלה זקוקים ליכולת מחשוב גדולה אבל ברור שמעבדים מהירים יותר אינם התשובה.

האם אפשר להגדיל את מחזורי היע”מ לשנייה מבלי להגדיל את מהירות היע”מ?
גישת “הפרד ומשול” פועלת גם כאן: במקום לדחוק את כל העבודה למעבד יחיד, יש לערב מעבדים רבים יותר בתהליך. הסיבה לכך פשוטה: צריכת ההספק גדלה עם המהירות. לדוגמה, עלות שיפור של 12% במהירות של מעבד היא גידול של 37% בצריכת ההספק, כך השימוש בשני מעבדים או יותר שמהירותם נמוכה, יאפשר מספר זהה או גדול יותר של מחזורי יע”מ בצד שימוש בהספק נמוך יותר. בנוסף, אם נשתמש במעבד בריבוי ליבות באותו השבב, מעגלי התמיכה (ועבודת התכנון) יהיו פשוטים יותר וגם שיתוף זיכרון המטמון (אם הוא משותף) או יצירת קוהרנטיות בין זיכרונות מטמון (כשהם נפרדים) יהיו אפשריים.
לכן היצרנים מפסיקים לייצר מעבדים מהירים ומספקים יכולת גדולה דרך פתרונות מרובי ליבות. עם זאת, בעוד שלמהנדסי החומרה קל יחסית, מפתחי התוכנה צריכים לעבוד קשה כדי להפעיל את הליבות הנוספות.

ארכיטקטורות של
ריבוי ליבות

מודלים של חומרה
קיימות ארכיטקטורות רבות של חומרה, בהן “הטרוגניות” ו”הומוגניות”. שבבי OMAP של TI הם דוגמה טובה לפתרון הטרוגני או אסימטרי: השבבים המתקדמים תוכננו לשימוש בטלפונים ניידים ובנוסף לליבת ARM לשימוש כללי מכילים גם יחידת GPU לטיפול במסך, מעבד DSP לתקשורת וליבת מעבד תמונה לטיפול במצלמה. ברור שפיתוח התוכנה הוא תהליך קשה, מפני שכל ליבה משתמשת בקבוצת פקודות שונה. עם זאת תכנון הומוגני שבו כל הליבות הן מאותו סוג יהיה נפוץ יותר. שבבי ליבה כפולה שולטים כיום בשוק, אם כי קיימים גם בעלי 4, 8, 16 ליבות ויותר. (קיימים שבבי 3 ליבות שהם בדרך כלל שבבי 4 ליבות, שאחת מהן כשלה בבדיקות ומושבתת לצמיתות. היצרנים מגדילים באופן כזה את תפוקת הייצור.) הזהות בין הליבות מאפשרת שימוש באותו קוד, לצורך הפעלתן לפי הצורך, אך ההחלטה איזה קטע תוכנה יפעיל איזה ליבה אינה פשוטה.
מערכות בריבוי מעבדים שימשו כבר בשנת 1961 כאשר B5000 של Burroughs איפשר גישה סימטרית של שמונה מעבדים באפיק מהיר אחד לזיכרון ולמשאבים אחרים. פשטות המבנה הביאה לשימוש נרחב בארכיטקטורת ריבוי מעבדים סימטרית (SMP) זו והיא תשמש במאמר זה מכאן.

שימוש בחומרת SMP
ארכיטקטורת התוכנה הנפוצה ביותר לארכיטקטורת SMP משתמשת במערכת הפעלה אחת השולטת בכל הליבות או המעבדים ומקצה להם באופן דינמי תהליכים (או אף תהליכונים–threads) לצורך איזון העומס. מובן שלהעברת תהליך מליבה אחת לאחרת יש עלות: למשל, יש להעביר את תכולת זיכרון המטמון ולהעתיק את מצב האוגרים והגדרות MMU. בנוסף, חלקי מערכת ההפעלה צריכים לפעול יחד ולהבטיח שמשאבים שנמצאים בשיתוף מוקצים באופן “בטוח” ולכן היא משתמשת יותר במנגנוני הסנכרון כגון מאותתים (semaphore). יש לזכור שלשימוש בארכיטקטורת SMP יש עלויות.
AMP – הגישה ההפוכה
החלופה היא הגישה האסימטרית. למרות שהחומרה סימטרית, מתייחסים לכל ליבה בנפרד, אשר פועלת באופן עצמאי. אין צורך באותה מערכת הפעלה בכולם, או באפשרות להעביר תהליכים בין הליבות. למרות המורכבות, המשמעות היא שכל ליבה יכולה לפעול במערכת הפעלה המתאימה לתפקידה. התקשורת בין התהליכים בליבות שונות יכולה להתבצע דרך הזיכרון ושימוש במנגנון IPC עצמאי כדוגמת LINX של Enea מקל תקשורת בין תהליכים מקומיים או בליבה אחרת. מודל AMP פועל היטב בעיבוד מוכוון קלט/ פלט מאחר שקל להוסיף ליבות, אך רק אם קצבי הקלט/ פלט אחידים וניתנים לכימות.

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

כתיבת יישומים משובצים לליבות מרובות

מה פועל היכן?
במערכות ריבוי מעבדים מושם לעתים דגש רב מדי על “הגינות” ותגובתיות במקום על הביצועים הכוללים של יישומים מסוימים. במערכות משובצות, אם התוכנה מחולקת בצורה נכונה למודולים עם ממשקים מוגדרים היטב, השימוש בארכיטקטורת SMP עומד בדרישות הביצועים.
במקרים אחרים השימוש בארכיטקטורת BMP או AMP, בנוסף להיותו יעיל יותר, הוא גם מאפשר להציב תהליכים קריטיים באופן שיקטין הפרעות.

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

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

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

* סינכרון
כפי שכבר צוין, חיוני לשלוט בגישה בו–זמנית למשאבים והדרך המסורתית לבצע זאת היא על ידי נעילה. קל יותר לקודד ולנפות שגיאות מבקרה גסה, אבל לעתים, התוצאה היא חוסר יעילות שנובע מתהליכים במצב סרק שממתינים בגלל נעילה. לעומת זאת, בקרה עדינה יותר יכולה להגדיל את היעילות והתגובתיות, אך קשה יותר בהרבה לקידוד, ולכן סביר יותר שתביא לנעילת קיפאון (deadlock), לחוסר נעילה (livelock), להיפוך סדרי עדיפויות ולשגיאות. יש לשים לב שבעיות כאלו עלולות להופיע במערכת בריבוי ליבות, למרות ביצוע בדיקה “מקיפה” במערכת עם ליבה יחידה מאחר שאלגוריתמים לשיתוף זמן אינם בדיוק הדמיה של המתרחש בסביבת ריבוי ליבות אמיתית.

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

תגובות סגורות