मैं एक आवेदन में प्रदर्शन हॉटस्पॉट की जांच कर रहा हूं, जो अपने समय का 50% मेमोव (3) में खर्च करता है। एप्लिकेशन लाखों 4-बाइट पूर्णांकों को सॉर्ट किए गए सरणियों में सम्मिलित करता है, और सम्मिलित मूल्य के लिए स्थान बनाने के लिए डेटा को "दाईं ओर" स्थानांतरित करने के लिए मेमोव का उपयोग करता है।
मेरी उम्मीद यह थी कि स्मृति की नकल करना बहुत तेज़ है, और मुझे आश्चर्य हुआ कि मेमोव में इतना समय व्यतीत होता है। लेकिन तब मुझे पता था कि मेमोव धीमा है क्योंकि यह अतिव्यापी क्षेत्रों को स्थानांतरित कर रहा है, जिसे स्मृति के बड़े पृष्ठों की प्रतिलिपि बनाने के बजाय एक तंग लूप में लागू किया जाना चाहिए। मैंने यह जानने के लिए एक छोटा सा माइक्रोबैन्चमार्क लिखा था कि क्या मेम्ची और मेमोव के बीच एक प्रदर्शन अंतर था, जिससे मेम्ची को हाथ जीतने की उम्मीद थी।
मैंने अपने बेंचमार्क को दो मशीनों (कोर i5, कोर i7) पर चलाया और देखा कि मेमोव वास्तव में मेमरी से ज्यादा तेज है, पुराने कोर i7 पर भी लगभग दोगुना तेज है! अब मैं स्पष्टीकरण की तलाश कर रहा हूं।
यहाँ मेरा बेंचमार्क है। यह मेम्पी के साथ 100 एमबी की प्रतिलिपि बनाता है, और फिर मेम्बोव के साथ लगभग 100 एमबी चलता है; स्रोत और गंतव्य अतिव्यापी हैं। स्रोत और गंतव्य के लिए विभिन्न "दूरी" की कोशिश की जाती है। प्रत्येक परीक्षण 10 बार चलाया जाता है, औसत समय मुद्रित किया जाता है।
https://gist.github.com/cruppstahl/78a57cdf937bca3d062c
यहां कोर i5 (लिनक्स 3.5.0-54-जेनेरिक # 81 ~ सटीक1-Ubuntu SMP x86_64 GNU / Linux, gcc 4.6.3 (Ubuntu / Linaro 4.6.3-1ubuntu5) पर परिणाम हैं। कोष्ठक में संख्या है) स्रोत और गंतव्य के बीच की दूरी (अंतर का आकार):
memcpy 0.0140074
memmove (002) 0.0106168
memmove (004) 0.01065
memmove (008) 0.0107917
memmove (016) 0.0107319
memmove (032) 0.0106724
memmove (064) 0.0106821
memmove (128) 0.0110633
मेमोव एक एसएसई अनुकूलित कोडांतरक कोड के रूप में लागू किया गया है, पीछे से सामने की ओर नकल कर रहा है। यह डेटा को कैश में लोड करने के लिए हार्डवेयर प्रीफैच का उपयोग करता है, और एक्सएमएम रजिस्टरों को 128 बाइट्स कॉपी करता है, फिर उन्हें गंतव्य पर संग्रहीत करता है।
( मेम्स्की-ssse3-back.S , लाइनें 1650 ff)
L(gobble_ll_loop):
prefetchnta -0x1c0(%rsi)
prefetchnta -0x280(%rsi)
prefetchnta -0x1c0(%rdi)
prefetchnta -0x280(%rdi)
sub $0x80, %rdx
movdqu -0x10(%rsi), %xmm1
movdqu -0x20(%rsi), %xmm2
movdqu -0x30(%rsi), %xmm3
movdqu -0x40(%rsi), %xmm4
movdqu -0x50(%rsi), %xmm5
movdqu -0x60(%rsi), %xmm6
movdqu -0x70(%rsi), %xmm7
movdqu -0x80(%rsi), %xmm8
movdqa %xmm1, -0x10(%rdi)
movdqa %xmm2, -0x20(%rdi)
movdqa %xmm3, -0x30(%rdi)
movdqa %xmm4, -0x40(%rdi)
movdqa %xmm5, -0x50(%rdi)
movdqa %xmm6, -0x60(%rdi)
movdqa %xmm7, -0x70(%rdi)
movdqa %xmm8, -0x80(%rdi)
lea -0x80(%rsi), %rsi
lea -0x80(%rdi), %rdi
jae L(gobble_ll_loop)
मेमू क्यों तेज है तो मेम्कॉपी? मैं मेमरी को मेमोरी पेज कॉपी करने की उम्मीद करूंगा, जो लूपिंग की तुलना में बहुत तेज होना चाहिए। सबसे खराब स्थिति में मैं उम्मीद करूंगा कि मेमोविले जितना ही तेज होगा।
पुनश्च: मुझे पता है कि मैं अपने कोड में मेम्मो को मेमकी से नहीं बदल सकता। मुझे पता है कि कोड नमूना C और C ++ को मिलाता है। यह सवाल वास्तव में सिर्फ अकादमिक उद्देश्यों के लिए है।
अद्यतन १
मैंने विभिन्न उत्तरों के आधार पर परीक्षणों के कुछ रूपों को चलाया।
- जब दो बार मेमेची चलाते हैं, तो दूसरा रन पहले की तुलना में तेज होता है।
- जब "टच" डेस्टिनेशन बफर ऑफ मेम्सी (
memset(b2, 0, BUFFERSIZE...)
) होता है तो मेम्पी का पहला रन भी तेज होता है। - मेमकी अब भी मेमोव की तुलना में थोड़ी धीमी है।
यहाँ परिणाम हैं:
memcpy 0.0118526
memcpy 0.0119105
memmove (002) 0.0108151
memmove (004) 0.0107122
memmove (008) 0.0107262
memmove (016) 0.0108555
memmove (032) 0.0107171
memmove (064) 0.0106437
memmove (128) 0.0106648
मेरा निष्कर्ष: @ ऑलिवर चार्ल्सवर्थ की एक टिप्पणी के आधार पर, ऑपरेटिंग सिस्टम को भौतिक मेमोरी करना पड़ता है जैसे ही मेम्सी डेस्टिनेशन बफर को पहली बार एक्सेस किया जाता है (यदि कोई जानता है कि यह "प्रूफ" कैसे किया जाता है तो कृपया एक उत्तर जोड़ें! )। इसके अलावा, जैसा कि @ माट्स पीटरसन ने कहा, मेम्मो मेम्ची से कैश फ्रेंडली है।
सभी महान जवाब और टिप्पणियों के लिए धन्यवाद!