Python Language
पायथन संगति
खोज…
टिप्पणियों
पायथन डेवलपर्स ने सुनिश्चित किया कि threading
और multiprocessing
बीच एपीआई समान है ताकि प्रोग्रामर के लिए दो वेरिएंट के बीच स्विच करना आसान हो।
सूत्रण मॉड्यूल
from __future__ import print_function
import threading
def counter(count):
while count > 0:
print("Count value", count)
count -= 1
return
t1 = threading.Thread(target=countdown,args=(10,))
t1.start()
t2 = threading.Thread(target=countdown,args=(20,))
t2.start()
सीपीथॉन जैसे पायथन के कुछ कार्यान्वयनों में, जीआईएल, या जी लोबाल I न्टरप्टर एल ock के रूप में जाना जाता है का उपयोग करने के कारण थ्रेड्स का उपयोग करके सही समानता नहीं प्राप्त की जाती है।
यहां पाइथन कॉन्सेप्ट का एक उत्कृष्ट अवलोकन दिया गया है:
डेविड बेज़ले (YouTube) द्वारा पाइथन कॉन्सेप्ट्री
मल्टीप्रोसेसिंग मॉड्यूल
from __future__ import print_function
import multiprocessing
def countdown(count):
while count > 0:
print("Count value", count)
count -= 1
return
if __name__ == "__main__":
p1 = multiprocessing.Process(target=countdown, args=(10,))
p1.start()
p2 = multiprocessing.Process(target=countdown, args=(20,))
p2.start()
p1.join()
p2.join()
यहां, प्रत्येक फ़ंक्शन को एक नई प्रक्रिया में निष्पादित किया जाता है। चूंकि पायथन वीएम का एक नया उदाहरण कोड चला रहा है, इसलिए कोई GIL
नहीं है और आपको कई कोर पर चलने वाली समानता मिलती है।
Process.start
विधि की शुरूआत इस नई प्रक्रिया और समारोह में पारित चलाने target
तर्क के साथ तर्क args
। Process.join
मेथड p1
और p2
प्रक्रियाओं के निष्पादन की समाप्ति की प्रतीक्षा करता है।
नई प्रक्रियाओं को अजगर और प्लेटफॉर्म के संस्करण के आधार पर अलग-अलग लॉन्च किया जाता है, जिस पर कोड चल रहा है जैसे :
- नई प्रक्रिया बनाने के लिए विंडोज
spawn
का उपयोग करता है। - 3.3 से पहले यूनिक्स सिस्टम और संस्करण के साथ,
fork
का उपयोग करके प्रक्रियाएं बनाई जाती हैं।
ध्यान दें कि यह विधि कांटा के POSIX उपयोग का सम्मान नहीं करती है और इस तरह अप्रत्याशित व्यवहार की ओर ले जाती है, खासकर जब अन्य मल्टीप्रोसेसिंग पुस्तकालयों के साथ बातचीत। - यूनिक्स सिस्टम और संस्करण 3.4+ के साथ, आप अपने प्रोग्राम की शुरुआत में
multiprocessing.set_start_method
forkserver
का उपयोग करकेfork
,forkserver
याspawn
साथ नई प्रक्रियाओं को शुरू करना चुन सकते हैं।forkserver
औरspawn
विधियाँ forking की तुलना में धीमी हैं लेकिन कुछ अनपेक्षित व्यवहारों से बचें।
POSIX कांटा उपयोग :
एक मल्टीथ्रेडेड प्रोग्राम में कांटे के बाद, बच्चा सुरक्षित रूप से केवल async-signal-safe फ़ंक्शन को कॉल कर सकता है, जब तक कि यह निष्पादित नहीं हो जाता।
( देखें )
कांटा का उपयोग करते हुए, सभी मौजूदा म्यूटेक्स के लिए एक ही राज्य के साथ एक नई प्रक्रिया शुरू की जाएगी, लेकिन केवल MainThread
को लॉन्च किया जाएगा। यह असुरक्षित है क्योंकि यह दौड़ की स्थिति पैदा कर सकता है जैसे :
- यदि आप
MainThread
मेंLock
उपयोग करते हैं और इसे किसी अन्य थ्रेड को पास करते हैं, जो किसी बिंदु पर लॉक करने के लिए माना जाता है। यदिfork
एक साथ उत्पन्न होता है, तो नई प्रक्रिया एक बंद ताला के साथ शुरू होगी जो कभी भी जारी नहीं होगी क्योंकि इस नई प्रक्रिया में दूसरा धागा मौजूद नहीं है।
वास्तव में, इस तरह के व्यवहार को शुद्ध अजगर में नहीं होना चाहिए क्योंकि multiprocessing
इसे ठीक से संभालती है लेकिन यदि आप अन्य पुस्तकालय के साथ बातचीत कर रहे हैं, तो इस तरह का व्यवहार आपके सिस्टम के दुर्घटना के लिए अग्रणी हो सकता है (उदाहरण के लिए macOS के साथ त्वरित / त्वरित)।
मल्टीप्रोसेसिंग प्रक्रियाओं के बीच डेटा पास करना
क्योंकि डेटा संवेदनशील होता है जब दो थ्रेड्स के बीच निपटा जाता है (लगता है समवर्ती पढ़ा और समवर्ती लेखन एक दूसरे के साथ संघर्ष कर सकता है, दौड़ की स्थिति पैदा कर सकता है), थ्रेड के बीच डेटा के आगे और पीछे की सुविधा के लिए अद्वितीय वस्तुओं का एक सेट बनाया गया था। किसी भी वास्तव में परमाणु संचालन का उपयोग थ्रेड्स के बीच किया जा सकता है, लेकिन क्यू के साथ चिपकना हमेशा सुरक्षित होता है।
import multiprocessing
import queue
my_Queue=multiprocessing.Queue()
#Creates a queue with an undefined maximum size
#this can be dangerous as the queue becomes increasingly large
#it will take a long time to copy data to/from each read/write thread
ज्यादातर लोग सुझाव देंगे कि कतार का उपयोग करते समय, हमेशा कतार डेटा को एक कोशिश में रखें: सिवाय: खाली का उपयोग करने के बजाय ब्लॉक करें। हालाँकि, ऐसे अनुप्रयोगों के लिए जहां कोई फर्क नहीं पड़ता है अगर आप एक स्कैन चक्र छोड़ते हैं (डेटा कतार में रखा जा सकता है, जबकि यह कतार से राज्यों को फ़्लिप कर रहा है। queue.Empty==True
है। queue.Empty==False
) यह आमतौर पर पढ़ने के लिए बेहतर होता है। और क्या मैं एक iftry ब्लॉक कहते हैं, में पहुँच लिखें, क्योंकि एक 'अगर' बयान तकनीकी रूप से अपवाद को पकड़ने की तुलना में अधिक प्रदर्शन है।
import multiprocessing
import queue
'''Import necessary Python standard libraries, multiprocessing for classes and queue for the queue exceptions it provides'''
def Queue_Iftry_Get(get_queue, default=None, use_default=False, func=None, use_func=False):
'''This global method for the Iftry block is provided for it's reuse and
standard functionality, the if also saves on performance as opposed to catching
the exception, which is expencive.
It also allows the user to specify a function for the outgoing data to use,
and a default value to return if the function cannot return the value from the queue'''
if get_queue.empty():
if use_default:
return default
else:
try:
value = get_queue.get_nowait()
except queue.Empty:
if use_default:
return default
else:
if use_func:
return func(value)
else:
return value
def Queue_Iftry_Put(put_queue, value):
'''This global method for the Iftry block is provided because of its reuse
and
standard functionality, the If also saves on performance as opposed to catching
the exception, which is expensive.
Return True if placing value in the queue was successful. Otherwise, false'''
if put_queue.full():
return False
else:
try:
put_queue.put_nowait(value)
except queue.Full:
return False
else:
return True