मैं एक सरल उदाहरण और स्पष्टीकरण के साथ योगदान करना चाहता हूं, जब मुझे इस समस्या से निपटने के लिए उपयोगी पाया गया है।
इस उत्तर में आपको पायथन के जीआईएल (वैश्विक दुभाषिया लॉक) के बारे में कुछ जानकारी मिलेगी और एक सरल दिन-प्रतिदिन का उदाहरण मल्टीप्रोसेसिंग डमी का उपयोग करके लिखा जाएगा और साथ ही कुछ सरल बेंचमार्क भी।
ग्लोबल इंटरप्रेटर लॉक (GIL)
पायथन शब्द के ट्रुस्ट अर्थ में मल्टी-थ्रेडिंग की अनुमति नहीं देता है। इसमें एक मल्टी-थ्रेडिंग पैकेज है, लेकिन अगर आप अपने कोड को गति देने के लिए मल्टी-थ्रेड बनाना चाहते हैं, तो आमतौर पर इसका उपयोग करने के लिए एक अच्छा विचार नहीं है।
पायथन में एक कंस्ट्रक्शन है जिसे ग्लोबल इंटरप्रेटर लॉक (GIL) कहा जाता है। जीआईएल यह सुनिश्चित करता है कि आपके किसी भी एक समय पर केवल एक 'थ्रेड' निष्पादित हो सकता है। एक धागा GIL का अधिग्रहण करता है, थोड़ा काम करता है, फिर अगले धागे पर GIL पास करता है।
यह बहुत जल्दी से होता है ताकि मानव आंख को यह महसूस हो सके कि आपके धागे समानांतर में निष्पादित हो रहे हैं, लेकिन वे वास्तव में बस एक ही सीपीयू कोर का उपयोग करके मोड़ ले रहे हैं।
यह सब GIL पास निष्पादन के लिए ओवरहेड जोड़ता है। इसका मतलब है कि यदि आप अपने कोड को तेजी से चलाना चाहते हैं तो थ्रेडिंग पैकेज का उपयोग करना अक्सर अच्छा विचार नहीं होता है।
पायथन के थ्रेडिंग पैकेज का उपयोग करने के कारण हैं। यदि आप कुछ चीजों को एक साथ चलाना चाहते हैं, और दक्षता चिंता का विषय नहीं है, तो यह पूरी तरह से ठीक है और सुविधाजनक है। या यदि आप ऐसा कोड चला रहे हैं, जिसके लिए कुछ (जैसे I / O) प्रतीक्षा करनी पड़ती है, तो यह बहुत मायने रख सकता है। लेकिन थ्रेडिंग लाइब्रेरी आपको अतिरिक्त सीपीयू कोर का उपयोग नहीं करने देगी।
मल्टी-थ्रेडिंग को ऑपरेटिंग सिस्टम (मल्टी-प्रोसेसिंग करके) के लिए आउटसोर्स किया जा सकता है, और कुछ बाहरी एप्लिकेशन जो आपके पायथन कोड (उदाहरण के लिए, स्पार्क या हडोप ) को कॉल करते हैं , या कुछ कोड जिसे आपका पायथन कोड कॉल करता है (उदाहरण के लिए) - अपने पायथन कोड को एक C फ़ंक्शन कहें जो महंगा बहु-थ्रेडेड सामान करता है)।
क्यों यह मामला
क्योंकि बहुत से लोग जीआईएल क्या है यह जानने से पहले अपने फैंसी पायथन मल्टी थ्रेडेड कोड में अड़चन खोजने की कोशिश में बहुत समय बिताते हैं।
यह जानकारी स्पष्ट हो जाने के बाद, मेरा कोड यहाँ है:
#!/bin/python
from multiprocessing.dummy import Pool
from subprocess import PIPE,Popen
import time
import os
# In the variable pool_size we define the "parallelness".
# For CPU-bound tasks, it doesn't make sense to create more Pool processes
# than you have cores to run them on.
#
# On the other hand, if you are using I/O-bound tasks, it may make sense
# to create a quite a few more Pool processes than cores, since the processes
# will probably spend most their time blocked (waiting for I/O to complete).
pool_size = 8
def do_ping(ip):
if os.name == 'nt':
print ("Using Windows Ping to " + ip)
proc = Popen(['ping', ip], stdout=PIPE)
return proc.communicate()[0]
else:
print ("Using Linux / Unix Ping to " + ip)
proc = Popen(['ping', ip, '-c', '4'], stdout=PIPE)
return proc.communicate()[0]
os.system('cls' if os.name=='nt' else 'clear')
print ("Running using threads\n")
start_time = time.time()
pool = Pool(pool_size)
website_names = ["www.google.com","www.facebook.com","www.pinterest.com","www.microsoft.com"]
result = {}
for website_name in website_names:
result[website_name] = pool.apply_async(do_ping, args=(website_name,))
pool.close()
pool.join()
print ("\n--- Execution took {} seconds ---".format((time.time() - start_time)))
# Now we do the same without threading, just to compare time
print ("\nRunning NOT using threads\n")
start_time = time.time()
for website_name in website_names:
do_ping(website_name)
print ("\n--- Execution took {} seconds ---".format((time.time() - start_time)))
# Here's one way to print the final output from the threads
output = {}
for key, value in result.items():
output[key] = value.get()
print ("\nOutput aggregated in a Dictionary:")
print (output)
print ("\n")
print ("\nPretty printed output: ")
for key, value in output.items():
print (key + "\n")
print (value)