పైథాన్ మల్టీప్రాసెసింగ్ మాడ్యూల్కు ఒక సమగ్ర గైడ్. సమాంతర ఎగ్జిక్యూషన్ కోసం ప్రాసెస్ పూల్స్ మరియు సమర్థవంతమైన డేటా షేరింగ్ కోసం షేర్డ్ మెమరీ నిర్వహణపై దృష్టి సారిస్తుంది. మీ పైథాన్ అప్లికేషన్లను పనితీరు మరియు స్కేలబిలిటీ కోసం ఆప్టిమైజ్ చేయండి.
పైథాన్ మల్టీప్రాసెసింగ్: ప్రాసెస్ పూల్స్ మరియు షేర్డ్ మెమరీపై నైపుణ్యం
పైథాన్, దాని చక్కదనం మరియు బహుముఖ ప్రజ్ఞ ఉన్నప్పటికీ, గ్లోబల్ ఇంటర్ప్రెటర్ లాక్ (GIL) కారణంగా తరచుగా పనితీరులో అడ్డంకులను ఎదుర్కొంటుంది. GIL ఏ సమయంలోనైనా పైథాన్ ఇంటర్ప్రెటర్పై ఒకే థ్రెడ్కు నియంత్రణను అనుమతిస్తుంది. ఈ పరిమితి CPU-బౌండ్ టాస్క్లను గణనీయంగా ప్రభావితం చేస్తుంది, మల్టీథ్రెడ్ అప్లికేషన్లలో నిజమైన సమాంతరతను అడ్డుకుంటుంది. ఈ సవాలును అధిగమించడానికి, పైథాన్ యొక్క multiprocessing మాడ్యూల్ బహుళ ప్రక్రియలను ఉపయోగించడం ద్వారా ఒక శక్తివంతమైన పరిష్కారాన్ని అందిస్తుంది, GILను సమర్థవంతంగా తప్పించుకొని నిజమైన సమాంతర ఎగ్జిక్యూషన్ను ప్రారంభిస్తుంది.
ఈ సమగ్ర గైడ్ పైథాన్ మల్టీప్రాసెసింగ్ యొక్క ప్రధాన అంశాలను, ముఖ్యంగా ప్రాసెస్ పూల్స్ మరియు షేర్డ్ మెమరీ నిర్వహణపై దృష్టి సారిస్తుంది. ప్రాసెస్ పూల్స్ సమాంతర టాస్క్ ఎగ్జిక్యూషన్ను ఎలా సులభతరం చేస్తాయో మరియు షేర్డ్ మెమరీ ప్రక్రియల మధ్య సమర్థవంతమైన డేటా షేరింగ్ను ఎలా సులభతరం చేస్తుందో మనం అన్వేషిస్తాము, మీ మల్టీ-కోర్ ప్రాసెసర్ల పూర్తి సామర్థ్యాన్ని అన్లాక్ చేస్తాము. మీ పైథాన్ అప్లికేషన్లను పనితీరు మరియు స్కేలబిలిటీ కోసం ఆప్టిమైజ్ చేయడానికి అవసరమైన జ్ఞానం మరియు నైపుణ్యాలతో మిమ్మల్ని సన్నద్ధం చేయడానికి మేము ఉత్తమ పద్ధతులు, సాధారణ ఆపదలు, మరియు ఆచరణాత్మక ఉదాహరణలను కవర్ చేస్తాము.
మల్టీప్రాసెసింగ్ అవసరాన్ని అర్థం చేసుకోవడం
సాంకేతిక వివరాలలోకి వెళ్లే ముందు, కొన్ని సందర్భాల్లో మల్టీప్రాసెసింగ్ ఎందుకు అవసరమో అర్థం చేసుకోవడం చాలా ముఖ్యం. ఈ క్రింది పరిస్థితులను పరిగణించండి:
- CPU-బౌండ్ టాస్క్లు: CPU ప్రాసెసింగ్పై ఎక్కువగా ఆధారపడే ఆపరేషన్లు, ఉదాహరణకు ఇమేజ్ ప్రాసెసింగ్, సంఖ్యా గణనలు, లేదా సంక్లిష్ట సిమ్యులేషన్లు, GIL ద్వారా తీవ్రంగా పరిమితం చేయబడతాయి. మల్టీప్రాసెసింగ్ ఈ టాస్క్లను బహుళ కోర్లలో పంపిణీ చేయడానికి అనుమతిస్తుంది, గణనీయమైన వేగవంతం సాధిస్తుంది.
- పెద్ద డేటాసెట్లు: పెద్ద డేటాసెట్లతో వ్యవహరించేటప్పుడు, ప్రాసెసింగ్ పనిభారాన్ని బహుళ ప్రక్రియలలో పంపిణీ చేయడం ద్వారా ప్రాసెసింగ్ సమయాన్ని నాటకీయంగా తగ్గించవచ్చు. స్టాక్ మార్కెట్ డేటా లేదా జన్యు శ్రేణులను విశ్లేషించడం ఊహించుకోండి - మల్టీప్రాసెసింగ్ ఈ టాస్క్లను నిర్వహించదగినదిగా చేస్తుంది.
- స్వతంత్ర టాస్క్లు: మీ అప్లికేషన్లో బహుళ స్వతంత్ర టాస్క్లను ఏకకాలంలో అమలు చేయడం ఉంటే, మల్టీప్రాసెసింగ్ వాటిని సమాంతరంగా చేయడానికి ఒక సహజ మరియు సమర్థవంతమైన మార్గాన్ని అందిస్తుంది. బహుళ క్లయింట్ అభ్యర్థనలను ఒకేసారి నిర్వహించే వెబ్ సర్వర్ లేదా సమాంతరంగా వివిధ డేటా సోర్స్లను ప్రాసెస్ చేసే డేటా పైప్లైన్ గురించి ఆలోచించండి.
అయితే, మల్టీప్రాసెసింగ్ దాని స్వంత సంక్లిష్టతలను, అనగా ఇంటర్-ప్రాసెస్ కమ్యూనికేషన్ (IPC) మరియు మెమరీ నిర్వహణ వంటివి పరిచయం చేస్తుందని గమనించడం ముఖ్యం. మల్టీప్రాసెసింగ్ మరియు మల్టీథ్రెడింగ్ మధ్య ఎంపిక చేయడం అనేది చేతిలో ఉన్న పని స్వభావంపై ఎక్కువగా ఆధారపడి ఉంటుంది. I/O-బౌండ్ టాస్క్లు (ఉదా., నెట్వర్క్ అభ్యర్థనలు, డిస్క్ I/O) తరచుగా asyncio వంటి లైబ్రరీలను ఉపయోగించి మల్టీథ్రెడింగ్ నుండి ఎక్కువ ప్రయోజనం పొందుతాయి, అయితే CPU-బౌండ్ టాస్క్లు సాధారణంగా మల్టీప్రాసెసింగ్కు బాగా సరిపోతాయి.
ప్రాసెస్ పూల్స్ పరిచయం
ప్రాసెస్ పూల్ అనేది ఏకకాలంలో టాస్క్లను అమలు చేయడానికి అందుబాటులో ఉన్న వర్కర్ ప్రక్రియల సమాహారం. multiprocessing.Pool క్లాస్ ఈ వర్కర్ ప్రక్రియలను నిర్వహించడానికి మరియు వాటి మధ్య టాస్క్లను పంపిణీ చేయడానికి ఒక అనుకూలమైన మార్గాన్ని అందిస్తుంది. ప్రాసెస్ పూల్స్ ఉపయోగించడం ద్వారా, వ్యక్తిగత ప్రక్రియలను మాన్యువల్గా నిర్వహించాల్సిన అవసరం లేకుండా టాస్క్లను సమాంతరంగా చేయడం సులభం అవుతుంది.
ప్రాసెస్ పూల్ను సృష్టించడం
ఒక ప్రాసెస్ పూల్ను సృష్టించడానికి, మీరు సాధారణంగా సృష్టించాల్సిన వర్కర్ ప్రక్రియల సంఖ్యను నిర్దేశిస్తారు. సంఖ్య నిర్దేశించకపోతే, సిస్టమ్లోని CPUల సంఖ్యను నిర్ణయించడానికి multiprocessing.cpu_count() ఉపయోగించబడుతుంది మరియు అంత మంది ప్రక్రియలతో ఒక పూల్ సృష్టించబడుతుంది.
from multiprocessing import Pool, cpu_count
def worker_function(x):
# Perform some computationally intensive task
return x * x
if __name__ == '__main__':
num_processes = cpu_count() # Get the number of CPUs
with Pool(processes=num_processes) as pool:
results = pool.map(worker_function, range(10))
print(results)
వివరణ:
- మేము
multiprocessingమాడ్యూల్ నుండిPoolక్లాస్ మరియుcpu_countఫంక్షన్ను దిగుమతి చేసుకుంటాము. - మేము ఒక గణనాయోగ్యమైన టాస్క్ (ఈ సందర్భంలో, ఒక సంఖ్యను వర్గం చేయడం) చేసే
worker_functionను నిర్వచిస్తాము. if __name__ == '__main__':బ్లాక్ లోపల (స్క్రిప్ట్ నేరుగా రన్ చేసినప్పుడు మాత్రమే కోడ్ అమలు అయ్యేలా చూస్తుంది), మేముwith Pool(...) as pool:స్టేట్మెంట్ను ఉపయోగించి ఒక ప్రాసెస్ పూల్ను సృష్టిస్తాము. ఇది బ్లాక్ నుండి నిష్క్రమించినప్పుడు పూల్ సరిగ్గా ముగిసిపోతుందని నిర్ధారిస్తుంది.- మేము
pool.map()పద్ధతిని ఉపయోగించిworker_functionనుrange(10)లోని ప్రతి అంశానికి వర్తింపజేస్తాము.map()పద్ధతి పూల్లోని వర్కర్ ప్రక్రియల మధ్య టాస్క్లను పంపిణీ చేసి, ఫలితాల జాబితాను తిరిగి ఇస్తుంది. - చివరగా, మేము ఫలితాలను ప్రింట్ చేస్తాము.
map(), apply(), apply_async(), మరియు imap() పద్ధతులు
Pool క్లాస్ వర్కర్ ప్రక్రియలకు టాస్క్లను సమర్పించడానికి అనేక పద్ధతులను అందిస్తుంది:
map(func, iterable):iterableలోని ప్రతి ఐటమ్కుfuncను వర్తింపజేస్తుంది, అన్ని ఫలితాలు సిద్ధమయ్యే వరకు బ్లాక్ చేస్తుంది. ఫలితాలు ఇన్పుట్ ఇటరబుల్ వలె అదే క్రమంలో ఒక జాబితాలో తిరిగి ఇవ్వబడతాయి.apply(func, args=(), kwds={}): ఇచ్చిన ఆర్గ్యుమెంట్లతోfuncను పిలుస్తుంది. ఫంక్షన్ పూర్తయ్యే వరకు ఇది బ్లాక్ చేస్తుంది మరియు ఫలితాన్ని తిరిగి ఇస్తుంది. సాధారణంగా, బహుళ టాస్క్ల కోసంapplymapకంటే తక్కువ సమర్థవంతమైనది.apply_async(func, args=(), kwds={}, callback=None, error_callback=None):applyయొక్క నాన్-బ్లాకింగ్ వెర్షన్. ఇది ఒకAsyncResultఆబ్జెక్ట్ను తిరిగి ఇస్తుంది. ఫలితాన్ని తిరిగి పొందడానికి మీరుAsyncResultఆబ్జెక్ట్ యొక్కget()పద్ధతిని ఉపయోగించవచ్చు, ఇది ఫలితం అందుబాటులోకి వచ్చే వరకు బ్లాక్ చేస్తుంది. ఇది కాల్బ్యాక్ ఫంక్షన్లకు కూడా మద్దతు ఇస్తుంది, ఫలితాలను అసమకాలికంగా ప్రాసెస్ చేయడానికి మిమ్మల్ని అనుమతిస్తుంది. ఫంక్షన్ ద్వారా ఎదురయ్యే మినహాయింపులను నిర్వహించడానికిerror_callbackను ఉపయోగించవచ్చు.imap(func, iterable, chunksize=1):mapయొక్క లేజీ వెర్షన్. ఇది అన్ని టాస్క్లు పూర్తయ్యే వరకు వేచి ఉండకుండా, ఫలితాలు అందుబాటులోకి వచ్చినప్పుడు వాటిని ఇచ్చే ఒక ఇటరేటర్ను తిరిగి ఇస్తుంది.chunksizeఆర్గ్యుమెంట్ ప్రతి వర్కర్ ప్రక్రియకు సమర్పించబడిన పని భాగాల పరిమాణాన్ని నిర్దేశిస్తుంది.imap_unordered(func, iterable, chunksize=1):imapలాంటిదే, కానీ ఫలితాల క్రమం ఇన్పుట్ ఇటరబుల్ క్రమానికి సరిపోలుతుందని హామీ లేదు. ఫలితాల క్రమం ముఖ్యం కాకపోతే ఇది మరింత సమర్థవంతంగా ఉంటుంది.
సరైన పద్ధతిని ఎంచుకోవడం మీ నిర్దిష్ట అవసరాలపై ఆధారపడి ఉంటుంది:
- మీకు ఫలితాలు ఇన్పుట్ ఇటరబుల్ వలె అదే క్రమంలో అవసరమైనప్పుడు మరియు అన్ని టాస్క్లు పూర్తయ్యే వరకు వేచి ఉండటానికి సిద్ధంగా ఉన్నప్పుడు
mapఉపయోగించండి. - ఒకే టాస్క్ల కోసం లేదా మీరు కీవర్డ్ ఆర్గ్యుమెంట్లను పంపించాల్సినప్పుడు
applyఉపయోగించండి. - మీరు టాస్క్లను అసమకాలికంగా అమలు చేయాలనుకున్నప్పుడు మరియు ప్రధాన ప్రక్రియను బ్లాక్ చేయకూడదనుకున్నప్పుడు
apply_asyncఉపయోగించండి. - ఫలితాలు అందుబాటులోకి వచ్చినప్పుడు వాటిని ప్రాసెస్ చేయాలనుకున్నప్పుడు మరియు కొద్దిగా ఓవర్హెడ్ను భరించగలిగినప్పుడు
imapఉపయోగించండి. - ఫలితాల క్రమం పట్టింపు లేనప్పుడు మరియు మీకు గరిష్ట సామర్థ్యం కావాలనుకున్నప్పుడు
imap_unorderedఉపయోగించండి.
ఉదాహరణ: కాల్బ్యాక్లతో అసమకాలిక టాస్క్ సమర్పణ
from multiprocessing import Pool, cpu_count
import time
def worker_function(x):
# Simulate a time-consuming task
time.sleep(1)
return x * x
def callback_function(result):
print(f"Result received: {result}")
def error_callback_function(exception):
print(f"An error occurred: {exception}")
if __name__ == '__main__':
num_processes = cpu_count()
with Pool(processes=num_processes) as pool:
for i in range(5):
pool.apply_async(worker_function, args=(i,), callback=callback_function, error_callback=error_callback_function)
# Close the pool and wait for all tasks to complete
pool.close()
pool.join()
print("All tasks completed.")
వివరణ:
- ఒక టాస్క్ విజయవంతంగా పూర్తయినప్పుడు పిలువబడే
callback_functionను మేము నిర్వచిస్తాము. - ఒక టాస్క్ మినహాయింపును ఎదుర్కొంటే పిలువబడే
error_callback_functionను మేము నిర్వచిస్తాము. - టాస్క్లను అసమకాలికంగా పూల్కు సమర్పించడానికి మేము
pool.apply_async()ను ఉపయోగిస్తాము. - పూల్కు మరిన్ని టాస్క్లు సమర్పించకుండా నిరోధించడానికి మేము
pool.close()ను పిలుస్తాము. - ప్రోగ్రామ్ నుండి నిష్క్రమించే ముందు పూల్లోని అన్ని టాస్క్లు పూర్తయ్యే వరకు వేచి ఉండటానికి మేము
pool.join()ను పిలుస్తాము.
షేర్డ్ మెమరీ నిర్వహణ
ప్రాసెస్ పూల్స్ సమర్థవంతమైన సమాంతర ఎగ్జిక్యూషన్ను ప్రారంభిస్తున్నప్పటికీ, ప్రక్రియల మధ్య డేటాను పంచుకోవడం ఒక సవాలుగా ఉంటుంది. ప్రతి ప్రక్రియకు దాని స్వంత మెమరీ స్పేస్ ఉంటుంది, ఇతర ప్రక్రియలలోని డేటాకు ప్రత్యక్ష ప్రాప్యతను నిరోధిస్తుంది. పైథాన్ యొక్క multiprocessing మాడ్యూల్ ప్రక్రియల మధ్య సురక్షితమైన మరియు సమర్థవంతమైన డేటా షేరింగ్ను సులభతరం చేయడానికి షేర్డ్ మెమరీ ఆబ్జెక్టులు మరియు సింక్రొనైజేషన్ ప్రిమిటివ్లను అందిస్తుంది.
షేర్డ్ మెమరీ ఆబ్జెక్టులు: Value మరియు Array
Value మరియు Array క్లాసులు బహుళ ప్రక్రియల ద్వారా యాక్సెస్ చేయగల మరియు సవరించగల షేర్డ్ మెమరీ ఆబ్జెక్టులను సృష్టించడానికి మిమ్మల్ని అనుమతిస్తాయి.
Value(typecode_or_type, *args, lock=True): నిర్దిష్ట రకం యొక్క ఒకే విలువను కలిగి ఉన్న షేర్డ్ మెమరీ ఆబ్జెక్ట్ను సృష్టిస్తుంది.typecode_or_typeవిలువ యొక్క డేటా రకాన్ని నిర్దేశిస్తుంది (ఉదా., పూర్ణాంకం కోసం'i', డబుల్ కోసం'd',ctypes.c_int,ctypes.c_double).lock=Trueరేస్ కండిషన్లను నివారించడానికి అనుబంధిత లాక్ను సృష్టిస్తుంది.Array(typecode_or_type, sequence, lock=True): నిర్దిష్ట రకం యొక్క విలువల శ్రేణిని కలిగి ఉన్న షేర్డ్ మెమరీ ఆబ్జెక్ట్ను సృష్టిస్తుంది.typecode_or_typeశ్రేణి మూలకాల యొక్క డేటా రకాన్ని నిర్దేశిస్తుంది (ఉదా., పూర్ణాంకం కోసం'i', డబుల్ కోసం'd',ctypes.c_int,ctypes.c_double).sequenceఅనేది శ్రేణి కోసం ప్రారంభ విలువల క్రమం.lock=Trueరేస్ కండిషన్లను నివారించడానికి అనుబంధిత లాక్ను సృష్టిస్తుంది.
ఉదాహరణ: ప్రక్రియల మధ్య ఒక విలువను పంచుకోవడం
from multiprocessing import Process, Value, Lock
import time
def increment_value(shared_value, lock, num_increments):
for _ in range(num_increments):
with lock:
shared_value.value += 1
time.sleep(0.01) # Simulate some work
if __name__ == '__main__':
shared_value = Value('i', 0) # Create a shared integer with initial value 0
lock = Lock() # Create a lock for synchronization
num_processes = 3
num_increments = 100
processes = []
for _ in range(num_processes):
p = Process(target=increment_value, args=(shared_value, lock, num_increments))
processes.append(p)
p.start()
for p in processes:
p.join()
print(f"Final value: {shared_value.value}")
వివరణ:
- మేము ప్రారంభ విలువ 0తో ఒక షేర్డ్
Valueఆబ్జెక్ట్ను ('i'రకం పూర్ణాంకం) సృష్టిస్తాము. - షేర్డ్ విలువకు యాక్సెస్ను సింక్రొనైజ్ చేయడానికి మేము ఒక
Lockఆబ్జెక్ట్ను సృష్టిస్తాము. - మేము బహుళ ప్రక్రియలను సృష్టిస్తాము, ప్రతి ఒక్కటి షేర్డ్ విలువను నిర్దిష్ట సంఖ్యలో పెంచుతుంది.
increment_valueఫంక్షన్ లోపల, షేర్డ్ విలువను యాక్సెస్ చేయడానికి ముందు లాక్ను పొందటానికి మరియు ఆ తర్వాత దానిని విడుదల చేయడానికి మేముwith lock:స్టేట్మెంట్ను ఉపయోగిస్తాము. ఇది ఒకే సమయంలో ఒకే ప్రక్రియ మాత్రమే షేర్డ్ విలువను యాక్సెస్ చేయగలదని నిర్ధారిస్తుంది, రేస్ కండిషన్లను నివారిస్తుంది.- అన్ని ప్రక్రియలు పూర్తయిన తర్వాత, మేము షేర్డ్ వేరియబుల్ యొక్క చివరి విలువను ప్రింట్ చేస్తాము. లాక్ లేకుండా, రేస్ కండిషన్ల కారణంగా చివరి విలువ అనూహ్యంగా ఉంటుంది.
ఉదాహరణ: ప్రక్రియల మధ్య ఒక శ్రేణిని పంచుకోవడం
from multiprocessing import Process, Array
import random
def fill_array(shared_array):
for i in range(len(shared_array)):
shared_array[i] = random.random()
if __name__ == '__main__':
array_size = 10
shared_array = Array('d', array_size) # Create a shared array of doubles
processes = []
for _ in range(3):
p = Process(target=fill_array, args=(shared_array,))
processes.append(p)
p.start()
for p in processes:
p.join()
print(f"Final array: {list(shared_array)}")
వివరణ:
- మేము నిర్దిష్ట పరిమాణంతో డబుల్ (
'd') రకం యొక్క ఒక షేర్డ్Arrayఆబ్జెక్ట్ను సృష్టిస్తాము. - మేము బహుళ ప్రక్రియలను సృష్టిస్తాము, ప్రతి ఒక్కటి శ్రేణిని యాదృచ్ఛిక సంఖ్యలతో నింపుతుంది.
- అన్ని ప్రక్రియలు పూర్తయిన తర్వాత, మేము షేర్డ్ శ్రేణి యొక్క కంటెంట్లను ప్రింట్ చేస్తాము. ప్రతి ప్రక్రియ చేసిన మార్పులు షేర్డ్ శ్రేణిలో ప్రతిబింబిస్తాయని గమనించండి.
సింక్రొనైజేషన్ ప్రిమిటివ్లు: లాక్స్, సెమాఫోర్లు, మరియు కండిషన్లు
బహుళ ప్రక్రియలు షేర్డ్ మెమరీని యాక్సెస్ చేసినప్పుడు, రేస్ కండిషన్లను నివారించడానికి మరియు డేటా స్థిరత్వాన్ని నిర్ధారించడానికి సింక్రొనైజేషన్ ప్రిమిటివ్లను ఉపయోగించడం చాలా అవసరం. multiprocessing మాడ్యూల్ అనేక సింక్రొనైజేషన్ ప్రిమిటివ్లను అందిస్తుంది, వాటిలో:
Lock: ఒక ప్రాథమిక లాకింగ్ మెకానిజం, ఇది ఒకే సమయంలో ఒకే ప్రక్రియకు మాత్రమే లాక్ను పొందడానికి అనుమతిస్తుంది. షేర్డ్ వనరులను యాక్సెస్ చేసే కోడ్ యొక్క క్లిష్టమైన విభాగాలను రక్షించడానికి ఉపయోగిస్తారు.Semaphore: ఒక సాధారణ సింక్రొనైజేషన్ ప్రిమిటివ్, ఇది ఒకే సమయంలో పరిమిత సంఖ్యలో ప్రక్రియలను ఒక షేర్డ్ వనరును యాక్సెస్ చేయడానికి అనుమతిస్తుంది. పరిమిత సామర్థ్యంతో వనరులకు యాక్సెస్ను నియంత్రించడానికి ఉపయోగపడుతుంది.Condition: ఒక సింక్రొనైజేషన్ ప్రిమిటివ్, ఇది ఒక నిర్దిష్ట పరిస్థితి నిజం కావడానికి ప్రక్రియలు వేచి ఉండటానికి అనుమతిస్తుంది. తరచుగా ప్రొడ్యూసర్-కన్స్యూమర్ దృశ్యాలలో ఉపయోగిస్తారు.
షేర్డ్ Value ఆబ్జెక్టులతో Lock ఉపయోగించడం యొక్క ఒక ఉదాహరణను మనం ఇప్పటికే చూశాము. ఇప్పుడు Condition ఉపయోగించి ఒక సరళీకృత ప్రొడ్యూసర్-కన్స్యూమర్ దృశ్యాన్ని పరిశీలిద్దాం.
ఉదాహరణ: కండిషన్తో ప్రొడ్యూసర్-కన్స్యూమర్
from multiprocessing import Process, Condition, Queue
import time
import random
def producer(condition, queue):
for i in range(5):
time.sleep(random.random())
condition.acquire()
queue.put(i)
print(f"Produced: {i}")
condition.notify()
condition.release()
def consumer(condition, queue):
for _ in range(5):
condition.acquire()
while queue.empty():
print("Consumer waiting...")
condition.wait()
item = queue.get()
print(f"Consumed: {item}")
condition.release()
if __name__ == '__main__':
condition = Condition()
queue = Queue()
p = Process(target=producer, args=(condition, queue))
c = Process(target=consumer, args=(condition, queue))
p.start()
c.start()
p.join()
c.join()
print("Done.")
వివరణ:
- డేటా యొక్క ఇంటర్-ప్రాసెస్ కమ్యూనికేషన్ కోసం ఒక
Queueఉపయోగించబడుతుంది. - ప్రొడ్యూసర్ మరియు కన్స్యూమర్ను సింక్రొనైజ్ చేయడానికి ఒక
Conditionఉపయోగించబడుతుంది. కన్స్యూమర్ క్యూలో డేటా అందుబాటులోకి రావడానికి వేచి ఉంటుంది, మరియు ప్రొడ్యూసర్ డేటా ఉత్పత్తి అయినప్పుడు కన్స్యూమర్కు తెలియజేస్తుంది. condition.acquire()మరియుcondition.release()పద్ధతులు కండిషన్తో అనుబంధించబడిన లాక్ను పొందడానికి మరియు విడుదల చేయడానికి ఉపయోగించబడతాయి.condition.wait()పద్ధతి లాక్ను విడుదల చేసి, నోటిఫికేషన్ కోసం వేచి ఉంటుంది.condition.notify()పద్ధతి కండిషన్ నిజం కావచ్చు అని వేచి ఉన్న ఒక థ్రెడ్ (లేదా ప్రక్రియ) కు తెలియజేస్తుంది.
గ్లోబల్ ప్రేక్షకుల కోసం పరిగణనలు
ప్రపంచవ్యాప్త ప్రేక్షకుల కోసం మల్టీప్రాసెసింగ్ అప్లికేషన్లను అభివృద్ధి చేసేటప్పుడు, వివిధ వాతావరణాలలో అనుకూలత మరియు సరైన పనితీరును నిర్ధారించడానికి అనేక అంశాలను పరిగణించడం చాలా అవసరం:
- క్యారెక్టర్ ఎన్కోడింగ్: ప్రక్రియల మధ్య స్ట్రింగ్లను పంచుకునేటప్పుడు క్యారెక్టర్ ఎన్కోడింగ్ గురించి జాగ్రత్తగా ఉండండి. UTF-8 సాధారణంగా సురక్షితమైన మరియు విస్తృతంగా మద్దతు ఉన్న ఎన్కోడింగ్. తప్పు ఎన్కోడింగ్ వివిధ భాషలతో వ్యవహరించేటప్పుడు గజిబిజి టెక్స్ట్ లేదా లోపాలకు దారితీస్తుంది.
- లోకేల్ సెట్టింగ్స్: లోకేల్ సెట్టింగ్స్ తేదీ మరియు సమయ ఫార్మాటింగ్ వంటి కొన్ని ఫంక్షన్ల ప్రవర్తనను ప్రభావితం చేయవచ్చు. లోకేల్-నిర్దిష్ట కార్యకలాపాలను సరిగ్గా నిర్వహించడానికి
localeమాడ్యూల్ను ఉపయోగించడాన్ని పరిగణించండి. - టైమ్ జోన్లు: సమయ-సున్నితమైన డేటాతో వ్యవహరించేటప్పుడు, టైమ్ జోన్ల గురించి తెలుసుకోండి మరియు టైమ్ జోన్ మార్పిడులను ఖచ్చితంగా నిర్వహించడానికి
datetimeమాడ్యూల్నుpytzలైబ్రరీతో ఉపయోగించండి. ఇది వివిధ భౌగోళిక ప్రాంతాలలో పనిచేసే అప్లికేషన్లకు చాలా ముఖ్యం. - వనరుల పరిమితులు: ఆపరేటింగ్ సిస్టమ్లు మెమరీ వాడకం లేదా తెరిచిన ఫైళ్ల సంఖ్య వంటి ప్రక్రియలపై వనరుల పరిమితులను విధించవచ్చు. ఈ పరిమితుల గురించి తెలుసుకోండి మరియు మీ అప్లికేషన్ను తదనుగుణంగా డిజైన్ చేయండి. విభిన్న ఆపరేటింగ్ సిస్టమ్లు మరియు హోస్టింగ్ వాతావరణాలకు విభిన్న డిఫాల్ట్ పరిమితులు ఉంటాయి.
- ప్లాట్ఫారమ్ అనుకూలత: పైథాన్ యొక్క
multiprocessingమాడ్యూల్ ప్లాట్ఫారమ్-స్వతంత్రంగా రూపొందించబడినప్పటికీ, విభిన్న ఆపరేటింగ్ సిస్టమ్లలో (విండోస్, మాక్ఓఎస్, లైనక్స్) ప్రవర్తనలో సూక్ష్మమైన తేడాలు ఉండవచ్చు. మీ అప్లికేషన్ను అన్ని లక్ష్య ప్లాట్ఫారమ్లపై క్షుణ్ణంగా పరీక్షించండి. ఉదాహరణకు, ప్రక్రియలు ఎలా పుడతాయో మారవచ్చు (ఫోర్కింగ్ వర్సెస్ స్పానింగ్). - లోపం నిర్వహణ మరియు లాగింగ్: విభిన్న వాతావరణాలలో తలెత్తగల సమస్యలను నిర్ధారించడానికి మరియు పరిష్కరించడానికి బలమైన లోపం నిర్వహణ మరియు లాగింగ్ను అమలు చేయండి. లాగ్ సందేశాలు స్పష్టంగా, సమాచారంగా మరియు బహుశా అనువదించదగినవిగా ఉండాలి. సులభమైన డీబగ్గింగ్ కోసం కేంద్రీకృత లాగింగ్ వ్యవస్థను ఉపయోగించడాన్ని పరిగణించండి.
- అంతర్జాతీయీకరణ (i18n) మరియు స్థానికీకరణ (l10n): మీ అప్లికేషన్లో యూజర్ ఇంటర్ఫేస్లు లేదా టెక్స్ట్ ప్రదర్శన ఉంటే, బహుళ భాషలు మరియు సాంస్కృతిక ప్రాధాన్యతలకు మద్దతు ఇవ్వడానికి అంతర్జాతీయీకరణ మరియు స్థానికీకరణను పరిగణించండి. ఇది స్ట్రింగ్లను బాహ్యీకరించడం మరియు వివిధ లోకేల్ల కోసం అనువాదాలను అందించడం కలిగి ఉంటుంది.
మల్టీప్రాసెసింగ్ కోసం ఉత్తమ పద్ధతులు
మల్టీప్రాసెసింగ్ యొక్క ప్రయోజనాలను గరిష్టీకరించడానికి మరియు సాధారణ ఆపదలను నివారించడానికి, ఈ ఉత్తమ పద్ధతులను అనుసరించండి:
- టాస్క్లను స్వతంత్రంగా ఉంచండి: షేర్డ్ మెమరీ మరియు సింక్రొనైజేషన్ అవసరాన్ని తగ్గించడానికి మీ టాస్క్లను సాధ్యమైనంత స్వతంత్రంగా ఉండేలా డిజైన్ చేయండి. ఇది రేస్ కండిషన్లు మరియు వివాదాల ప్రమాదాన్ని తగ్గిస్తుంది.
- డేటా బదిలీని తగ్గించండి: ఓవర్హెడ్ను తగ్గించడానికి ప్రక్రియల మధ్య అవసరమైన డేటాను మాత్రమే బదిలీ చేయండి. సాధ్యమైతే పెద్ద డేటా నిర్మాణాలను పంచుకోవడం మానుకోండి. చాలా పెద్ద డేటాసెట్ల కోసం జీరో-కాపీ షేరింగ్ లేదా మెమరీ మ్యాపింగ్ వంటి పద్ధతులను ఉపయోగించడాన్ని పరిగణించండి.
- లాక్లను మితంగా ఉపయోగించండి: లాక్ల అధిక వినియోగం పనితీరులో అడ్డంకులకు దారితీస్తుంది. కోడ్ యొక్క క్లిష్టమైన విభాగాలను రక్షించడానికి అవసరమైనప్పుడు మాత్రమే లాక్లను ఉపయోగించండి. సముచితమైతే సెమాఫోర్లు లేదా కండిషన్లు వంటి ప్రత్యామ్నాయ సింక్రొనైజేషన్ ప్రిమిటివ్లను ఉపయోగించడాన్ని పరిగణించండి.
- డెడ్లాక్లను నివారించండి: డెడ్లాక్లను నివారించడానికి జాగ్రత్తగా ఉండండి, ఇది రెండు లేదా అంతకంటే ఎక్కువ ప్రక్రియలు నిరవధికంగా బ్లాక్ చేయబడినప్పుడు, వనరులను విడుదల చేయడానికి ఒకదానికొకటి వేచి ఉన్నప్పుడు సంభవించవచ్చు. డెడ్లాక్లను నివారించడానికి స్థిరమైన లాకింగ్ క్రమాన్ని ఉపయోగించండి.
- మినహాయింపులను సరిగ్గా నిర్వహించండి: వర్కర్ ప్రక్రియలలో మినహాయింపులను నిర్వహించండి, తద్వారా అవి క్రాష్ కాకుండా మరియు మొత్తం అప్లికేషన్ను పడగొట్టకుండా నివారించవచ్చు. మినహాయింపులను పట్టుకోవడానికి మరియు వాటిని సముచితంగా లాగ్ చేయడానికి ట్రై-ఎక్సెప్ట్ బ్లాక్లను ఉపయోగించండి.
- వనరుల వినియోగాన్ని పర్యవేక్షించండి: సంభావ్య అడ్డంకులు లేదా పనితీరు సమస్యలను గుర్తించడానికి మీ మల్టీప్రాసెసింగ్ అప్లికేషన్ యొక్క వనరుల వినియోగాన్ని పర్యవేక్షించండి. CPU వినియోగం, మెమరీ వినియోగం మరియు I/O కార్యాచరణను పర్యవేక్షించడానికి
psutilవంటి సాధనాలను ఉపయోగించండి. - టాస్క్ క్యూను ఉపయోగించడాన్ని పరిగణించండి: మరింత సంక్లిష్టమైన దృశ్యాల కోసం, టాస్క్లను నిర్వహించడానికి మరియు వాటిని బహుళ ప్రక్రియలు లేదా బహుళ యంత్రాలలో పంపిణీ చేయడానికి ఒక టాస్క్ క్యూను (ఉదా., సెలెరీ, రెడ్డిస్ క్యూ) ఉపయోగించడాన్ని పరిగణించండి. టాస్క్ క్యూలు టాస్క్ ప్రాధాన్యత, పునఃప్రయత్న యంత్రాంగాలు మరియు పర్యవేక్షణ వంటి లక్షణాలను అందిస్తాయి.
- మీ కోడ్ను ప్రొఫైల్ చేయండి: మీ కోడ్లోని అత్యంత సమయం తీసుకునే భాగాలను గుర్తించడానికి మరియు ఆ ప్రాంతాలపై మీ ఆప్టిమైజేషన్ ప్రయత్నాలను కేంద్రీకరించడానికి ఒక ప్రొఫైలర్ను ఉపయోగించండి. పైథాన్
cProfileమరియుline_profilerవంటి అనేక ప్రొఫైలింగ్ సాధనాలను అందిస్తుంది. - క్షుణ్ణంగా పరీక్షించండి: మీ మల్టీప్రాసెసింగ్ అప్లికేషన్ సరిగ్గా మరియు సమర్థవంతంగా పనిచేస్తుందని నిర్ధారించుకోవడానికి దానిని క్షుణ్ణంగా పరీక్షించండి. వ్యక్తిగత భాగాల యొక్క సరైనతను ధృవీకరించడానికి యూనిట్ పరీక్షలను మరియు విభిన్న ప్రక్రియల మధ్య పరస్పర చర్యను ధృవీకరించడానికి ఇంటిగ్రేషన్ పరీక్షలను ఉపయోగించండి.
- మీ కోడ్ను డాక్యుమెంట్ చేయండి: ప్రతి ప్రక్రియ యొక్క ఉద్దేశ్యం, ఉపయోగించిన షేర్డ్ మెమరీ ఆబ్జెక్టులు మరియు ఉపయోగించిన సింక్రొనైజేషన్ యంత్రాంగాలతో సహా మీ కోడ్ను స్పష్టంగా డాక్యుమెంట్ చేయండి. ఇది ఇతరులకు మీ కోడ్ను అర్థం చేసుకోవడానికి మరియు నిర్వహించడానికి సులభం చేస్తుంది.
అధునాతన పద్ధతులు మరియు ప్రత్యామ్నాయాలు
ప్రాసెస్ పూల్స్ మరియు షేర్డ్ మెమరీ యొక్క ప్రాథమిక అంశాలకు మించి, మరింత సంక్లిష్టమైన మల్టీప్రాసెసింగ్ దృశ్యాల కోసం పరిగణించవలసిన అనేక అధునాతన పద్ధతులు మరియు ప్రత్యామ్నాయ విధానాలు ఉన్నాయి:
- ZeroMQ: ఇంటర్-ప్రాసెస్ కమ్యూనికేషన్ కోసం ఉపయోగించగల అధిక-పనితీరు గల అసమకాలిక సందేశ లైబ్రరీ. ZeroMQ పబ్లిష్-సబ్స్క్రైబ్, రిక్వెస్ట్-రిప్లై, మరియు పుష్-పుల్ వంటి వివిధ సందేశ నమూనాలను అందిస్తుంది.
- Redis: షేర్డ్ మెమరీ మరియు ఇంటర్-ప్రాసెస్ కమ్యూనికేషన్ కోసం ఉపయోగించగల ఇన్-మెమరీ డేటా స్ట్రక్చర్ స్టోర్. Redis పబ్/సబ్, లావాదేవీలు మరియు స్క్రిప్టింగ్ వంటి లక్షణాలను అందిస్తుంది.
- Dask: పెద్ద డేటాసెట్లపై గణనలను సమాంతరంగా చేయడానికి ఉన్నత-స్థాయి ఇంటర్ఫేస్ను అందించే ఒక సమాంతర కంప్యూటింగ్ లైబ్రరీ. Daskను ప్రాసెస్ పూల్స్ లేదా పంపిణీ చేయబడిన క్లస్టర్లతో ఉపయోగించవచ్చు.
- Ray: AI మరియు పైథాన్ అప్లికేషన్లను నిర్మించడం మరియు స్కేల్ చేయడం సులభం చేసే ఒక పంపిణీ చేయబడిన ఎగ్జిక్యూషన్ ఫ్రేమ్వర్క్. Ray రిమోట్ ఫంక్షన్ కాల్స్, పంపిణీ చేయబడిన నటులు మరియు ఆటోమేటిక్ డేటా నిర్వహణ వంటి లక్షణాలను అందిస్తుంది.
- MPI (Message Passing Interface): ఇంటర్-ప్రాసెస్ కమ్యూనికేషన్ కోసం ఒక ప్రమాణం, సాధారణంగా శాస్త్రీయ కంప్యూటింగ్లో ఉపయోగిస్తారు. పైథాన్కు
mpi4pyవంటి MPI కోసం బైండింగ్స్ ఉన్నాయి. - షేర్డ్ మెమరీ ఫైల్స్ (mmap): మెమరీ మ్యాపింగ్ ఒక ఫైల్ను మెమరీలోకి మ్యాప్ చేయడానికి మిమ్మల్ని అనుమతిస్తుంది, తద్వారా బహుళ ప్రక్రియలు అదే ఫైల్ డేటాను నేరుగా యాక్సెస్ చేయగలవు. ఇది సాంప్రదాయిక ఫైల్ I/O ద్వారా డేటాను చదవడం మరియు వ్రాయడం కంటే సమర్థవంతంగా ఉంటుంది. పైథాన్లోని
mmapమాడ్యూల్ మెమరీ మ్యాపింగ్కు మద్దతు ఇస్తుంది. - ఇతర భాషలలో ప్రాసెస్-ఆధారిత వర్సెస్ థ్రెడ్-ఆధారిత కాంకరెన్సీ: ఈ గైడ్ పైథాన్పై దృష్టి కేంద్రీకరించినప్పటికీ, ఇతర భాషలలోని కాంకరెన్సీ నమూనాలను అర్థం చేసుకోవడం విలువైన అంతర్దృష్టులను అందిస్తుంది. ఉదాహరణకు, గో కాంకరెన్సీ కోసం గొరూటీన్లు (తేలికపాటి థ్రెడ్లు) మరియు ఛానెల్లను ఉపయోగిస్తుంది, అయితే జావా థ్రెడ్లు మరియు ప్రాసెస్-ఆధారిత సమాంతరత రెండింటినీ అందిస్తుంది.
ముగింపు
పైథాన్ యొక్క multiprocessing మాడ్యూల్ CPU-బౌండ్ టాస్క్లను సమాంతరంగా చేయడానికి మరియు ప్రక్రియల మధ్య షేర్డ్ మెమరీని నిర్వహించడానికి శక్తివంతమైన సాధనాల సమితిని అందిస్తుంది. ప్రాసెస్ పూల్స్, షేర్డ్ మెమరీ ఆబ్జెక్టులు మరియు సింక్రొనైజేషన్ ప్రిమిటివ్ల యొక్క భావనలను అర్థం చేసుకోవడం ద్వారా, మీరు మీ మల్టీ-కోర్ ప్రాసెసర్ల పూర్తి సామర్థ్యాన్ని అన్లాక్ చేయవచ్చు మరియు మీ పైథాన్ అప్లికేషన్ల పనితీరును గణనీయంగా మెరుగుపరచవచ్చు.
మల్టీప్రాసెసింగ్లో ఉన్న వాణిజ్యపరమైన అంశాలను, అనగా ఇంటర్-ప్రాసెస్ కమ్యూనికేషన్ యొక్క ఓవర్హెడ్ మరియు షేర్డ్ మెమరీని నిర్వహించే సంక్లిష్టత వంటి వాటిని జాగ్రత్తగా పరిగణలోకి తీసుకోవాలని గుర్తుంచుకోండి. ఉత్తమ పద్ధతులను అనుసరించడం మరియు మీ నిర్దిష్ట అవసరాలకు తగిన పద్ధతులను ఎంచుకోవడం ద్వారా, మీరు ప్రపంచవ్యాప్త ప్రేక్షకుల కోసం సమర్థవంతమైన మరియు స్కేలబుల్ మల్టీప్రాసెసింగ్ అప్లికేషన్లను సృష్టించవచ్చు. ప్రపంచవ్యాప్తంగా విభిన్న వాతావరణాలలో విశ్వసనీయంగా నడవాల్సిన అప్లికేషన్లను triển khai చేసినప్పుడు క్షుణ్ణమైన పరీక్ష మరియు బలమైన లోపం నిర్వహణ చాలా ముఖ్యమైనవి.