आपके लक्ष्य हैं:
- अपने काम को कई मशीनों में वितरित करें (कंप्यूटिंग / वितरित समानांतर प्रसंस्करण वितरित)
- सभी सीपीयू (मल्टीप्रोसेसिंग / थ्रेडिंग) में किसी दिए गए मशीन पर काम वितरित करें
अजवाइन इन दोनों को आपके लिए काफी आसानी से कर सकता है। समझने वाली पहली बात यह है कि प्रत्येक सेलेरी कार्यकर्ता को डिफ़ॉल्ट रूप से कई कार्यों के लिए कॉन्फ़िगर किया गया है क्योंकि एक सिस्टम पर सीपीयू कोर उपलब्ध हैं:
कॉनकरीर, प्रीफ़ॉर्क वर्कर प्रक्रिया की संख्या है जो आपके कार्यों को समवर्ती रूप से संसाधित करने के लिए उपयोग की जाती है, जब ये सभी कार्य करने में व्यस्त हैं नए कार्यों को संसाधित होने से पहले समाप्त होने के लिए किसी एक कार्य के लिए इंतजार करना होगा।
डिफ़ॉल्ट कॉन्सेप्ट नंबर उस मशीन पर सीपीयू की संख्या है (कोर सहित) , आप -c विकल्प का उपयोग करके एक कस्टम नंबर निर्दिष्ट कर सकते हैं। कोई अनुशंसित मूल्य नहीं है, क्योंकि इष्टतम संख्या कई कारकों पर निर्भर करती है, लेकिन अगर आपके कार्य ज्यादातर I / O- बाध्य हैं, तो आप इसे बढ़ाने की कोशिश कर सकते हैं, प्रयोग से पता चला है कि CPU की संख्या की तुलना में दोगुना से अधिक जोड़ना संभव नहीं है। प्रभावी, और इसके बजाय प्रदर्शन को नीचा दिखाने की संभावना है।
इसका अर्थ है कि प्रत्येक व्यक्तिगत कार्य को कई सीपीयू / कोर के उपयोग के लिए मल्टीप्रोसेसिंग / थ्रेडिंग का उपयोग करने के बारे में चिंता करने की आवश्यकता नहीं है। इसके बजाय, अजवाइन प्रत्येक उपलब्ध सीपीयू का उपयोग करने के लिए समवर्ती रूप से पर्याप्त कार्य चलाएगा।
उस रास्ते से, अगला कदम एक ऐसा कार्य बनाना है जो आपके कुछ सबसेट को संसाधित करने का काम करता है list_of_millions_of_ids
। आपके पास यहां कुछ विकल्प हैं - एक है प्रत्येक कार्य को एक ही आईडी संभालना है, इसलिए आप एन कार्यों को चलाते हैं, जहां N == len(list_of_millions_of_ids)
। यह गारंटी देगा कि काम आपके सभी कार्यों के बीच समान रूप से वितरित किया गया है, क्योंकि कभी भी ऐसा मामला नहीं होगा जहां एक कार्यकर्ता जल्दी खत्म होता है और बस इंतजार कर रहा है; अगर इसे काम की जरूरत है, तो यह कतार से एक आईडी खींच सकता है। आप एक अजवाइन का उपयोग करके ऐसा कर सकते हैं (जॉन डो द्वारा वर्णित) group
।
कार्यशो:
@app.task
def process_id(item):
id = item
database.objects(newid=id).save()
और कार्यों को निष्पादित करने के लिए:
from celery import group
from tasks import process_id
jobs = group(process_id.s(item) for item in list_of_millions_of_ids)
result = jobs.apply_async()
एक अन्य विकल्प सूची को छोटे टुकड़ों में तोड़ना है, और अपने श्रमिकों को टुकड़े वितरित करना है। यह दृष्टिकोण कुछ चक्रों को बर्बाद करने का जोखिम चलाता है, क्योंकि आप कुछ श्रमिकों के साथ इंतजार कर सकते हैं जबकि अन्य अभी भी काम कर रहे हैं। हालाँकि, अजवाइन के दस्तावेज़ीकरण से पता चलता है कि यह चिंता अक्सर निराधार है:
कुछ लोग चिंता कर सकते हैं कि आपके कार्यों को करने से समानता का क्षरण हो सकता है, लेकिन यह व्यस्त क्लस्टर के लिए शायद ही कभी सच होता है और व्यवहार में जब आप मैसेजिंग के ओवरहेड से बच रहे होते हैं तो इससे प्रदर्शन में वृद्धि हो सकती है।
इसलिए, आप यह जान सकते हैं कि सूची को चट कर जाना और प्रत्येक कार्य को चंक्स वितरित करना बेहतर प्रदर्शन करता है, क्योंकि संदेश की अधिकता कम हो जाती है। आप संभवतः डेटाबेस पर लोड को इस तरह से थोड़ा हल्का कर सकते हैं, प्रत्येक आईडी की गणना करके, इसे एक सूची में संग्रहीत कर सकते हैं, और फिर एक बार में एक आईडी करने के बजाय पूरी सूची को डीबी में जोड़ सकते हैं। । चौका देने वाला तरीका कुछ इस तरह दिखेगा
कार्यशो:
@app.task
def process_ids(items):
for item in items:
id = item
database.objects(newid=id).save()
और कार्य शुरू करने के लिए:
from tasks import process_ids
jobs = process_ids.chunks(list_of_millions_of_ids, 30)
jobs.apply_async()
आप इस बात पर थोड़ा प्रयोग कर सकते हैं कि किस आकार का हिस्सा आपको सबसे अच्छा परिणाम देता है। आप एक मीठा स्थान ढूंढना चाहते हैं, जहां आप मैसेजिंग ओवरहेड को काट रहे हैं, साथ ही आकार को भी छोटा रखते हुए कि आप श्रमिकों को किसी अन्य कार्यकर्ता की तुलना में बहुत तेजी से खत्म नहीं कर रहे हैं, और फिर बस कुछ भी नहीं करने के लिए इंतजार कर रहे हैं।