Concurrency בתעשיה

S h a r k 1 8

New member
Concurrency בתעשיה

היי....

רציתי לשאול עד כמה פתרונות ה multi-threading מושרשים עמוק בתעשיה? האם זה הלחם והחמאה של כל מתכנת? האם זה מושג שהוא בסיסי ממש-ממש (כמו לולאה ומערך, למשל)?

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

vinney

Well-known member
תכתוב קוד לDOS 6, שם אין מקביליות.

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

ipv6

Member
לא יודע מה זה "מושרש עמוק"

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

אם אתה הולך לכיוונים של מערכות Low level שהביצועים קריטיים בהן, כנראה תתקל בחשיבה multi threaded בצורה כזאת או אחרת.
 

S h a r k 1 8

New member
ואיך זה בתכנות בשפות High Level? גם שם זה נורא בסיסי?

ולמה הכוונה "תחום ידע שכדאי להכיר"? להכיר מבחינתי זה שלום-שלום. אני שאלתי על ממש לתכנת ב multi threaded, לדבג, למצוא פתרונות וכו'....
&nbsp
מצד אחד, זה נשמע ממש בסיסי בשביל מתכנתים. מצד שני, היו המוני ראיונות עבודה שלא שאלו אותי כלום על התחום הזה, כולל למשרות low level.
&nbsp
 

ipv6

Member
זה קצת קשה לענות בלי קונטקסט(=חברה\מוצר ספציפי)

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

פגשתי מערכות אחרות שהיו בהם כמה thread-ים עם קשר רופף בינהם לפעמים בלי שיתוף משאבים, שם היה פחות קריטי לחשוב Multi threaded.

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

Lhuna1

New member
נכון, רק הערה קטנה, שביצועים הם לעיתים קרובות חשובים

גם במערכות high-level... (שהבנאדם לא יחשוב שאם הוא הולך להתעסק עם דברים מסוימים הוא יהיה פטור מזה).
 

S h a r k 1 8

New member
איך בד"כ מדבגים את זה?

באמצעות הדפסות על המסך או עם כלי דיבוג "מתוחכמים" יותר?
&nbsp
 

Lhuna1

New member
כמו שמדבגים כל דבר אחר

כל אחד עם השיטות החביבות עליו + מה שקיים בסביבה בה אתה מתכנת, וקודם כל באמצעות ההיגיון שלך.
(כל דיבאגר שאני מכירה יראה לך באיזה ת'רד אתה נמצא אם עצרת בברייקפוינט וכן את ה-call stack של כל שאר הת'רדים).
&nbsp
זה נשמע שאתה מאוד נרתע/חושש מהנושא הזה, ואין סיבה.
נכון, זה מוסיף עוד רמה של מורכבות למערכת, אבל זה לא משהו שונה במהותו מכל בעיה תכנותית אחרת.
&nbsp
&nbsp
 

Lhuna1

New member
עד כמה שידוע לי ב-JAVASCRIPT

כל הקוד שלך רץ בת'רד אחד.
(מוזמנים לתקן אותי אם זה לא נכון, זה לא ממש התחום שלי רק יצא לי להתממשק מול מתכנתי WEB אז אולי אני טועה).
&nbsp
בכל אופן, כן, ברוב המערכות והסביבות זה אינטגרלי.
לגבי הניתוח שלך אני לא כל כך מסכימה.
מקשה על מציאת שגיאות - נכון.
אבל - "מאריך מאד את זמני הפיתוח"? זה תלוי מה אתה רוצה לעשות. הרבה פעמים ההיפך הוא הנכון.
יש דברים שבלי מולטית'רד תתקשה מאוד להשיג, בעיקר פונקציונליות שבה הביצועים חשובים. אז בשביל לממש הכל בת'רד אחד וגם לשמור על הביצועים תצטרך לעשות שמיניות באוויר ודברים מאוד מסובכים, בעוד שעם שימוש בת'רדים נוספים זה יכול להיות פשוט ביותר ודווקא לקצר זמני פיתוח.
&nbsp
 

user32

Well-known member
מנהל
כן, לא, בערך

בדרך כלל JS מריץ הכל בthread אחד. בHTML5 הוסיפו מה שנקרא Web Worker שמאפשר להריץ קטע קוד בthread ברקע. זה נמצא כנראה מעט מאוד בשימוש אז אפשר לומר שJS כמעט תמיד רצה בת'רד אחד.
 

hadooper

New member
node.js עד כמה שזכור לי אינו רץ רק בטרד אחד.

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

user32

Well-known member
מנהל
לא חושב שזה נכון

הקוד שאתה מריץ בNode רץ בת'רד אחד. הוא רץ בצורה יעילה עם הרבה פעולות אסינכרוניות וnon blocking io וכו' אבל בת'רד אחד. כך לפחות אני מבין.
אם יש בסביבה ת'רדים אחרים פנימיים זה לא משנה. אולי יש GC שרץ בתרד מקביל? יכול להיות אבל זה לא משנה את העובדה שהקוד JS שהמתכנת מריץ רץ בבודד.
בnode אין נעילות, אי אפשר להגיע לdead lock ושאר צרות מהסוג הזה ושני פעולות לא יתבצעו בו זמנית על משתנה אחד.
אגב, גם בדפדפן רצים המון ת'רדים אבל הJS ירוץ בת'רד בודד.
 

hadooper

New member
כלומר, נהוג להתייחס אליו חיצונית כאילו היה single-threaded

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

user32

Well-known member
מנהל
קראת את כל השרשור שם?

כן, יש ת'רדים שונים שמטפלים בדברים שונים כמו IO למשל. אבל הקוד שאתה כותב לעולם ירוץ בthread אחד. האחרון שהגיב שם מתאר את זה יפה: פעולות כמו IO מבוצעות על ידי thread שונה (שלמתכנת הJS אין שליטה ולא אכפת לו מזה) וכשהם חוזרים הם ממוזגים חזרה לתוך הthread הראשי והיחיד של הV8 (שהוא מנוע הJS).

כמה דברים:
קודם כל, אם באמת הקוד היה חוזר לthread אחד, איך הייתי יכול למשל לרוץ ולשנות מערך בתגובה לשני אירועים שונים? הם מן הסתם היו מתנגשים והיה צורך בנעילות. עובדה שלא צריך נעילות.
עוד משהו: נסה לכתוב פעולה ארוכה בNode ולראות מה יקרה? אני למשל הרצתי console.log בלולאה של 1,000,000 ובדפדפן פתחתי שני חלונות. הם התבצעו בזה אחר זה (כל אחד לקח בערך 10-15 שניות).
זה שיש קריאות החוצה שמתבצעות בthread פנימי אחר לא מעניין כל עוד הקוד שאתה כותב רץ בthread אחד וכשהקריאה מהthread החיצוני הפנימי יחזור הוא יבוצע תמיד באותו thread יחיד ראשי.
ככה לפחות אני מבין את הדברים.
 

hadooper

New member
המממ.. די הגיוני.. חייב להודות שעברתי די ברפרוף... אם כי

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

user32

Well-known member
מנהל
אולי

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

choo

Active member
הסיבה לשימוש בחוטים נפרדים עשויה להיות כפולה:

&nbsp
א. נניח ששולחים ומקבלים כמויות נתונים לא זניחות. הטיפול בקבלת הנתונים ושירשור שלהם לבקשת HTTP אחת יכול לקחת זמן מעבד לא זניח. לפיכך, העברה של הפעולות הללו לחוטים נפרדים על ידי המנוע - עשויה להיות הגיונית למדי.
&nbsp
ב. בעבודה עם קבצים בלינוקס, הממשק האסינכרוני סובל מבעיות מימוש שגורמות לכך שבמקרים מסויימים הוא עובר למצב סינכרוני. בנוסף, אי אפשר לבצע המתנה ל-I/O לקבצים באמצעות select, poll וחבריהן - במקום זה צריך להשתמש בממשק של aio - וזה אומר שיש צורך בחוט (אחד או יותר) נפרד כדי להמתין לתוצאות של פעולות קלט/פלט לקבצים.
&nbsp
מעבר לכל זה - צריך להיות ברור שבמידה ויש צורך לבצע פעולות מתואמות בין בקשות שונות - מישהו יצטרך לבצע את התאום הזה. דוגמא פשוטה - אם בקשת http אחת מבצעת כתיבה לקובץ, ובקשת http אחרת מנסה לבצע קריאה מהקובץ - בלי נעילות, התוצאה שתקבל הבקשה הקוראת אינה מוגדרת.
&nbsp
גם בעבודה מול בסיס נתונים - מאחר והשאילתות עשויות להתבצע במקביל - מישהו צריך לבצע סינכרון ונעילות - במקרה הזה - ככל הנראה שהאחריות מועברת לבסיס הנתונים ולקוד ה-sql שמבצע את השאילתות. אפשר להשתמך על מודל ה-ACID של בסיס הנתונים - יש אפליקציות שזה יתאים להן. יש אפליקציות שעבורן זה לא יעבוד נכון.
 

user32

Well-known member
מנהל
בערך מה שחשבתי

 
למעלה