5

के साथ क्यों रुक गया है सबसे पहले मुझे यकीन नहीं था कि मुझे इसे उबंटू प्रश्न या यहां पोस्ट करना चाहिए या नहीं। लेकिन मुझे लगता है कि यह एक ओएस की तुलना में एक पायथन प्रश्न का अधिक है।मेरा पायथन ऐप 'सिस्टम'/कर्नेल CPU समय

मेरा पायथन एप्लिकेशन 64 कोर एएमडी सर्वर पर उबंटू के शीर्ष पर चल रहा है। यह ctypes के माध्यम से एक .so से कॉल करके नेटवर्क पर 5 गीगा कैमरों से छवियों को खींचता है और फिर उन्हें संसाधित करता है। मुझे अपने एप्लिकेशन में लगातार विराम दिखाई दे रहा है जिससे कैमरों से फ्रेम को बाहरी कैमरा लाइब्रेरी द्वारा छोड़ा जा सकता है।

इसे डीबग करने के लिए मैंने लोकप्रिय psutil पायथन पैकेज का उपयोग किया है जिसके साथ मैं अलग-अलग थ्रेड में प्रत्येक 0.2 सेकंड में CPU आंकड़े लॉग आउट करता हूं। मैं उस धागे में 0.2 सेकंड के लिए सोता हूं और जब वह नींद काफी अधिक समय लेती है तो मुझे कैमरे के फ्रेम भी गिराए जाते हैं। मैंने देखा है कि 17 सेकंड तक रुक गया है! मेरी अधिकांश प्रसंस्करण या तो ओपनसीवी या न्यूम्पी (दोनों जिनमें जीआईएल रिलीज होती है) या ऐप के एक हिस्से में multiprocessing.Pool 59 प्रक्रियाओं के साथ (यह पाइथन जीआईएल के आसपास पहुंचने के लिए) है।

मेरा डीबग लॉगिंग बहुत अधिक 'सिस्टम' (यानी कर्नेल) CPU समय को मेरे कई प्रक्रियाओं के धागे पर रोकता है जब विराम होता है।

उदाहरण के लिए। मैं सीपीयू टाइम्स को निम्नानुसार देखता हूं (आमतौर पर प्रत्येक 0.2 सेकंड) और फिर अचानक एक बड़ी छलांग ('प्रक्रिया' संख्या सीपीयू उपयोग में होती है, यानी 1 सीपीयू पूरी तरह से इस्तेमाल किया जाएगा 1, लिनक्स top दिखा रहा है 123% 1.2 होगा):

Process user | Process system | OS system % | OS idle % 
19.9   | 10.5   | 6   | 74 
5.6   | 2.3   | 4   | 87 
6.8   | 1.7   | 11   | 75 
4.6   | 5.5   | 43   | 52 
0.5   | 26.4   | 4   | 90 

मुझे नहीं पता कि उच्च ओएस सिस्टम उपयोग उच्च प्रक्रिया प्रणाली के उपयोग से मेल खाने से पहले एक पंक्ति की सूचना क्यों दी जाती है। 64 कोर = 41% के 26.4 के बाद से दो मैच ऊपर। उस समय मेरे एप्लिकेशन ने लगभग 3.5 सेकंड पॉज़ (जैसा कि मेरे सीपीयू जानकारी लॉगिंग थ्रेड द्वारा ओपनसीवी के cv2.getTickCount() का उपयोग करके और पायथन लॉगिंग आउटपुट में टाइम स्टैम्प में कूदने के लिए निर्धारित किया) कई कैमरा फ्रेम को छोड़ने का कारण बन गया।

जब ऐसा होता है तो मैंने अपनी प्रक्रिया के प्रत्येक थ्रेड के लिए सीपीयू जानकारी भी लॉग की है। ऊपर दिए गए उदाहरण के लिए 25 थ्रेड एक सिस्टम 'सीपीयू उपयोग 0.9 पर और कुछ और 0.6 पर चल रहे थे, जो ऊपर 26.4 की प्रक्रिया के लिए कुल मिलाकर मिलता है। उस बिंदु पर लगभग 183 धागे चल रहे थे।

यह विराम आमतौर पर मल्टीप्रोसेसिंग पूल के उपयोग के करीब होता है (इसका उपयोग छोटे विस्फोटों के लिए किया जाता है) लेकिन पूल का उपयोग होने पर हर बार ऐसा नहीं होता है। इसके अलावा, अगर मैं पूल के बाहर होने वाली प्रसंस्करण की मात्रा को कम करता हूं तो कोई कैमरा छोड़ना नहीं होता है।

प्रश्न: मैं कैसे निर्धारित कर सकता हूं कि ओएस 'सिस्टम'/कर्नेल समय अचानक छत के माध्यम से क्यों जाता है? एक पायथन ऐप में ऐसा क्यों होगा?

और सबसे महत्वपूर्ण बात यह है कि कोई विचार क्यों हो रहा है और इससे कैसे बचें?

नोट्स:

  • इस रूट के रूप में चलाता है से upstart
  • कैमरों ऐप पुन: प्रारंभ (नवोदय में respawn का उपयोग) बंद कर दिया जाता है (यह करने के लिए कैमरे दुर्भाग्य से पुस्तकालय के लिए है) और इसे एक से अधिक होता है एक दिन में, इसलिए यह लंबे समय तक चलने के कारण नहीं है, मैंने यह भी देखा है कि प्रक्रिया शुरू होने के तुरंत बाद यह होता है
  • यह वही कोड चलाया जा रहा है, यह मेरे कोड
  • की एक अलग शाखा चलाने के कारण नहीं है
  • वर्तमान में -2 के एक nice है, मैं हटाने से कोई साथ nice
  • उबंटू 12.04.5 LTS को प्रभावित
  • अजगर 2.7
  • मशीन स्मृति की 128GB है जो मैं
+0

क्या आपने यह देखने के लिए प्रोफाइलिंग करने का प्रयास किया है कि आपका कोड कहां व्यतीत कर रहा है? https://docs.python.org/2/library/profile.html – bsa

+0

cProfile केवल एक थ्रेडेड है और जबकि यप्पी बहुप्रचारित है, मुझे लगता है कि यह लटकता है। मुझे प्रत्येक थ्रेड में एक सीप्रोफाइलर जोड़ना होगा, अपने आंकड़ों को एकसाथ इकट्ठा करना होगा और उन्हें हर समय साफ़ करने का समन्वय करना होगा क्योंकि मुझे इन सामयिक विरामों के दौरान केवल प्रोफ़ाइल आंकड़े चाहिए (यह लगातार सामान्य चलने के शोर में जवाब खो देगा)। कोशिश की जा सकती है लेकिन समस्याग्रस्त लगता है। मान लीजिए कि अगर कुछ और नहीं हो जाता तो मैं वहां जाऊंगा। –

उत्तर

7
का उपयोग कर के पास कोई कहाँ हूँ की कोशिश की है

ठीक है। मेरे पास अपने प्रश्न का उत्तर है। हां, इसे दूर करने के लिए मुझे 3 महीने से अधिक समय लगेगा।

ऐसा लगता है कि पाइथन में जीआईएल थ्रैशिंग है जो बड़े पैमाने पर 'सिस्टम' सीपीयू स्पाइक्स और संबंधित विरामों का कारण है। यहां एक good explanation of where the thrashing comes from है। उस प्रस्तुति ने मुझे सही दिशा में भी इंगित किया।

पायथन 3.2 introduced a new GIL implementation इस थ्रैशिंग से बचने के लिए।

from threading import Thread 
import psutil 

def countdown(): 
    n = 100000000 
    while n > 0: 
     n -= 1 

t1 = Thread(target=countdown) 
t2 = Thread(target=countdown) 
t1.start(); t2.start() 
t1.join(); t2.join() 

print(psutil.Process().cpu_times())  

पर मेरी मैकबुक प्रो अजगर 2.7.9 इस 'प्रणाली' के 'उपयोगकर्ता CPU के 14.7s और 13.2s का उपयोग करता है के साथ: परिणाम एक सरल लड़ी उदाहरण (ऊपर प्रस्तुति से लिया गया) के साथ दिखाया जा सकता है सी पी यू।

पायथन 3.4 'उपयोगकर्ता' के 15.0 (थोड़ा और) का उपयोग करता है लेकिन केवल 0.2 सिस्टम 'सिस्टम' का उपयोग करता है।

तो, जीआईएल अभी भी जगह पर है, फिर भी यह केवल तभी चलता है जब कोड सिंगल थ्रेडेड होता है, लेकिन यह पाइथन 2 की सभी जीआईएल विवाद से बचाता है जो कर्नेल ('सिस्टम') CPU समय के रूप में प्रकट होता है। मेरा विवाद, मेरा मानना ​​है कि मूल प्रश्न के मुद्दों का कारण क्या था।

अद्यतन

सीपीयू समस्या पर एक अतिरिक्त कारण OpenCV/TBB साथ हो पाया था। इस SO question में पूरी तरह से प्रलेखित।

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