नोट: यह दृष्टिकोण विंडोज़ पर काम नहीं करता है और यह केवल लिनक्स पर परीक्षण किया जाता है।
multiprocessing.Process
का उपयोग करना: जब Process()
का उपयोग कर प्रत्येक प्रक्रिया के लिए एक भौतिक कोर नियत
काफी आसान है। आप taskset -p [mask] [pid]
का उपयोग कर पाश कि दोहराता प्रत्येक कोर गर्त के लिए एक बना सकते हैं और नए कोर करने के लिए नई प्रक्रिया प्रदान करती है कर सकते हैं:
import multiprocessing
import os
def foo():
return
if __name__ == "__main__" :
for process_idx in range(multiprocessing.cpu_count()):
p = multiprocessing.Process(target=foo)
os.system("taskset -p -c %d %d" % (process_idx % multiprocessing.cpu_count(), os.getpid()))
p.start()
मैं अपने कार्य केंद्र पर 32 कोर है इसलिए मैं यहाँ आंशिक परिणामों डाल देता हूँ:
pid 520811's current affinity list: 0-31
pid 520811's new affinity list: 0
pid 520811's current affinity list: 0
pid 520811's new affinity list: 1
pid 520811's current affinity list: 1
pid 520811's new affinity list: 2
pid 520811's current affinity list: 2
pid 520811's new affinity list: 3
pid 520811's current affinity list: 3
pid 520811's new affinity list: 4
pid 520811's current affinity list: 4
pid 520811's new affinity list: 5
...
जैसा कि आप देखते हैं, यहां प्रत्येक प्रक्रिया के पिछले और नए संबंध हैं। पहला कोर सभी कोर (0-31) के लिए है और फिर कोर 0 को सौंपा गया है, दूसरी प्रक्रिया डिफ़ॉल्ट रूप से कोर 0 को सौंपा गया है और फिर इसका संबंध अगले कोर (1) में बदल दिया गया है, और बहुत आगे।
multiprocessing.Pool
का उपयोग करना:
चेतावनी: इस तरीके pool.py
मॉड्यूल में सुधार करने की जरूरत है के बाद से वहाँ कोई रास्ता नहीं है कि मैं इस बात का पता है कि तुम Pool()
से पीआईडी निकाल सकते हैं है। इसके अलावा इस परिवर्तन का परीक्षण python 2.7
और multiprocessing.__version__ = '0.70a1'
पर किया गया है।
Pool.py
में, उस रेखा को खोजें जहां _task_handler_start()
विधि कहा जा रहा है। अगली पंक्ति में, आप प्रक्रिया पूल में एक "भौतिक" कोर के लिए प्रयोग कर दे सकते हैं (मैं import os
यहाँ रखा ताकि पाठक यह आयात करने के लिए भूल जाते हैं नहीं है):
import os
for worker in range(len(self._pool)):
p = self._pool[worker]
os.system("taskset -p -c %d %d" % (worker % cpu_count(), p.pid))
और आप कर रहे हैं किया हुआ।टेस्ट:
import multiprocessing
def foo(i):
return
if __name__ == "__main__" :
pool = multiprocessing.Pool(multiprocessing.cpu_count())
pool.map(foo,'iterable here')
परिणाम:
pid 524730's current affinity list: 0-31
pid 524730's new affinity list: 0
pid 524731's current affinity list: 0-31
pid 524731's new affinity list: 1
pid 524732's current affinity list: 0-31
pid 524732's new affinity list: 2
pid 524733's current affinity list: 0-31
pid 524733's new affinity list: 3
pid 524734's current affinity list: 0-31
pid 524734's new affinity list: 4
pid 524735's current affinity list: 0-31
pid 524735's new affinity list: 5
...
ध्यान दें कि pool.py
को यह संशोधन कोर को काम देना राउंड robinly। इसलिए यदि आप सीपीयू-कोर की तुलना में अधिक नौकरियां सौंपते हैं, तो आप उनमें से कई को एक ही कोर पर समाप्त कर देंगे।
संपादित करें:
क्या ओ पी की तलाश में है एक pool()
कि विशिष्ट कोर पर पूल घूर करने में सक्षम है है। multiprocessing
पर इस और अधिक बदलावों की आवश्यकता है (पहले उल्लिखित परिवर्तन पूर्ववत करें)।
चेतावनी:
कॉपी-पेस्ट करने के लिए कार्यशील परिभाषाएँ और फ़ंक्शन कॉल कोशिश मत करो। केवल उस भाग को पेस्ट करें जिसे self._worker_handler.start()
के बाद जोड़ा जाना चाहिए (आप इसे नीचे देखेंगे)। ध्यान दें कि मेरी multiprocessing.__version__
मुझसे कहता संस्करण '0.70a1'
है, लेकिन यह बात जब तक तुम सिर्फ तुम क्या जोड़ने की जरूरत है जोड़ने के रूप में नहीं करता है:
multiprocessing
के pool.py
:
__init__()
करने के लिए एक cores_idx = None
तर्क जोड़ने परिभाषा।
def __init__(self, processes=None, initializer=None, initargs=(),
maxtasksperchild=None,cores_idx=None)
भी आप self._worker_handler.start()
के बाद निम्नलिखित कोड जोड़ने चाहिए:: मेरे संस्करण में यह यह जोड़ने के बाद इस तरह दिखता है
if not cores_idx is None:
import os
for worker in range(len(self._pool)):
p = self._pool[worker]
os.system("taskset -p -c %d %d" % (cores_idx[worker % (len(cores_idx))], p.pid))
multiprocessing
के __init__.py
:
एक cores_idx=None
तर्क जोड़े रिटर्न भाग में Pool()
के साथ-साथ अन्य Pool()
फ़ंक्शन कॉल की परिभाषा के लिए। मेरे संस्करण में ऐसा लगता है:
def Pool(processes=None, initializer=None, initargs=(), maxtasksperchild=None,cores_idx=None):
'''
Returns a process pool object
'''
from multiprocessing.pool import Pool
return Pool(processes, initializer, initargs, maxtasksperchild,cores_idx)
और आप कर चुके हैं। निम्न उदाहरण कोर 0 पर 5 कर्मचारियों की एक पूल और 2 चलाता है केवल:
import multiprocessing
def foo(i):
return
if __name__ == "__main__":
pool = multiprocessing.Pool(processes=5,cores_idx=[0,2])
pool.map(foo,'iterable here')
परिणाम:
pid 705235's current affinity list: 0-31
pid 705235's new affinity list: 0
pid 705236's current affinity list: 0-31
pid 705236's new affinity list: 2
pid 705237's current affinity list: 0-31
pid 705237's new affinity list: 0
pid 705238's current affinity list: 0-31
pid 705238's new affinity list: 2
pid 705239's current affinity list: 0-31
pid 705239's new affinity list: 0
बेशक आप अभी भी cores_idx
को हटाने के द्वारा के रूप में अच्छी multiprocessing.Poll()
के सामान्य कार्यक्षमता हो सकता है तर्क।
@ GáborErdős लेकिन करता है कि पूल सभी * शारीरिक * कोर या सिर्फ पहले चार कोर? – user189035
@ गैबरएर्डो: क्या आप निश्चित हैं? 'आयात psutils' 'psutil.cpu_count (तार्किक = झूठा) 'अंतर को जानना प्रतीत होता है। – user189035
@ युगी: नहीं, मुझे नहीं लगता कि यह एक डुप्लिकेट है, हालांकि मेरा प्रश्न गलत तरीके से तैयार किया गया हो सकता है (उसमें 'सभी' भाग पर एक अनुचित जोर दिया गया था)। – user189035