Whatsup - לינוקס, תוכנה חופשית וקוד פתוח בעברית

תיכנות בלינוקס - ריצה מקבילית בפייתון: threading או multiprocessing

COM64 - 19/02/2021 - 11:49
נושא ההודעה: ריצה מקבילית בפייתון: threading או multiprocessing
אני כותב קוד שבצע מספר רב של פעולות שמבחינת משאבי מיחשוב דורשות מעט מאד אך זמן הביצוע של כל אחת מגיע לעשרות שניות. אין קשר או תלות בין הפעולות.

אני רוצה להריץ את כולן במקביל, מה ההבדלים בין threading ל-multiprocessing? האם יש עדיפות לאחת מהן כשמה שנדרש לביצוע הוא חיבור לציוד רשת מרוחק, הרצת מספר פקודות על הציוד ואיסוף של המידע שהתקבל לתוך רשימה או קובץ json?

תודה !
COM64 - 19/02/2021 - 15:36
נושא ההודעה:
מוסיף לשאלה מעל, אני מנסה כרגע לעבוד עם multiprocessing ומתקשה להבין איך אני מחזיר ערך לפונקציה שהריצה את ה-process?

לדוגמה:
[code]
def return_multi(some_value):
return some_value*2

jobs = []
for i in range(5):
p = multiprocessing.Process(target=return_multi, args=(i,))
jobs.append(p)
p.start()

[code][/code]

קראתי קצת על shared memory ו-server process אבל אני שואל את עצמי (ואת חברי הפורום) האם ישנה דרך "רגילה" לקרא את הערך שמוחזר מכל instance שרץ?

האם בשימוש ב-threading ישנה אפשרות כזו?

או שאופן העבודה במקביל לא מאפשר את זה.
Anonymous - 19/02/2021 - 23:03
נושא ההודעה:
תתחיל מ-threading זה הפתרון שיש לו פחות overhead ויותר מתאים למה שאתה מתאר. אם המהירות מוגבלת בעיקר בגלל תקשורת שמחכה לצד השני להגיב אז יש עוד פתרון והוא event driven או מה שנקרא reactive שמאפשר לעשות את הפעולות במקביל בלי שנדרש thread נפרד לכל פעולה.
Anonymous - 20/02/2021 - 02:01
נושא ההודעה: Re: ריצה מקבילית בפייתון: threading או multiprocessing
COM64 :
אני כותב קוד שבצע מספר רב של פעולות שמבחינת משאבי מיחשוב דורשות מעט מאד אך זמן הביצוע של כל אחת מגיע לעשרות שניות. אין קשר או תלות בין הפעולות.

אני רוצה להריץ את כולן במקביל, מה ההבדלים בין threading ל-multiprocessing? האם יש עדיפות לאחת מהן כשמה שנדרש לביצוע הוא חיבור לציוד רשת מרוחק, הרצת מספר פקודות על הציוד ואיסוף של המידע שהתקבל לתוך רשימה או קובץ json?

תודה !

כלל אצבע - תקודד עם threads (שרצים על אותו מעבד כמו האבא שהריץ אותם), תסתכל ב top - אם ניצול מעבד נשאר על 100% לאורך זמן, אולי כדאי לשקול שימוש במעבדים האחרים, ז"א multi-processing.
COM64 - 20/02/2021 - 08:58
נושא ההודעה:
תודה על שתי התגובות.

אז חזרתי ל-threads והתחלתי ללמוד את נושא ה-event driven.
המעבד ירוץ בעומס נמוך לפחות בתחילת הדרך, רוב הזמן הוא פשוט ממתין לציוד שיחזיר תשובה.
Anonymous - 21/02/2021 - 15:49
נושא ההודעה: שאלה של מי שלא נגע בפיתון בעשר שנים אחרונות
האם יש עדיין הגיון להשתמש בprocesses כמו פעם ותורים או פשוט לכתוב א-סינכרוני?

קוד:

import asyncio

async def myfunc():
    return 42

כלומר 1ץ האם לא ניתן להניח שא-סינכרוני בפיתון הוא לא כמו javascript והוא רץ ב theread נפרד?
2. כמו ב c++ הוא יודיע אוטומטית כמה מעבדים על המכונה ויודיע לפתוח בו זמנית את הכמות הנידרשת?

- אני באמת לא יודיע python ולא נגעתי בשפה ב 10 שנים אחרונות....
Anonymous - 21/02/2021 - 15:58
נושא ההודעה:
בהמשך ל 1 ו- 2 ממיקודם..
3. גם תכנות א-סינכרוני יפתור בעיות של shared memory מה שב c#/c++ דורש mux וכאלה..?
Anonymous - 21/02/2021 - 18:25
נושא ההודעה:
python פשוט לא תומכת ב multi-threadings שמשתמש ב multi-core. כשאתה יוצר thread בפייתון, הוא תמיד רץ על אותו מעבד כמו האבא. זה מה יש.

מזכיר לי שורת הערה שראיתי בקוד רלוונטי, שבו כתוב (תרגום עקום): "אני מפחד לחפש בגוגל איך לפתור את הבעיה - כיצד הורה יכול להרוג את הילד..." חוש הומור של מפתחים Twisted Evil
oz_nahum - 24/02/2021 - 23:42
נושא ההודעה:
Anonymous :
python פשוט לא תומכת ב multi-threadings שמשתמש ב multi-core. כשאתה יוצר thread בפייתון, הוא תמיד רץ על אותו מעבד כמו האבא. זה מה יש.

מזכיר לי שורת הערה שראיתי בקוד רלוונטי, שבו כתוב (תרגום עקום): "אני מפחד לחפש בגוגל איך לפתור את הבעיה - כיצד הורה יכול להרוג את הילד..." חוש הומור של מפתחים Twisted Evil


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

השאלה המקורית אומרת שהקוד מחכה לתשובה, במקרים כאלו - Thread שתופס ליבה של המעבד כמו בג'אווה זה פשוט בזבוז. Python Threads מספיקים בהחלט רב.
בהפשטה רבה מאוד - Thread בשפות תכנות אחרות נקרא Process בפייתון.
אבל כמו שאמרתי לא צריך את זה ב-99% כשלא מדובר בפעולות חשוב אינטנסיביות.
במקרה המדובר אפשר גם להשתמש ב-Async.
queency - 25/02/2021 - 20:50
נושא ההודעה:
אם אתה שואל אותי THREAD זה תכנות לקוי.
אני בכלל לא מדבר על הDEBUG שיהיה סיוט.

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

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

עדיף לבנות רכיב חיצוני שעושה POOL ומשתמש אולי ב QUEUE
או שמייצר INDEX לכל תהליך שפונה אליו .

אם תהיה יותר פרטני יביאו לך רעיונות לפתרון שאולי בכלל לא חשבת
עליהם ומפשטים את הקוד.
COM64 - 26/02/2021 - 08:37
נושא ההודעה:
queency :
אם תהיה יותר פרטני יביאו לך רעיונות לפתרון שאולי בכלל לא חשבת
עליהם ומפשטים את הקוד.


ניקח דוגמה פשוטה, אני כותב קוד שמבצע SSH לסוויץ, מריץ עליו פקודה ואת הפלט אני מכניס ל-Dictionary.
החיבור ב-SSH לוקח כמה שניות כשכל השאר מסתיים בהרבה פחות משניה. אני צריך להריץ את הפקודה על אלפי סוויצים ולכן חייב להריץ במקביל.

לצורך התרגול, נניח שלא ניתן להשתמש בפתרון חיבור אחר וחובה להשתמש ב-SSH.

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

כבר חשבתי להשתמש בבסיס נתונים כלשהו, להכניס את הפלט ל-json ולשמור בבסיס הנתונים. כך אין לי התעסקות עם החזרה של הפלט לפרוסס האבא שקרא לכל הפרוססים במקביל.
Anonymous - 26/02/2021 - 08:56
נושא ההודעה:
מה לגבי שימוש במשהו קיים במקום להמציא את הגלגל
https://parallel-ssh.readthedocs.io
Anonymous - 26/02/2021 - 14:05
נושא ההודעה:
אם יש צורך בניהול מקביל של פעולות שונות ולא רק ssh אז - שרת ג׳ובים

https://edgeguides.rubyonrails.org/active_job_basics.html

או משהוא דומה שיש ב python

כי אחרת יש עוד דברים שלא חשבתה עליהם (מה אם הפרוסס מת באופן לא צפוי ועוד...)
COM64 - 26/02/2021 - 18:00
נושא ההודעה:
Anonymous :
מה לגבי שימוש במשהו קיים במקום להמציא את הגלגל
https://parallel-ssh.readthedocs.io


נראה שזה לא עובד עם פייתון 3.7 כשיש צורך לבצע לוגין ב-SSH עם שם משתמש וסיסמה. יש באג על זה מ-2018 והגירסה העדכנית ביותר גם מ-2018. במקרה שלי לא קיימת אפשרות להשתמש במפתחות.

ממשיך לבדוק אם יש לזה פתרון כלשהו היות שזה נראה לפחות לשלב בו אני נמצא פתרון מספק.
COM64 - 26/02/2021 - 18:02
נושא ההודעה:
Anonymous :
אם יש צורך בניהול מקביל של פעולות שונות ולא רק ssh אז - שרת ג׳ובים

https://edgeguides.rubyonrails.org/active_job_basics.html

או משהוא דומה שיש ב python

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


בשלב הנוכחי אני רוצה רק לבדוק היתכנות ולכן חיפשתי משהו שיהיה פשוט ליישום. צודק לגבי נושאים רבים שעדיין אני לא חושב עליהם וידרשו יותר מחיבור והמתנה למענה.
Anonymous - 26/02/2021 - 21:41
נושא ההודעה:
ציטוט:
נראה שזה לא עובד עם פייתון 3.7 כשיש צורך לבצע לוגין ב-SSH עם שם משתמש וסיסמה. יש באג על זה מ-2018 והגירסה העדכנית ביותר גם מ-2018. במקרה שלי לא קיימת אפשרות להשתמש במפתחות

אפשר לשאול איפה אתה רואה את זה?
אני רואה גרסאות מ-2021 והקוד ב-github מתוחזק עם תיקונים ושינויים שוטפים.
COM64 - 27/02/2021 - 10:31
נושא ההודעה:
Anonymous :
ציטוט:
נראה שזה לא עובד עם פייתון 3.7 כשיש צורך לבצע לוגין ב-SSH עם שם משתמש וסיסמה. יש באג על זה מ-2018 והגירסה העדכנית ביותר גם מ-2018. במקרה שלי לא קיימת אפשרות להשתמש במפתחות

אפשר לשאול איפה אתה רואה את זה?
אני רואה גרסאות מ-2021 והקוד ב-github מתוחזק עם תיקונים ושינויים שוטפים.


צודק, טעיתי אחרי שראיתי את גרסה 1.6.0 באתר הזה https://parallel-ssh.org/. בפועל אני רואה שמותקנת אצלי גירסה 2.3.1

דוגמה לקוד שאני מנסה להריץ:

קוד:
from pssh.clients import ParallelSSHClient
hosts = [‘10.0.0.204’, ‘10.0.0.205’]
client = ParallelSSHClient(hosts, user = ‘admin’, password = ‘123456’)
client.run_command(‘show run’)


והודעת השגיאה:

קוד:
Traceback (most recent call last):
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/base/single.py”, line 208, in _auth_retry
self.auth()
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/base/single.py”, line 355, in auth
self._password_auth()
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/native/single.py”, line 229, in _password_auth
self.session.userauth_password(self.user, self.password)
File “ssh2/session.pyx”, line 321, in ssh2.session.Session.userauth_password
File “ssh2/utils.pyx”, line 166, in ssh2.utils.handle_error_codes
ssh2.exceptions.AuthenticationError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/base/single.py”, line 208, in _auth_retry
self.auth()
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/base/single.py”, line 355, in auth
self._password_auth()
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/native/single.py”, line 229, in _password_auth
self.session.userauth_password(self.user, self.password)
File “ssh2/session.pyx”, line 321, in ssh2.session.Session.userauth_password
File “ssh2/utils.pyx”, line 166, in ssh2.utils.handle_error_codes
ssh2.exceptions.AuthenticationError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/base/single.py”, line 208, in _auth_retry
self.auth()
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/base/single.py”, line 355, in auth
self._password_auth()
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/native/single.py”, line 229, in _password_auth
self.session.userauth_password(self.user, self.password)
File “ssh2/session.pyx”, line 321, in ssh2.session.Session.userauth_password
File “ssh2/utils.pyx”, line 166, in ssh2.utils.handle_error_codes
ssh2.exceptions.AuthenticationError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “”, line 1, in
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/native/parallel.py”, line 217, in run_command
return_list=return_list, read_timeout=read_timeout if read_timeout else timeout,
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/base/parallel.py”, line 198, in run_command
return_list=return_list)
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/base/parallel.py”, line 204, in _get_output_from_cmds
finished = joinall(_cmds, raise_error=True)
File “src/gevent/greenlet.py”, line 849, in gevent._greenlet.joinall
File “src/gevent/greenlet.py”, line 865, in gevent._greenlet.joinall
File “src/gevent/greenlet.py”, line 312, in gevent._greenlet.Greenlet._raise_exception
File “/usr/lib/python3/dist-packages/gevent/_compat.py”, line 47, in reraise
raise value.with_traceback(tb)
File “src/gevent/greenlet.py”, line 716, in gevent._greenlet.Greenlet.run
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/base/parallel.py”, line 216, in _get_output_from_greenlet
raise ex
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/base/parallel.py”, line 209, in _get_output_from_greenlet
host_out = cmd.get()
File “src/gevent/greenlet.py”, line 633, in gevent._greenlet.Greenlet.get
File “src/gevent/greenlet.py”, line 312, in gevent._greenlet.Greenlet._raise_exception
File “/usr/lib/python3/dist-packages/gevent/_compat.py”, line 47, in reraise
raise value.with_traceback(tb)
File “src/gevent/greenlet.py”, line 716, in gevent._greenlet.Greenlet.run
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/base/parallel.py”, line 285, in _run_command
raise ex
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/base/parallel.py”, line 277, in _run_command
_client = self._make_ssh_client(host_i, host)
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/native/parallel.py”, line 252, in _make_ssh_client
identity_auth=self.identity_auth,
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/native/single.py”, line 129, in init
identity_auth=identity_auth)
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/base/single.py”, line 195, in init
self._init()
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/base/single.py”, line 200, in _init
self._auth_retry()
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/base/single.py”, line 212, in _auth_retry
return self._auth_retry(retries=retries+1)
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/base/single.py”, line 212, in _auth_retry
return self._auth_retry(retries=retries+1)
File “/usr/local/lib/python3.7/dist-packages/pssh/clients/base/single.py”, line 214, in _auth_retry
raise AuthenticationError(msg, self.host, self.port, ex)
pssh.exceptions.AuthenticationError: (‘Authentication error while connecting to %s:%s - %s’, ‘10.0.0.204’, 22, AuthenticationError())

COM64 - 27/02/2021 - 11:51
נושא ההודעה:
OK נראה שהבעיה ב"צד השני". כל הניסיונות שלי היו מול סוויצים וירטואלים של אריסטה בגירסה vEOS 4.25.1F

לעומת זאת, מול דביאן וסוויץ של סיסקו זה עובד.

מוריד גירסה אחרונה של אריסטה וסיסקו ואעדכן.
mksoft - 28/02/2021 - 10:24
נושא ההודעה:
אם העבודה היא חיבורי ssh מרובים, ואין לך בעיה לעבוד async הייתי ממליץ לך על AsyncSSH.
כל הזמנים הם GMT + 2 שעות