برنامه نویسی چند پردازشی Multi Proccessing

  • مدرس: علی بیگدلی
  • تاریخ انتشار: Jan 06, 2021

چند پردازش در پایتون

این مقاله مقدمه ای مختصر و خلاصه در مورد چند پردازش در زبان برنامه نویسی پایتون است.

چند پردازش چیست؟

چند پردازش به توانایی یک سیستم برای حمایت از بیش از یک پردازنده در یک زمان اشاره دارد. برنامه های کاربردی در یک سیستم چند پردازشی به روش های کوچکتر که به صورت مستقل اجرا می شوند، شکسته می شوند. سیستم عامل این موضوعات را به پردازنده ها برای بهبود عملکرد سیستم اختصاص می دهد.

چرا چند پردازشی؟

یک سیستم کامپیوتری را با یک پردازنده واحد در نظر بگیرید. اگر چندین فرآیند در یک زمان اختصاص داده شود، باید هر کار را مختل کرده و به طور مختصر به یکدیگر متصل شود تا تمامی فرآیندها را ادامه دهد. این وضعیت درست مثل آشپز است که در آشپزخانه تنها کار می کند. او باید چندین کار را انجام دهد مانند پخت، تکان دادن، خمیر خمیر، و غیره بنابراین اصل بر این است: وظایف بیشتری که شما باید در یک بار انجام دهید، سخت تر می شود تا همه آنها را پیگیری کنید و تخصیص زمان را برای هر پردازش تبدیل به یک چالش می کند. در اینجاست که مفهوم چند پردازش ایجاد می شود! یک سیستم چند پردازشی میتواند شامل:

  • چند پردازنده، یعنی یک رایانه با بیش از یک پردازنده مرکزی.
  • پردازنده چند هسته ای، به عنوان مثال یک مولفه محاسباتی با دو یا چند واحد پردازش واقعی مستقل (به نام "هسته").

در اینجا CPU به راحتی می تواند چندین وظیفه را یک بار انجام دهد و هر کار را با استفاده از پردازشگر خود انجام می دهد. این دقیقا همان چیزی است که سرآشپز بهش نیاز دارد یعنی دستیارانی که در آشپزی به وی کمک می کنند. در حال حاضر، آنها می توانند وظایف خود را تقسیم کنند و سرآشپز نیاز به تغییر بین وظایف خود ندارد.

چند پردازش در پایتون

در پایتون، ماژول چند پردازشی شامل API بسیار ساده و بصری برای تقسیم کار بین فرآیندهای چندگانه است. اجازه دهید ما یک مثال ساده را با استفاده از ماژول چند پردازش در نظر بگیریم:  

# importing the multiprocessing module 
import multiprocessing 
  
def print_cube(num): 

    #function to print cube of given num 
    print("Cube: {}".format(num * num * num)) 
  
def print_square(num): 

    #function to print square of given num 
    print("Square: {}".format(num * num)) 
  
if __name__ == "__main__": 
    # creating processes 
    p1 = multiprocessing.Process(target=print_square, args=(10, )) 
    p2 = multiprocessing.Process(target=print_cube, args=(10, )) 
  
    # starting process 1 
    p1.start() 
    # starting process 2 
    p2.start() 
  
    # wait until process 1 is finished 
    p1.join() 
    # wait until process 2 is finished 
    p2.join() 
  
    # both processes finished 
    print("Done!") 

حال می خواهیم که قطعات کد بالا را تفسیر کنیم:

  • در بخش اول قطعه کد اضافه کردن کتابخانه را مشاهده می کنید که با دستور
import multiproccessing

صورت می گیرد.

  • برای ایجاد یک فرآیند، ما یک شیء از کلاس Process ایجاد می کنیم.که آرگومان های زیر را می گیرد: target: تابع باید توسط فرآیند اجرا شود args: استدلال هایی که به تابع هدف منتقل می شوندنکته: سازنده فرایند، بسیاری از استدلال های دیگر را نیز اتخاذ می کند که بعدا مورد بحث قرار می گیرد. در مثال فوق، ما دو فرآیند با توابع هدف مختلف ایجاد کردیم:
p1 = multiprocessing.Process(target=print_square, args=(10, ))
p2 = multiprocessing.Process(target=print_cube, args=(10, ))

 

  • برای شروع یک فرآیند، ما از روش شروع کلاس Process استفاده می کنیم، که در واقع با متدstart()صورت خواهد گرفت.
p1.start()
p2.start()
  • هنگامی که فرآیند شروع می شود، برنامه فعلی نیز اجرا می شود. برای جلوگیری از اجرای برنامه فعلی تا زمانی که فرایند کامل شود، از روش پیوست استفاده می کنیم.
p1.join()
p2.join()
  • در نتیجه، برنامه فعلی برای تکمیل P1 و سپس P2 منتظر می ماند. یکبار آنها را تکمیل می کنند، اظهارات بعدی برنامه فعلی اعدام می شوند.

اجازه دهید برنامه دیگری را در نظر بگیریم تا مفهوم فرآیندهای مختلفی که در همان اسکریپت پایتون در حال اجرا هستند را درک کنیم. در این مثال زیر، شناسه فرآیندهای اجرا شده در توابع هدف را چاپ می کنیم:

# importing the multiprocessing module 
import multiprocessing 
import os 
  
def worker1(): 
    # printing process id 
    print("ID of process running worker1: {}".format(os.getpid())) 
  
def worker2(): 
    # printing process id 
    print("ID of process running worker2: {}".format(os.getpid())) 
  
if __name__ == "__main__": 
    # printing main program process id 
    print("ID of main process: {}".format(os.getpid())) 
  
    # creating processes 
    p1 = multiprocessing.Process(target=worker1) 
    p2 = multiprocessing.Process(target=worker2) 
  
    # starting processes 
    p1.start() 
    p2.start() 
  
    # process IDs 
    print("ID of process p1: {}".format(p1.pid)) 
    print("ID of process p2: {}".format(p2.pid)) 
  
    # wait until processes are finished 
    p1.join() 
    p2.join() 
  
    # both processes finished 
    print("Both processes finished execution!") 
  
    # check if processes are alive 
    print("Process p1 is alive: {}".format(p1.is_alive())) 
    print("Process p2 is alive: {}".format(p2.is_alive())) 

خروجی قطعه کد بالا:

ID of main process: 28628
ID of process running worker1: 29305
ID of process running worker2: 29306
ID of process p1: 29305
ID of process p2: 29306
Both processes finished execution!
Process p1 is alive: False
Process p2 is alive: False

 

  • اسکریپت اصلی پایتون یک شناسه فرآیند متفاوت دارد و ماژول چند پردازش فرایندهای جدید با شناسه های فرایند مختلف را ایجاد می کند، همانطور که ما اشیای فرآیند p1 و p2 را ایجاد می کنیم. در برنامه فوق، از تابع os.getpid () برای دریافت شناسه فرآیند در حال اجرا تابع هدف فعلی استفاده می کنیم. توجه داشته باشید که آن را با شناسه های فرایند p1 و p2 مطابقت می دهیم که با استفاده از ویژگی pid از کلاس Process به دست می آید.
  • هر فرآیند به طور مستقل اجرا می شود و فضای حافظه خود دارد.
  • به محض اجرای تابع هدف، پردازش ها خاتمه می یابد. در برنامه فوق، از روش is_alive از کلاس Process استفاده کردیم تا بررسی کنیم که آیا یک فرایند هنوز فعال است یا نه.

نمودار زیر را در نظر بگیرید تا ببینید چگونه فرآیندهای جدید متفاوت از اسکریپت اصلی پایتون هستند:

ثبت دیدگاه
نام *
ایمیل*
دیدگاه *
0دیدگاه