English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
في الآونة الأخيرة، تعلمت البرمجة المتوازية في بايثون، لذا قمت بتلخيص مختصر للمحاورات المتعددة، والمحاورات المتوازية، والتنفيذ المتوازي والتعاون.
المحاورات المتعددة
المحاورات المتعددة تسمح بوجود عدة أجهزة تحكم داخل عملية واحدة، مما يسمح لعدة وظائف أن تكون نشطة في نفس الوقت، مما يسمح لعدة وظائف بالتشغيل في نفس الوقت. حتى في الحواسيب التي تحتوي على معالج واحد، يمكن تحقيق تأثير تشغيل متوازي للمحاورات من خلال التبديل المستمر بين أوامر المحاورات المختلفة.
المحاورات المتعددة تساوي نظام تشغيل متوازي. النظام المتوازي عادةً يقوم بتشغيل عدة مهام في نفس الوقت. إذا كان يمكن للمهام المختلفة مشاركة الموارد، خاصةً عند محاولة كتابة نفس المتغير في نفس الوقت، فإنه يجب حل مشكلة التوازي، مثل نظام التذاكر المتعدد في نظام القطار: أمران، أمر يتحقق مما إذا كانت التذاكر قد نفدت، وأمر آخر يبيع التذاكر في نوافذ متعددة في نفس الوقت، قد يحدث أن يتم بيع تذاكر غير موجودة.
في الحالات المتوازية، يحدد ترتيب تنفيذ الأوامر النواة. داخل نفس السطر، يتم تنفيذ الأوامر وفقًا للترتيب، ولكن من الصعب تحديد ترتيب تنفيذ الأوامر بين السطرين المختلفين. لذلك، يجب النظر في مشاكل التوازي في السطرين. التوازي (التنسيق) هو السماح لخط واحد فقط بزيارة ميزة معينة في وقت معين.
1- مكتبة thread
2- مكتبة threading
threading.Thread إنشاء سطر.
إضافة قفل متكامل لتحديد ما إذا كان هناك تذاكر متبقية وكتابة التذاكر، لضمان عدم حدوث حالة حيث يتم التحقق من عدم وجود تذاكر متبقية بواسطة سطر واحد، بينما يتم تنفيذ عملية كتابة التذاكر بواسطة سطر آخر.
#! /usr/bin/python #-* coding: utf-8 -* # __author__ ="tyomcat" استيراد threading import time استيراد os دالة booth(tid): العالمية i العالمية lock while True: lock.acquire() إذا كان i e0: i=i-1 print "النافذة:",tid,",عدد التذاكر المتبقية:",i time.sleep(1) else: print "Thread_id",tid,"No more tickets" os._exit(0) lock.release() time.sleep(1) i = 100 lock=threading.Lock() لـ k في النطاق(10): new_thread = threading.Thread(target=booth, args=(k,)) new_thread.start()
ثانيًا، الأكورديت (يُعرف أيضًا بالمتسلسل أو الفيبرونيت)
الأكورديت، التي تختلف عن تقديم السطر المتمرد، هي تقديم تعاوني. الأكورديت هو خط واحد، لكنه يمكنه أن يجعل الكود غير البشري الذي كان سيتم كتابته باستخدام طريقة متوازية + إعادة الطلب، يبدو وكأنه مكتوب بشكل متزامن.
1- يمكن تحقيق الأكورديت في بايثون عن طريق مولدات (مولد).
أولاً، يجب أن يكون لدينا فهم جيد لمولدات وـ yield.
عند استدعاء وظيفة بايثون عادية، عادة ما تبدأ من السطر الأول للوظيفة وتنتهي بـ return الجملة أو الاستثناء أو تنفيذ الوظيفة (يمكن اعتبارها العودة بصمت إلى None).
بمجرد أن أعطت الوظيفة السيطرة إلى الدعاء، فإن ذلك يعني أن الأمور قد انتهت. ولكن في بعض الأحيان يمكن إنشاء وظيفة تنتج سلسلة لـ "حفظ عملها"، وهي ما تسمى بـ "مولدات" (وظائف تستخدم الكلمة المفتاحية yield).
بسبب أن الوظيفة لم تكن تعود كما هو متوقع، يمكنها "إنتاج سلسلة" لأنها لم تعود بالطريقة التقليدية. يعني الكلمة "return" أن الوظيفة تعود بالسيطرة على تنفيذ الكود إلى المكان الذي تم استدعاء الوظيفة منه. أما الكلمة "yield" فإنها تعني أن نقل السيطرة هو مؤقت واختياري، وسنستعيد السيطرة على الوظيفة في المستقبل.
لننظر في مثال المنتج والمستهلك:
#! /usr/bin/python #-* coding: utf-8 -* # __author__ ="tyomcat" import time import sys # المُنتج def produce(l): i=0 while 1: if i < 10: l.append(i) yield i i=i+1 time.sleep(1) else: return # المستهلك def consume(l): p = produce(l) while 1: try: p.next() while len(l) > 0: print l.pop() except StopIteration: sys.exit(0) if __name__ == "__main__": l = [] consume(l)
عندما يتم تنفيذ برنامج produce yield i، يتم إرجاع مولد وإيقاف التنفيذ، وعندما يتم استدعاء p.next() في custom، يعود البرنامج إلى produce yield i لإكمال التنفيذ، ويتم إضافة عنصر إلى l، ثم يتم طباعة l.pop()، حتى يحدث استثناء StopIteration.
2、Stackless Python
3、وحدة greenlet
التنفيذ القائم على greenlet يتفوق على Stackless Python من حيث الأداء، ويكون أبطأ حوالي ضعف Stackless Python، وأسرع تقريبًا بنصف ترتيب من الخيارات الأخرى. في الواقع، greenlet ليست آلية متوازية حقيقية، بل هي التبديل بين قطع الكود المختارة في نفس السلسلة، وتنفيذ "أنت تشغل قليلاً وأنا تشغل قليلاً"، و يجب تحديد متى يتم التبديل وما إلى ذلك عند التبديل.
4、وحدة eventlet
3、المساعدين المتعددين
1、العملية الفرعية (subprocess package)
في python، من خلال حزمة subprocess، يتم إنشاء عملية فرعية وتشغيل برنامج خارجي.
عند استدعاء أوامر النظام، يتم النظر أولاً في مكتبة os. يتم استخدام os.system() و os.popen() لإجراء العمليات. ولكن هاتان الأوامر بسيطتان جدًا، ولا يمكنها إكمال بعض العمليات المعقدة، مثل تقديم إدخال للإجراءات الجارية أو قراءة مخرجات الأوامر، أو تحديد حالة تشغيل الأوامر، أو إدارة تنفيذ العديد من الأوامر بشكل متوازي وما إلى ذلك. في هذه الحالة، يمكن لمحرك subprocess من Popen أن يكمل بفعالية العمليات التي نحتاج إليها.
>>> import subprocess >>> command_line = raw_input() ping -c 10 www.baidu.com >>> args = shlex.split(command_line) >>> p = subprocess.Popen(args)
Use subprocess.PIPE to connect the input and output of multiple subprocesses to form a pipeline (pipe):
import subprocess child1 = subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE) child2 = subprocess.Popen(["wc"], stdin=child1.stdout,stdout=subprocess.PIPE) out = child2.communicate() print(out)
communicate() method reads data from stdout and stderr and inputs it into stdin.
2、multi-processing (multiprocessing package)
(1)、multiprocessing package is the multi-process management package in Python. Similar to threading.Thread, it can use the multiprocessing.Process object to create a process.
The process pool (Process Pool) can create multiple processes.
apply_async(func,args) - Take a process from the process pool to execute func, args are the parameters of func. It will return an AsyncResult object, you can call the get() method on the object to obtain the result.
close() - The process pool will no longer create new processes
join() - wait for all processes in the process pool. It is necessary to call the close() method of Pool first before join.
#! /usr/bin/env python # -*- coding:utf-8 -*- # __author__ == "tyomcat" # "My computer has 4 cpu" from multiprocessing import Pool import os, time def long_time_task(name): print 'Run task %s (%s)...' % (name, os.getpid()) start = time.time() time.sleep(3) end = time.time() print 'Task %s runs %0.2f seconds.' % (name, (end - start)) if __name__=='__main__': print 'Parent process %s.' % os.getpid() p = Pool() for i in range(4): p.apply_async(long_time_task, args=(i,)) print 'Waiting for all subprocesses done...' p.close() p.join() print 'All subprocesses done.'
(2) مشاركة الموارد بين العمليات
باستخدام الذاكرة المشتركة ومساعد الادارة: يمكن استخدام عملية كخادم، وإعداد الادارة لتخزين الموارد فعليًا.
المساعدين الآخرين يمكنهم الوصول إلى Manager عبر المعاملات أو عنوان العنوان، وبعد إنشاء الاتصال، يمكنهم تنفيذ موارد الخادم.
#! /usr/bin/env python # -*- coding:utf-8 -*- # __author__ == "tyomcat" from multiprocessing import Queue,Pool import multiprocessing,time,random def write(q): for value in ['A','B','C','D']: print "Put %s to Queue!" % value q.put(value) time.sleep(random.random()) def read(q,lock): while True: lock.acquire() if not q.empty(): value=q.get(True) print "Get %s from Queue" % value time.sleep(random.random()) else: break lock.release() if __name__ == "__main__": manager=multiprocessing.Manager() q=manager.Queue() p=Pool() lock=manager.Lock() pw=p.apply_async(write,args=(q,)) pr=p.apply_async(read,args=(q,lock)) p.close() p.join() print print "كل البيانات مكتوبة وقد تم قراءتها"
أربعة، متوازية
سواء كانت النواة أو العملية، يتم استخدام نظام السينكرون، مما يؤدي إلى انخفاض كبير في الأداء عند العرقلة، مما يمنع استخدام إمكانيات CPU بكاملها، مما يضيع استثمارات الأجهزة، وأكثر من ذلك، يسبب صلابة البرمجيات، التشابك، لا يمكن قطعه، مما يكون غير مناسب لتوسيع وتغيير في المستقبل.
سواء كان عملية أو نواة، يحتاج كل عرقلة أو تغيير إلى التعرض للدعوة النظامية (system call)، أولاً يجب أن يجري CPU برنامج التشغيل التابع للنظام، ثم يقرر البرنامج التابع للنظام أي عملية (نواة) يجب تشغيلها. يحتاج أيضًا إلى إضافة قفل عند الوصول إلى بعض الأجزاء المشتركة من الكود من قبل العديد من النواة،
معظم الخوادم الم异步 الشائعة حاليًا تعتمد على الحدث (مثل nginx).
في نموذج الحدث التفاعلي الم异步، يتم تحويل العمليات التي تسبب العرقلة إلى عمليات متوازية، والسلسلة الرئيسية مسؤولة عن إطلاق هذه العمليات المتوازية وتعامل نتائجها. نظرًا لأن جميع العمليات التي تسبب العرقلة يتم تحويلها إلى عمليات متوازية، نظريًا معظم وقت السلسلة الرئيسية يتم استخدامه لمعالجة المهام الحقيقية، مما يقلل من وقت التشغيل المتوازي، لذا فإن أداء هذا النموذج عادةً ما يكون جيدًا.
هذا هو نهاية محتوى هذا المقال، نأمل أن يكون قد ساعدكم في التعلم، ونأمل أن تشجعوا دائمًا دليل التعليمات.
بيان: محتوى هذا المقال تم جمعه من الإنترنت، وملكياته للملكيات الأصلية، ومحتوى تم تقديمه من قبل مستخدمي الإنترنت بشكل متعاوني وتقديمهم بأنفسهم، ولا يمتلك هذا الموقع حقوق الملكية، ولا يتم تعديل المحتوى بشكل يدوي، ولا يتحمل هذا الموقع أي مسؤولية قانونية. إذا وجدت محتوى يشتبه في حقوق النسخ، فالرجاء إرسال بريد إلكتروني إلى: notice#oldtoolbag.com (عند إرسال البريد الإلكتروني، يرجى استبدال '#' ب '@') لإبلاغنا، وتقديم الدليل، وإذا تم التحقق من ذلك، فإن هذا الموقع سيقوم بإزالة المحتوى المشبوه بشكل فوري.