2012-02-21 21 views
6

कल मैं unordered_map का उपयोग करने की कोशिश की और इस कोड को मुझे उलझन में कितना स्मृति का उपयोग किया।std :: unordered_map बहुत ही उच्च स्मृति उपयोग

typedef list<string> entityId_list; 
struct tile_content { 
    char cost; 
    entityId_list entities; 
}; 
unordered_map<int, tile_content> hash_map; 

for (size_t i = 0; i < 19200; i++) { 
    tile_content t; 
    t.cost = 1; 
    map[i] = t; 
} 

सभी कोड के इस भागों डिबग मोड में एमएस VS2010 में संकलित किया गया। जो मैंने अपने टास्क मैनेजर में देखा है वह लगभग 1200 केबी "साफ" प्रक्रिया थी, लेकिन हैश_मैप भरने के बाद यह 8124 केबी मेमोरी का उपयोग करता है। क्या यह unordered_map का सामान्य व्यवहार है? इतनी मेमोरी क्यों उपयोग की जाती है?

+0

बस यह ध्यान रखना चाहता था कि एक अनियंत्रित नक्शा सैकड़ों मेगाबाइट तक रख सकता है, भले ही कोई आइटम अंदर संग्रहीत न हो (जब आप इटरेटर के माध्यम से मिटते हैं, क्योंकि यदि नक्शा पुनरावर्तक पुनरावर्तक हो जाता है) तो यह बग रिपोर्ट देखें (जैसा कि हो सकता है अच्छी तरह से माइक्रोसॉफ्ट कार्यान्वयन को प्रभावित नहीं करते हैं): https://svn.boost.org/trac/boost/ticket/11419 – GameDeveloper

उत्तर

9

unordered_map संरचना को बड़ी संख्या में ऑब्जेक्ट्स को इस तरह से रखने के लिए डिज़ाइन किया गया है जो जोड़ता है, हटा देता है, लुकअप और ऑर्डरलेस ट्रैवर्स कुशल बनाता है। यह छोटे डेटा संरचनाओं के लिए स्मृति-कुशल होने का मतलब नहीं है। आकार बदलने से जुड़ी जुर्माना से बचने के लिए, यह पहली बार बनाई गई है जब यह कई हैश चेन हेड आवंटित करता है।

6

यह जरूरी नहीं है कि हैश नक्शा इतना स्मृति का उपयोग करता है, लेकिन इस प्रक्रिया ओएस से कि अधिक स्मृति अनुरोध किया है कि।

यह स्मृति तो इस कार्यक्रम के द्वारा malloc/नई अनुरोधों को संतुष्ट किया जाता है। कुछ (या सबसे अधिक, मुझे इस बारे में निश्चित नहीं है) स्मृति आवंटकों को उस समय की आवश्यकता के मुकाबले ओएस से अधिक स्मृति की आवश्यकता होती है।

पता करने के लिए कितनी स्मृति मैं perftools की तरह एक स्मृति प्रोफाइलर का प्रयोग करेंगे unordered_map द्वारा प्रयोग किया जाता है।

9

~ 20k वस्तुओं के लिए मोटे तौर पर 6MB है यही कारण है, तो वस्तु प्रति 300 बाइट्स। हैश टेबल को वर्तमान प्रविष्टियों की तुलना में कई गुना अधिक बाल्टी रखने के लिए आकार दिया जा सकता है, प्रत्येक बाल्टी खुद को एक सूची या टकराव वस्तुओं के वेक्टर के लिए सूचक हो सकती है, इसमें से प्रत्येक में शामिल प्रत्येक ढेर आवंटन शायद निकटतम तक हो गया है दो की शक्ति, और आपको डीबग मिला है जिस पर कुछ अतिरिक्त ब्लोट उत्पन्न हो सकता है, यह सब मेरे बारे में सही लगता है।

वैसे भी, आप डीबग बिल्ड ;-P में कुछ भी की स्मृति या CPU दक्षता के लिए सहानुभूति पाने के लिए नहीं जा रहे हैं। माइक्रोसॉफ्ट वहां किसी भी ढलान को इंजेक्ट कर सकता है, और उपयोगकर्ता को प्रदर्शन के आसपास अपेक्षाओं का कोई अधिकार नहीं है। यदि आपको एक अनुकूलित निर्माण में यह बुरा लगता है, तो आपके पास बात करने के लिए कुछ मिल गया है।

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

+0

क्या आप अंतिम वाक्य का कारण दे सकते हैं? – Andrew

+2

@ एंड्रयू: सॉर्ट किए गए वैक्टर के मुख्य प्रदर्शन पेशेवर संगत स्मृति उपयोग और इन-प्लेस मान हैं, जबकि 'unordered_map' कार्यान्वयन गतिशील रूप से अलग-अलग नोड आवंटित करते हैं और संचालन के दौरान उन्हें पॉइंटर्स का पालन करना पड़ता है; दोनों बाइनरी पेड़ों और सॉर्ट किए गए वैक्टरों में संचालन में ओ (लॉग एन) '' <'' तुलना, जबकि 'unordered_map संचालन के लिए हैश फ़ंक्शन कॉल की आवश्यकता होती है (जो महंगा हो सकता है लेकिन प्रति ऑपरेशन में केवल एक बार किया जाता है, और ऑर्केस्ट्रेट किया जा सकता है प्रति मूल्य एक बार होने के लिए) और '==' तुलना। हमेशा की तरह, जब आप परवाह करते हैं तो अपने वास्तविक डेटा और उपयोग के लिए उपाय करें। –

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