प्रसंग नई लिनक्स गुठली में बहुत धीमा है


99

हम Ubuntu 10.04 LTS से Ubuntu 12.04 LTS तक अपने सर्वर पर OS अपग्रेड करना चाह रहे हैं। दुर्भाग्य से, ऐसा लगता है कि एक धागा जो कि चलने योग्य हो गया है उसे चलाने के लिए विलंबता 2.6 कर्नेल से 3.2 कर्नेल तक बढ़ गई है। वास्तव में हमें प्राप्त होने वाली विलंबता संख्या पर विश्वास करना कठिन है।

मुझे परीक्षण के बारे में और अधिक विशिष्ट होने दें। हमारे पास एक कार्यक्रम है जो दो धागे चलाता है। पहले थ्रेड को वर्तमान समय (RDCS का उपयोग करके टिक्स) में मिलता है और फिर एक सेकंड में एक बार स्थिति चर का संकेत देता है। दूसरा धागा स्थिति चर पर इंतजार करता है और संकेत मिलने पर जाग जाता है। इसके बाद यह वर्तमान समय (RDCS का उपयोग करके टिक्स में) प्राप्त करता है। दूसरे धागे में समय और पहले धागे में समय के बीच का अंतर गणना और कंसोल पर प्रदर्शित होता है। इसके बाद दूसरा धागा स्थिति चर पर एक बार फिर इंतजार करता है। यह लगभग एक सेकंड के बाद पहले धागे द्वारा फिर से संकेत दिया जाएगा।

इसलिए, संक्षेप में, हमें परिणाम के रूप में एक बार दूसरी बार स्थिति चर विलंबता माप के माध्यम से थ्रेड संचार के लिए एक धागा मिलता है ।

कर्नेल 2.6.32 में, यह विलंबता 2.8-3.5 के आदेश पर कहीं है, जो उचित है। कर्नेल 3.2.0 में, यह विलंबता 40-100 के ऑर्डर पर कहीं बढ़ गई है। मैंने दोनों मेजबानों के बीच हार्डवेयर के किसी भी अंतर को शामिल नहीं किया है। वे समान हार्डवेयर (दोहरे सॉकेट X5687 {Westmere-EP) प्रोसेसर पर चलते हैं जो हाइपरथ्रेडिंग, स्पीडस्टेप और सभी सी राज्यों को बंद करने के साथ 3.6 गीगाहर्ट्ज पर चल रहे हैं)। परीक्षण ऐप उन्हें एक ही सॉकेट के स्वतंत्र भौतिक कोर पर चलाने के लिए थ्रेड्स की आत्मीयता को बदलता है (यानी, पहला धागा कोर 0 पर चलाया जाता है और दूसरा धागा कोर 1 पर चलाया जाता है), इसलिए थ्रेड्स का कोई उछाल नहीं है कुर्सियां ​​के बीच कोर या उछल / संचार।

दोनों मेजबानों के बीच एकमात्र अंतर यह है कि एक Ubuntu 10.04 LTS को कर्नेल 2.6.32-28 (तेज संदर्भ स्विच बॉक्स) के साथ चला रहा है और दूसरा कर्नेल 3.2.0-23 के साथ नवीनतम Ubuntu 12.04 LTS चला रहा है (धीमा संदर्भ स्विच बॉक्स)। सभी BIOS सेटिंग्स और हार्डवेयर समान हैं।

क्या कर्नेल में कोई बदलाव हुआ है जो इस हास्यास्पद धीमी गति का हिसाब कर सकता है कि इसे चलाने में कितना समय लगता है?

अद्यतन: यदि आप अपने होस्ट और लिनक्स बिल्ड पर परीक्षण चलाना चाहते हैं, तो मैंने आपके इनकार के लिए कोड को पास्टबिन में पोस्ट किया है । संकलन:

g++ -O3 -o test_latency test_latency.cpp -lpthread

साथ चलाएं (यह मानते हुए कि आपके पास कम से कम एक दोहरे कोर बॉक्स है):

./test_latency 0 1 # Thread 1 on Core 0 and Thread 2 on Core 1

अद्यतन 2 : कर्नेल मापदंडों के माध्यम से बहुत खोज करने के बाद, कर्नेल परिवर्तन और व्यक्तिगत शोध पर पोस्ट, मुझे पता चला है कि समस्या क्या है और इस प्रश्न के उत्तर के रूप में समाधान पोस्ट किया है।


1
बस एक अनुमान है, लेकिन शायद एक पैरामीटर को बदलने से /proc/sys/kernel/*काम हो सकता है? यदि आपको ऐसा कुछ मिलता है, जो काम करता है, तो उस कॉन्फ़िगरेशन /etc/sysctl.confया फ़ाइल /etc/sysctl.d/को रिबूट के पार बनाए रखने के लिए रखें।
कार्लोस कैंपड्रेस

1
मैंने दोनों मेजबानों के बीच / खरीद / sys / कर्नेल की तुलना की, लेकिन कोई सार्थक अंतर नहीं देखा, विशेष रूप से किसी भी शेड्यूलिंग संबंधित कॉन्फ़िगरेशन आइटम में।
माइकल गोल्डसेन

मैं अस्पष्ट रूप से एक अफवाह को याद करता हूं कि आरडीटीसीटी को कोर के बीच ठीक से सिंक्रनाइज़ नहीं किया गया है, लेकिन मुझे उम्मीद है कि अगर यह एक मुद्दा था तो आप समय उलट देख रहे होंगे। क्या आपने एक ही कोर पर दोनों धागे को चलाने के लिए संपन्नता की कोशिश की है और देखते हैं कि क्या होता है?
डेविड

इंटेल इस नए कोर पर, आरडीसीटी कोर के पार निर्दोष रूप से काम करता है, विशेष रूप से एक ही सीपीयू (यानी, एक ही सॉकेट) पर कोर। दिलचस्प बात यह है कि यदि दोनों धागे एक ही कोर पर चलाए जाते हैं, तो विलंबता नए कर्नेल पर लगभग 4-10 तक जाती है और लगभग। 3 हमें पुराने कर्नेल पर।
माइकल गोल्डसेन

बस एक सामान्य टिप्पणी - टीएससीएस पर सिंक्रनाइज़ होने के लिए निर्भर करना सबसे अच्छा है, हालांकि आपके विशिष्ट मामले में, चूंकि आप एक भौतिक चिप पर दो कोर का उपयोग कर रहे हैं, इसलिए इसे वास्तव में काम करना चाहिए।
ट्वेलबर्ग

जवाबों:


95

हाल की गुठली में खराब धागे के जागने के प्रदर्शन की समस्या का समाधान intel_idlecpuidle ड्राइवर के लिए स्विच के साथ करना है acpi_idle, पुराने कर्नेल में उपयोग किए गए ड्राइवर। अफसोस की बात है, intel_idleड्राइवर सी-राज्यों के लिए उपयोगकर्ता के BIOS कॉन्फ़िगरेशन को अनदेखा करता है और अपनी धुन पर नृत्य करता है । दूसरे शब्दों में, भले ही आप अपने पीसी (या सर्वर के) BIOS में सभी सी राज्यों को पूरी तरह से अक्षम कर देते हैं, यह ड्राइवर अभी भी उन्हें संक्षिप्त निष्क्रियता की अवधि के दौरान मजबूर करेगा, जो लगभग हमेशा हो रहे हैं जब तक कि सभी कोर खपत सिंथेटिक बेंचमार्क (जैसे, तनाव) ) दौड रहा है। आप प्रोसेसर की आवृत्तियों से संबंधित अन्य उपयोगी जानकारी के साथ-साथ अधिकांश संगत हार्डवेयर पर अद्भुत Google i7z टूल का उपयोग करके सी स्टेट ट्रांज़िशन की निगरानी कर सकते हैं ।

आपके सेटअप में वर्तमान में कौन सा cpuidle ड्राइवर सक्रिय है, यह देखने के लिए, current_driverफ़ाइल को निम्नानुसार cpuidleअनुभाग में दर्ज करें /sys/devices/system/cpu:

cat /sys/devices/system/cpu/cpuidle/current_driver

यदि आप चाहते हैं कि आपका आधुनिक लिनक्स ओएस सबसे कम संदर्भ स्विच विलंबता संभव है, तो इन सभी बचत बचत को अक्षम करने के लिए निम्न कर्नेल बूट पैरामीटर जोड़ें:

उबंटू 12.04 पर, आप उन्हें GRUB_CMDLINE_LINUX_DEFAULTप्रविष्टि में जोड़कर /etc/default/grubऔर फिर चलाकर ऐसा कर सकते हैं update-grub। जोड़ने के लिए बूट पैरामीटर हैं:

intel_idle.max_cstate=0 processor.max_cstate=0 idle=poll

तीन बूट विकल्प क्या करते हैं, इसके बारे में यहाँ विवरण दिए गए हैं:

intel_idle.max_cstateशून्य पर सेट करना या तो आपके cpuidle ड्राइवर को acpi_idle(विकल्प के प्रलेखन के अनुसार कम से कम) वापस लौटा देगा , या इसे पूरी तरह से अक्षम कर देगा। मेरे बॉक्स पर यह पूरी तरह से अक्षम है (यानी, आउटपुट का उत्पादन करने के लिए current_driverफ़ाइल प्रदर्शित करना )। इस मामले में दूसरा बूट विकल्प, अनावश्यक है। हालाँकि, दस्तावेज़ में कहा गया है कि ड्राइवर के लिए max_cstate को शून्य पर सेट करने से ड्राइवर को OS वापस करना चाहिए । इसलिए, मैं केवल मामले में दूसरे बूट विकल्प में डालता हूं।/sys/devices/system/cpu/cpuidlenoneprocessor.max_cstate=0intel_idleacpi_idle

processor.max_cstateविकल्प के लिए अधिकतम सी राज्य सेट acpi_idleउम्मीद है कि यह रूप में अच्छी तरह अक्षम, शून्य करने के लिए ड्राइवर। मेरे पास एक प्रणाली नहीं है कि मैं इस पर परीक्षण कर सकता हूं, क्योंकि intel_idle.max_cstate=0पूरी तरह से मेरे लिए उपलब्ध हार्डवेयर के सभी पर cpuidle ड्राइवर को बाहर निकालता है। हालांकि, अगर आपकी स्थापना से आपको वापसी करता है intel_idleकरने के लिए acpi_idleसिर्फ पहला बूट विकल्प के साथ, मुझे पता है अगर दूसरा विकल्प, तो कृपया processor.max_cstateकिया जो यह है कि मैं इस सवाल का जवाब अद्यतन कर सकते हैं टिप्पणी में ऐसा करने प्रलेखित किया गया था।

अंत में, तीन मापदंडों में से अंतिम, idle=pollएक वास्तविक शक्ति हॉग है। यह C1 / C1E को अक्षम कर देगा, जो बहुत अधिक बिजली की खपत की कीमत पर अंतिम शेष बिट विलंबता को हटा देगा, इसलिए इसका उपयोग केवल तब करें जब यह वास्तव में आवश्यक हो। अधिकांश के लिए यह ओवरकिल होगा, क्योंकि सी 1 * विलंबता यह सब बड़ा नहीं है। मूल प्रश्न में वर्णित हार्डवेयर पर चल रहे मेरे परीक्षण एप्लिकेशन का उपयोग करते हुए, विलंबता 9 से 3 तक चली गई। यह निश्चित रूप से अत्यधिक विलंबता संवेदनशील अनुप्रयोगों (जैसे, वित्तीय व्यापार, उच्च परिशुद्धता टेलीमेट्री / ट्रैकिंग, उच्च फ्रीक। डेटा अधिग्रहण, आदि ...) के लिए एक महत्वपूर्ण कमी है, लेकिन विशाल बहुमत के लिए बिजली के हिट के लायक नहीं हो सकता है। डेस्कटॉप ऐप्स। सुनिश्चित करने के लिए पता करने का एकमात्र तरीका प्रदर्शन में आपके आवेदन के सुधार को प्रोफाइल करना है।

अपडेट करें:

विभिन्न साथ अतिरिक्त परीक्षण के बाद idle=*पैरामीटर, मैं ने पाया है कि स्थापित करने idleके लिए mwaitकरता है, तो आपके हार्डवेयर द्वारा समर्थित एक बेहतर विचार है। ऐसा लगता है कि MWAIT/MONITORनिर्देशों का उपयोग सीपीयू को सी 1 ई में प्रवेश करने की अनुमति देता है बिना किसी ध्यान देने योग्य विलंबता के थ्रेड वेक अप टाइम में जोड़ा जाता है। इसके साथ idle=mwait, आपको कूलर सीपीयू तापमान (तुलना में idle=poll), कम बिजली का उपयोग और फिर भी एक पोलिंग आइडियल लूप की उत्कृष्ट कम विलंबता को बनाए रखना होगा। इसलिए, इन निष्कर्षों के आधार पर कम सीपीयू थ्रेड जागता विलंबता के लिए मेरे अद्यतन अनुशंसित बूट मापदंडों का सेट है:

intel_idle.max_cstate=0 processor.max_cstate=0 idle=mwait

इसके idle=mwaitबजाय इसके उपयोग से idle=pollटर्बो बूस्ट (सीपीयू को उसकी TDP [थर्मल डिज़ाइन पावर] से नीचे रहने में मदद) और हाइपरथ्रेडिंग (जिसके लिए MWAIT एक संपूर्ण भौतिक कोर का उपभोग नहीं करने के लिए आदर्श तंत्र है) का उपयोग करने में मदद कर सकता है उच्च सी राज्यों से बचने का समय)। हालांकि, परीक्षण में यह साबित होना बाकी है, जो कि मैं करता रहूंगा।

अपडेट 2:

mwaitबेकार विकल्प दिया गया है नए 3.x कर्नेल से हटा (अद्यतन के लिए उपयोगकर्ता ck_ करने के लिए धन्यवाद)। दो विकल्पों के साथ हमें छोड़ देता है:

idle=halt- के रूप में अच्छी तरह से काम करना चाहिए mwait, लेकिन यह सुनिश्चित करने के लिए परीक्षण करें कि यह आपके हार्डवेयर के मामले में है। HLTअनुदेश लगभग एक के बराबर है MWAITराज्य संकेत 0. तथ्य यह है कि एक अवरोध एक HLT राज्य से बाहर निकलने के लिए आवश्यक है, एक स्मृति लिखने (या व्यवधान) MWAIT राज्य से बाहर निकलने के लिए इस्तेमाल किया जा सकता है, जबकि में समस्या झूठ के साथ। लिनक्स कर्नेल अपने निष्क्रिय लूप में क्या उपयोग करता है, इसके आधार पर, यह MWAIT को संभावित रूप से अधिक कुशल बना सकता है। इसलिए, जैसा कि मैंने कहा था कि परीक्षण / प्रोफाइल और देखें कि क्या यह आपकी विलंबता जरूरतों को पूरा करता है ...

तथा

idle=poll - बिजली और गर्मी की कीमत पर, उच्चतम प्रदर्शन विकल्प।


क्षमा करें, लेकिन आप फर्मवेयर द्वारा प्रबंधित किए जाने वाले सी राज्यों की अपेक्षा क्यों कर रहे थे? सस्पेंड स्टेट्स रनटाइम स्टेट्स हैं, और वे ओएस द्वारा डिज़ाइन द्वारा प्रबंधित होते हैं। जैसा कि आपने खोजा, यदि आप रनटाइम सस्पेंड नहीं करना चाहते हैं तो इसका उपयोग न करें।
एंडी रॉस

6
क्षमा करें, लेकिन C राज्यों, EIST और C1E को BIOS में बंद किया जा सकता है। मुझे उम्मीद है कि OS मेरी BIOS सेटिंग्स का सम्मान करेगा। यह विशेष रूप से सच है, इस मामले में भयावह टूलींग और प्रलेखन को देखते हुए।
माइकल गोल्डस्मिन

4
शायद अपने बायोस के माध्यम से बंद कर दिया। मैं एक प्रासंगिक कल्पना में कुछ भी नहीं जानता कि इसकी आवश्यकता है। क्षमा करें, लेकिन BIOS से कुछ भी "उम्मीद" आपको बार-बार काटने वाला है। आधुनिक पीसी में सबसे अच्छी बात फर्मवेयर कुछ भी नहीं कर सकता है। मुझे खेद है कि आप आश्चर्यचकित थे, लेकिन स्पष्ट रूप से यह उपयोगकर्ता की त्रुटि है। आपका बेंचमार्क सस्पेंड और रिज्यूम टाइम को माप रहा था।
एंडी रॉस

19
उपकरणों को सक्षम / अक्षम करने के लिए BIOS सुविधा चयन की भूमिकाओं में से एक है। कुछ मामलों में ये चयन ओएस (जैसे, मदरबोर्ड यूएसबी, ईएसएटीए और एनआईसी) पर मजबूर होते हैं। दूसरों में ओएस से आपकी इच्छाओं का सम्मान करने की उम्मीद की जाती है (जैसे, ईआईएसटी, सी स्टेट्स, हाइपरथ्रेडिंग, एक्सक्यूट डिसेबल, एईएस-एनआई, वर्चुअलाइजेशन, आदि ...)। BIOS एक केंद्रीय उपकरण / सुविधा चयन सतह प्रदान करता है जो OS तटस्थ है। यह उपयोगकर्ता को होस्ट पर कई (शायद बहुत अलग) ओएस स्थापित करने की अनुमति देता है जो सभी समान हार्डवेयर सुविधाओं का उपयोग करते हैं। हालाँकि, यह जवाब व्यक्तिपरक है इसलिए असहमत होने के लिए सहमत होना होगा।
माइकल गोल्डसेन

1
idle = mwait अब हाल ही में 3.x kernel lkml.org/lkml/2013/2/10/21 अन्य वैकल्पिक सलाह में समर्थित नहीं है ?
ck_

8

शायद जो धीमा हो गया है वह फ्यूटेक्स है, हालत चर के लिए बिल्डिंग ब्लॉक। यह कुछ प्रकाश डालेगा:

strace -r ./test_latency 0 1 &> test_latency_strace & sleep 8 && killall test_latency

फिर

for i in futex nanosleep rt_sig;do echo $i;grep $i test_latency_strace | sort -rn;done

जो समयानुसार क्रमबद्ध, दिलचस्प प्रणाली कॉल के लिए लिए गए माइक्रोसेकंड को दिखाएगा।

कर्नेल पर 2.6.32

$ for i in futex nanosleep rt_sig;do echo $i;grep $i test_latency_strace | sort -rn;done
futex
 1.000140 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000129 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000124 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000119 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000106 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000103 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000102 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 0.000125 futex(0x7f98ce4c0b88, FUTEX_WAKE_PRIVATE, 2147483647) = 0
 0.000042 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000038 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000037 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000030 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000029 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 0
 0.000028 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000027 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000018 futex(0x7fff82f0ec3c, FUTEX_WAKE_PRIVATE, 1) = 0
nanosleep
 0.000027 nanosleep({1, 0}, {1, 0}) = 0
 0.000019 nanosleep({1, 0}, {1, 0}) = 0
 0.000019 nanosleep({1, 0}, {1, 0}) = 0
 0.000018 nanosleep({1, 0}, {1, 0}) = 0
 0.000018 nanosleep({1, 0}, {1, 0}) = 0
 0.000018 nanosleep({1, 0}, {1, 0}) = 0
 0.000018 nanosleep({1, 0}, 0x7fff82f0eb40) = ? ERESTART_RESTARTBLOCK (To be restarted)
 0.000017 nanosleep({1, 0}, {1, 0}) = 0
rt_sig
 0.000045 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000040 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000038 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000035 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000034 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000033 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000032 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000032 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000031 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000031 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000028 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000028 rt_sigaction(SIGRT_1, {0x37f8c052b0, [], SA_RESTORER|SA_RESTART|SA_SIGINFO, 0x37f8c0e4c0}, NULL, 8) = 0
 0.000027 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000027 rt_sigaction(SIGRTMIN, {0x37f8c05370, [], SA_RESTORER|SA_SIGINFO, 0x37f8c0e4c0}, NULL, 8) = 0
 0.000027 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000025 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000025 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000023 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000023 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000022 rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
 0.000022 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000021 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000021 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000021 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000021 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000021 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000019 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0

कर्नेल पर 3.1.9

$ for i in futex nanosleep rt_sig;do echo $i;grep $i test_latency_strace | sort -rn;done
futex
 1.000129 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000126 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000122 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000115 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000114 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000112 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000109 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 0.000139 futex(0x3f8b8f2fb0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
 0.000043 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000041 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000037 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000036 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000034 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000034 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
nanosleep
 0.000025 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000022 nanosleep({1, 0}, {0, 3925413}) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
 0.000021 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
rt_sig
 0.000045 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000044 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000043 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000040 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000038 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000037 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000036 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000036 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000035 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000035 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000035 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000035 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000034 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000031 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000027 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000027 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000027 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000027 rt_sigaction(SIGRT_1, {0x3f892067b0, [], SA_RESTORER|SA_RESTART|SA_SIGINFO, 0x3f8920f500}, NULL, 8) = 0
 0.000026 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000026 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000025 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000024 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000023 rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
 0.000023 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000022 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000021 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000019 rt_sigaction(SIGRTMIN, {0x3f89206720, [], SA_RESTORER|SA_SIGINFO, 0x3f8920f500}, NULL, 8) = 0

मुझे यह 5 साल पुरानी बग रिपोर्ट मिली जिसमें "पिंग पोंग" प्रदर्शन परीक्षण शामिल है जो तुलना करता है

  1. सिंगल-थ्रेडेड लिबप्रेथ म्यूटेक्स
  2. libpthread अवस्था चर
  3. सादे पुराने यूनिक्स संकेत

मुझे जोड़ना था

#include <stdint.h>

संकलित करने के लिए, जो मैंने इस आदेश के साथ किया था

g++ -O3 -o condvar-perf condvar-perf.cpp -lpthread -lrt

कर्नेल पर 2.6.32

$ ./condvar-perf 1000000
NPTL
mutex                 elapsed:    29085 us; per iteration:   29 ns / 9.4e-05 context switches.
c.v. ping-pong test   elapsed:  4771993 us; per iteration: 4771 ns / 4.03 context switches.
signal ping-pong test elapsed:  8685423 us; per iteration: 8685 ns / 4.05 context switches.

कर्नेल पर 3.1.9

$ ./condvar-perf 1000000
NPTL
mutex                 elapsed:    26811 us; per iteration:   26 ns / 8e-06 context switches.
c.v. ping-pong test   elapsed: 10930794 us; per iteration: 10930 ns / 4.01 context switches.
signal ping-pong test elapsed: 10949670 us; per iteration: 10949 ns / 4.01 context switches.

मैं निष्कर्ष निकालता हूं कि कर्नेल के बीच 2.6.32 और 3.1.9 संदर्भ स्विच वास्तव में धीमा हो गया है, हालांकि आप कर्नेल 3.2 में उतना नहीं देखते हैं। मुझे पता है कि यह अभी तक आपके सवाल का जवाब नहीं देता है, मैं खुदाई करता रहूंगा।

संपादित करें: मैंने पाया है कि प्रक्रिया की वास्तविक समय प्राथमिकता (दोनों धागे) को बदलने से 3.1.9 पर प्रदर्शन 2.6.32 से मेल खाता है। हालांकि, 2.6.32 पर समान प्राथमिकता निर्धारित करने से यह धीमा हो जाता है ... जाओ आंकड़ा - मैं इसे और अधिक देखूंगा।

यहाँ अब मेरे परिणाम हैं:

कर्नेल पर 2.6.32

$ ./condvar-perf 1000000
NPTL
mutex                 elapsed:    29629 us; per iteration:   29 ns / 0.000418 context switches.
c.v. ping-pong test   elapsed:  6225637 us; per iteration: 6225 ns / 4.1 context switches.
signal ping-pong test elapsed:  5602248 us; per iteration: 5602 ns / 4.09 context switches.
$ chrt -f 1 ./condvar-perf 1000000
NPTL
mutex                 elapsed:    29049 us; per iteration:   29 ns / 0.000407 context switches.
c.v. ping-pong test   elapsed: 16131360 us; per iteration: 16131 ns / 4.29 context switches.
signal ping-pong test elapsed: 11817819 us; per iteration: 11817 ns / 4.16 context switches.
$ 

कर्नेल पर 3.1.9

$ ./condvar-perf 1000000
NPTL
mutex                 elapsed:    26830 us; per iteration:   26 ns / 5.7e-05 context switches.
c.v. ping-pong test   elapsed: 12812788 us; per iteration: 12812 ns / 4.01 context switches.
signal ping-pong test elapsed: 13126865 us; per iteration: 13126 ns / 4.01 context switches.
$ chrt -f 1 ./condvar-perf 1000000
NPTL
mutex                 elapsed:    27025 us; per iteration:   27 ns / 3.7e-05 context switches.
c.v. ping-pong test   elapsed:  5099885 us; per iteration: 5099 ns / 4 context switches.
signal ping-pong test elapsed:  5508227 us; per iteration: 5508 ns / 4 context switches.
$ 

मैंने इसे फेडोरा और सेंटोस पर चलाया, उबंटू नहीं है। मैं अपने परिणाम पोस्ट करूँगा।
amdn

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

ठीक है, कि futex कार्यान्वयन को नियमित करता है - हम आपके संदर्भ के सिद्धांत पर वापस आ गए हैं .... इस उत्तर को हटाने के लिए स्वतंत्र महसूस करें क्योंकि यह वास्तव में टिप्पणियों में है ... मैं सिर्फ कमांडों को प्रारूपित करने की क्षमता चाहता था।
आमदन

हां, समय कुछ ही सेकंड में है ... एक सेकंड से भी लंबे समय तक चलने वाले फ्यूटेक्स के कॉल स्थिति पर प्रतीक्षा कर रहे धागे के लिए हैं।
amdn

तो, क्या होगा अगर आप परिणामों से कुछ भी चमकते हैं?
माइकल गोल्डस्मिन

1

आप देख सकते हैं कि प्रोसेसर हाल की प्रक्रियाओं और लिनक्स कर्नेल में क्लिक कर रहे हैं जो कि पीस्टेट चालक के कारण है जो सी-स्टेट्स से अलग है। इसलिए, इसे अक्षम करने के लिए, आप निम्नलिखित कर्नेल पैरामीटर:

intel_pstate=disable

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.