2016-04-22 4 views
28

सेटअपमेरी पाइथन प्रक्रियाओं पर कौन सी सीपीयू कोर चल रही हैं?

मैं एक बहुत जटिल (एक विंडोज पीसी पर) पायथन में सॉफ्टवेयर का टुकड़ा लिखा है। मेरा सॉफ्टवेयर मूल रूप से दो पायथन दुभाषिया गोले शुरू होता है। पहला शेल शुरू होता है (मुझे लगता है) जब आप main.py फ़ाइल को डबल क्लिक करते हैं। कि खोल के भीतर, अन्य थ्रेड निम्नलिखित तरीके से शुरू कर रहे हैं:

# Start TCP_thread 
    TCP_thread = threading.Thread(name = 'TCP_loop', target = TCP_loop, args = (TCPsock,)) 
    TCP_thread.start() 

    # Start UDP_thread 
    UDP_thread = threading.Thread(name = 'UDP_loop', target = UDP_loop, args = (UDPsock,)) 
    TCP_thread.start() 

Main_thread एक TCP_thread और एक UDP_thread शुरू होता है। हालांकि ये अलग धागे हैं, वे सभी एक ही पायथन खोल के भीतर भागते हैं।

Main_thread भी एक उपप्रजाति शुरू करता है। यह निम्नलिखित तरीके से किया जाता है:

p = subprocess.Popen(['python', mySubprocessPath], shell=True) 

अजगर प्रलेखन से, मैं समझता हूँ कि इस उपप्रक्रिया एक साथ चल रहा है एक अलग अजगर दुभाषिया सत्र/खोल में (!)। इस सबप्रोसेस में Main_thread पूरी तरह से मेरे जीयूआई को समर्पित है। जीयूआई अपने सभी संचारों के लिए TCP_thread शुरू करता है।

मुझे पता है कि चीजें थोड़ा जटिल हो जाती हैं। इसलिए मैं इस आंकड़े में पूरे सेटअप संक्षेप है:

enter image description here


मैं इस स्थापना के विषय में कई प्रश्न हैं। मैं यहाँ उन्हें नीचे सूची जाएगा:

प्रश्न 1 [हल]

यह सही है कि एक अजगर दुभाषिया एक समय सभी धागे को चलाने के लिए केवल एक सीपीयू कोर का उपयोग करता है? दूसरे शब्दों में, Python interpreter session 1 (आकृति से) एक सीपीयू कोर पर सभी 3 धागे (Main_thread, TCP_thread और UDP_thread) चलाएंगे?

उत्तर: हाँ, यह सच है। जीआईएल (ग्लोबल इंटरप्रेटर लॉक) यह सुनिश्चित करता है कि सभी थ्रेड एक समय में एक सीपीयू कोर पर चलते हैं।

प्रश्न 2 [अभी तक नहीं सुलझ]

मैं ट्रैक करने के लिए जो सीपीयू कोर यह है एक तरह से है?

प्रश्न 3

[आंशिक रूप से हल] इस सवाल हम के बारे में धागे भूल के लिए, लेकिन हम अजगर में उपप्रक्रिया तंत्र पर ध्यान केंद्रित। एक नया सबप्रोसेस शुरू करने से तात्पर्य एक नया पायथन दुभाषिया उदाहरण शुरू होता है। क्या ये सही है?

उत्तर: हाँ यह सही है।

p = subprocess.Popen(['python', mySubprocessPath], shell = True) 

मुद्दा स्पष्ट कर दिया गया है सबसे पहले के बारे में है कि क्या निम्नलिखित कोड एक नया अजगर दुभाषिया उदाहरण बन जाएगा कुछ भ्रम की स्थिति थी। यह कोड वास्तव में एक नया पायथन दुभाषिया उदाहरण शुरू करता है।

क्या पाइथन एक अलग CPU कोर पर उस अलग पायथन दुभाषिया उदाहरण को चलाने के लिए पर्याप्त स्मार्ट होगा? क्या किसी को ट्रैक करने का कोई तरीका है, शायद कुछ स्पोरैडिक प्रिंट स्टेटमेंट्स के साथ भी?

प्रश्न 4 [नए सवाल]

समुदाय चर्चा एक नया सवाल उठाया। वहाँ जाहिरा तौर पर दो दृष्टिकोण जब (एक नई पायथन दुभाषिया उदाहरण के भीतर) एक नई प्रक्रिया को उत्पन्न करने हैं:

# Approach 1(a) 
    p = subprocess.Popen(['python', mySubprocessPath], shell = True) 

    # Approach 1(b) (J.F. Sebastian) 
    p = subprocess.Popen([sys.executable, mySubprocessPath]) 

    # Approach 2 
    p = multiprocessing.Process(target=foo, args=(q,)) 

दूसरा दृष्टिकोण स्पष्ट नकारात्मक पक्ष यह है कि यह सिर्फ एक समारोह को निशाना बनाता है - जबकि मैं एक नया अजगर स्क्रिप्ट को खोलने के लिए की जरूरत है । वैसे भी, क्या दोनों दृष्टिकोण प्राप्त होते हैं जो वे प्राप्त करते हैं?

+0

https://docs.python.org/2/library/multiprocessing.html – mootmoot

+3

मैं तुम्हें सवाल तुम क्यों जो भौतिक कोर अपने धागे को चलाने पर ध्यान देना चाहिए लगता है। ओएस आमतौर पर विभिन्न कारकों के आधार पर सिस्टम में उपलब्ध सीपीयू के बीच धागे को स्थानांतरित करेगा। क्या कोई विशेष कारण है कि आप इस प्रक्रिया के साथ निगरानी और/या हस्तक्षेप करना चाहते हैं? – Dolda2000

+0

अच्छा सवाल :-)। हां, मेरा मानना ​​है कि मेरे पास वैध कारण है। मैं पायथन में डेटा अधिग्रहण प्रणाली का निर्माण कर रहा हूं, जो मेरे माइक्रोकंट्रोलर डेटा (जैसे एनालॉग इनपुट, ...) पढ़ता है और मेरे जीयूआई में लाइव ग्राफ दिखाता है। जब तक आने वाला डेटा सीमित हो, तब तक कोई भी मल्टीप्रोसेसिंग की परवाह नहीं करता है। लेकिन एक बार यह वास्तव में तेजी से हो जाता है, मैं नियंत्रण में रहना चाहता हूँ। हो सकता है कि मैं अपने पाइथन सॉफ़्टवेयर के कुछ कम-विलंबता वाले हिस्सों को समर्पित सीपीयू कोर पर चला सकूं जो कि मैं किसी और चीज के लिए उपयोग नहीं करता, इसलिए उच्च प्रतिक्रिया सुनिश्चित करता हूं। –

उत्तर

16

प्रश्न: यह सही है कि एक अजगर दुभाषिया एक समय सभी धागे को चलाने के लिए केवल एक सीपीयू कोर का उपयोग करता है?

नहीं जीआईएल और सीपीयू संबंध असंबद्ध अवधारणाएं हैं। जीआईएल को I/O संचालन को अवरुद्ध करने के दौरान जारी किया जा सकता है, वैसे भी एक सी एक्सटेंशन के अंदर लंबे CPU गहन कंप्यूटेशंस।

यदि जीआईएल पर धागा अवरुद्ध है; यह शायद किसी भी CPU कोर पर नहीं है और इसलिए यह कहना उचित है कि शुद्ध पायथन मल्टीथ्रेडिंग कोड CPython कार्यान्वयन पर एक समय में केवल एक सीपीयू कोर का उपयोग कर सकता है।

प्रश्न: दूसरे शब्दों में, पायथन दुभाषिया सत्र 1 (आंकड़े से) एक सीपीयू कोर पर चलेंगे सभी 3 धागे (Main_thread, TCP_thread और UDP_thread)?

मुझे नहीं लगता कि सीपीथन सीपीयू संबंध को अंतर्निहित रूप से प्रबंधित करता है। थ्रेड चलाने के लिए यह संभवतः ओएस शेड्यूलर पर निर्भर करता है। पाइथन धागे वास्तविक ओएस धागे के शीर्ष पर लागू किए जाते हैं।

प्रश्न: या अजगर दुभाषिया उन्हें कई कोर में फैला करने में सक्षम है?

प्रयोग करने योग्य CPU की संख्या का पता लगाने के लिए:

>>> import os 
>>> len(os.sched_getaffinity(0)) 
16 

फिर से, या नहीं, धागे अलग CPUs पर निर्धारित हैं अजगर दुभाषिया पर निर्भर नहीं करता।

प्रश्न: मान लीजिए कि इस सवाल का जवाब प्रश्न 1 'कई कोर' है, मैं प्रत्येक थ्रेड चल रहा है, जो कोर पर शायद कुछ छिटपुट प्रिंट बयान के साथ ट्रैक करने के लिए एक तरह से है? यदि प्रश्न 1 का उत्तर 'केवल एक कोर' है, तो क्या मेरे पास यह ट्रैक करने का एक तरीका है कि यह कौन सा है?

मुझे कल्पना है कि एक विशिष्ट सीपीयू एक समय-स्लॉट से दूसरे में बदल सकता है। आप look at something like /proc/<pid>/task/<tid>/status on old Linux kernels कर सकते थे। मेरी मशीन, task_cpu can be read from /proc/<pid>/stat or /proc/<pid>/task/<tid>/stat पर:

>>> open("/proc/{pid}/stat".format(pid=os.getpid()), 'rb').read().split()[-14] 
'4' 

एक मौजूदा पोर्टेबल समाधान के लिए, psutil इस तरह की जानकारी को उजागर करता है कि क्या देखते हैं।

आप सीपीयू का एक सेट करने के लिए मौजूदा प्रक्रिया को प्रतिबंधित कर सकता है:

os.sched_setaffinity(0, {0}) # current process on 0-th core 

प्रश्न: इस सवाल हम धागे के बारे में भूल के लिए, लेकिन हम अजगर में उपप्रक्रिया तंत्र पर ध्यान केंद्रित। एक नया सबप्रोसेस शुरू करना एक नया पायथन दुभाषिया सत्र/खोल शुरू करना है। क्या ये सही है?

हां। subprocess मॉड्यूल नई ओएस प्रक्रियाएं बनाता है। यदि आप python निष्पादन योग्य चलाते हैं तो यह एक नया पायथन इंटरपेटर शुरू करता है। यदि आप एक बैश स्क्रिप्ट चलाते हैं तो कोई नया पायथन दुभाषिया नहीं बनाया गया है, यानी bash निष्पादन योग्य एक नया पायथन दुभाषिया/सत्र/आदि शुरू नहीं करता है।

प्रश्न: जाना चाहिए कि यह सही है, अजगर बहुत चालाक एक अलग सीपीयू कोर पर कि अलग दुभाषिया सत्र रन बनाने के लिए किया जाएगा? क्या इसका ट्रैक करने का कोई तरीका है, शायद कुछ स्पोरैडिक प्रिंट स्टेटमेंट्स के साथ भी?

ऊपर देखें (यानी, ओएस तय करता है कि आपका धागा कहां चलाने के लिए और ओएस एपीआई हो सकती है जो थ्रेड चलती है)।

multiprocessing.Process(target=foo, args=(q,)).start()

multiprocessing.Process भी एक नया ओएस प्रक्रिया (है कि एक नया अजगर दुभाषिया चलता है) पैदा करता है।

असल में, मेरा सबप्रोसेस एक और फ़ाइल है। तो यह उदाहरण मेरे लिए काम नहीं करेगा।

पायथन कोड व्यवस्थित करने के लिए मॉड्यूल का उपयोग करता है। यदि आपका कोड another_file.py में import another_file आपके मुख्य मॉड्यूल में है और another_file.foo से multiprocessing.Process पर है।

फिर भी, आप इसकी तुलना पी = subprocess.Popen (..) से कैसे करेंगे? क्या इससे कोई फर्क पड़ता है कि अगर मैं नई प्रक्रिया शुरू करता हूं (या मुझे 'पाइथन दुभाषिया उदाहरण' कहना चाहिए) subprocess.Popen (..) बनाम multiprocessing.Process (..)?

multiprocessing.Process() संभवतः subprocess.Popen() के शीर्ष पर लागू किया गया है। multiprocessing एपीआई प्रदान करता है जो threading एपीआई के समान है और यह पाइथन प्रक्रियाओं के बीच संचार के विवरण को दूर करता है (प्रक्रियाओं के बीच पाइथन ऑब्जेक्ट्स को क्रमबद्ध करने के लिए कैसे क्रमबद्ध किया जाता है)।

यदि कोई CPU गहन कार्य नहीं है तो आप एक ही प्रक्रिया में अपने जीयूआई और आई/ओ धागे चला सकते हैं। यदि आपके पास सीपीयू गहन कार्यों की एक श्रृंखला है तो एक साथ कई सीपीयू का उपयोग करने के लिए, या तो lxml, regex, numpy (या Cython का उपयोग करके बनाया गया कोई भी) के साथ कई धागे का उपयोग करें जो लंबे समय तक गणना के दौरान जीआईएल जारी कर सकते हैं या उन्हें ऑफ़लोड कर सकते हैं अलग प्रक्रियाओं में (एक आसान तरीका है एक प्रक्रिया पूल का उपयोग करना जैसे कि concurrent.futures द्वारा प्रदान किया गया)।

प्रश्न: समुदाय चर्चा ने एक नया प्रश्न उठाया। वहाँ जाहिरा तौर पर दो दृष्टिकोण जब (एक नई पायथन दुभाषिया उदाहरण के भीतर) एक नई प्रक्रिया को उत्पन्न करने हैं:

# Approach 1(a) 
p = subprocess.Popen(['python', mySubprocessPath], shell = True) 

# Approach 1(b) (J.F. Sebastian) 
p = subprocess.Popen([sys.executable, mySubprocessPath]) 

# Approach 2 
p = multiprocessing.Process(target=foo, args=(q,)) 

"दृष्टिकोण 1 (क)" (हालांकि यह विंडोज पर काम कर सकते हैं) POSIX पर गलत है। पोर्टेबिलिटी के लिए, "दृष्टिकोण 1 (बी)" का उपयोग करें जब तक आपको पता न हो कि आपको cmd.exe की आवश्यकता है (इस मामले में एक स्ट्रिंग पास करें, यह सुनिश्चित करने के लिए कि सही कमांड-लाइन एस्केपिंग का उपयोग किया जाता है)।

दूसरे दृष्टिकोण में स्पष्ट नकारात्मकता है कि यह केवल एक कार्य को लक्षित करता है - जबकि मुझे एक नई पायथन लिपि खोलने की आवश्यकता है। वैसे भी, क्या दोनों दृष्टिकोण प्राप्त होते हैं जो वे प्राप्त करते हैं?

subprocess नई प्रक्रियाओं बनाता है, किसी भी प्रक्रियाओं जैसे, आप एक bash स्क्रिप्ट चलाने सकता है। multprocessing किसी अन्य प्रक्रिया में पायथन कोड चलाने के लिए उपयोग किया जाता है। यह आयात एक पायथन मॉड्यूल को अधिक लचीला है और एक स्क्रिप्ट के रूप में इसे चलाने के लिए की तुलना में अपने कार्य चलाते हैं। Call python script with input with in a python script using subprocess देखें।

3

चूंकि आप threading मॉड्यूल का उपयोग कर रहे हैं जो thread पर बना है। जैसा कि प्रलेखन सुझाव देता है, यह आपके ओएस के 'POSIX थ्रेड कार्यान्वयन' 'pthread का उपयोग करता है।

  1. धागे पायथन दुभाषिया के बजाय ओएस द्वारा प्रबंधित किए जाते हैं। तो जवाब आपके सिस्टम में पाथ्रेड लाइब्रेरी पर निर्भर करेगा। हालांकि, सीपीथॉन कई धागे को पाइथन बाइटकोड को निष्पादित करने से रोकने के लिए जीआईएल का उपयोग करता है। तो वे अनुक्रमित किया जाएगा। लेकिन फिर भी उन्हें अलग-अलग कोरों में अलग किया जा सकता है, जो आपके pthread libs पर निर्भर करता है।
  2. बस एक डीबगर का उपयोग करें और इसे अपने python.exe से संलग्न करें। उदाहरण के लिए GDB thread command
  3. प्रश्न 1 के समान, नई प्रक्रिया आपके ओएस द्वारा प्रबंधित की जाती है और शायद एक अलग कोर पर चल रही है। इसे देखने के लिए डीबगर या किसी भी प्रक्रिया मॉनिटर का प्रयोग करें। अधिक जानकारी के लिए, CreatProcess() दस्तावेज़ीकरण page पर जाएं।
1

1, 2: आप तीन असली सूत्र है, लेकिन CPython में वे Gil द्वारा सीमित हैं, इसलिए, यह मानते हुए वे शुद्ध अजगर चला रहे हैं, कोड आप CPU उपयोग देखेंगे के रूप में यदि केवल एक कोर का इस्तेमाल किया।

3: के रूप में कहा gdlmx उस पर, एक धागा को चलाने के लिए एक कोर का चयन करने के लिए ओएस के लिए है, लेकिन आप वास्तव में नियंत्रण की जरूरत है, तो आप ctypes के माध्यम से देशी एपीआई का उपयोग कर प्रक्रिया या धागे आत्मीयता सेट कर सकते हैं। जब से तुम विंडोज पर हैं, यह इस तरह होगा:

# This will run your subprocess on core#0 only 
p = subprocess.Popen(['python', mySubprocessPath], shell = True) 
cpu_mask = 1 
ctypes.windll.kernel32.SetProcessAffinityMask(p._handle, cpu_mask) 

मैं simplicty के लिए यहां निजी Popen._handle का उपयोग करें। स्वच्छ तरीका OpenProcess(p.tid) आदि

और हाँ, subprocess अन्य नई प्रक्रिया में अन्य सभी की तरह अजगर चलाता है।

+0

(3) पूरी तरह से काम करता है। इसके बिना, सभी कोरों के चारों ओर एक साधारण एकल थ्रेडेड व्यस्त पाश फेंक दिया जाता है; उस कोड के साथ, यह स्थायी रूप से कोर # 0 पर है।मुझे कोई जानकारी नहीं है कि यह हमेशा उपयोगी है, लेकिन शायद एक कोर पर एक महत्वपूर्ण धागा रखने के लिए कुछ कैश से संबंधित कारण हैं। – max

संबंधित मुद्दे