कस्टम C ++ आवंटनकर्ताओं के सम्मोहक उदाहरण?


176

std::allocatorकस्टम समाधान के पक्ष में खाई के लिए वास्तव में कुछ अच्छे कारण क्या हैं ? क्या आपने ऐसी किसी भी स्थिति में भाग लिया है जहाँ शुद्धता, प्रदर्शन, मापनीयता आदि के लिए यह बिल्कुल आवश्यक था? किसी भी वास्तव में चतुर उदाहरण?

कस्टम आवंटन हमेशा मानक लाइब्रेरी की एक विशेषता रही है जिसकी मुझे बहुत आवश्यकता नहीं थी। मैं सोच रहा था कि क्या एसओ यहां किसी को भी अपने अस्तित्व को सही ठहराने के लिए कुछ आकर्षक उदाहरण दे सकता है।

जवाबों:


121

जैसा कि मैंने यहाँ उल्लेख किया है , मैंने देखा है कि इंटेल टीबीबी का कस्टम एसटीएल एलोकेटर एक एकल को बदलकर एक मल्टीथ्रेडेड ऐप के प्रदर्शन में काफी सुधार करता है

std::vector<T>

सेवा

std::vector<T,tbb::scalable_allocator<T> >

(यह टीबीबी के निफ्टी थ्रेड-प्राइवेट ढेर का उपयोग करने के लिए एलोकेटर को स्विच करने का एक त्वरित और सुविधाजनक तरीका है; इस दस्तावेज़ में पृष्ठ 7 देखें )


3
उस दूसरी कड़ी के लिए धन्यवाद। धागा-निजी ढेर को लागू करने के लिए आवंटनकर्ताओं का उपयोग चतुर है। मुझे यह पसंद है कि यह एक अच्छा उदाहरण है जहां कस्टम आवंटनकर्ताओं को ऐसे परिदृश्य में स्पष्ट लाभ होता है जो संसाधन-सीमित (एम्बेड या कंसोल) नहीं है।
नाफ्फ

7
मूल लिंक अब ख़राब हो गया है, लेकिन CiteSeer के पास पीडीएफ है: citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.71.8289
Arto Bendenen

1
मुझे पूछना है: क्या आप मज़बूती से इस तरह के एक वेक्टर को दूसरे धागे में स्थानांतरित कर सकते हैं? (मैं अनुमान नहीं लगा रहा हूं)
सिपाहीबेटेज

@sellibitze: चूंकि वैक्टर को टीबीबी कार्यों के भीतर से हेरफेर किया जा रहा था और कई समानांतर परिचालनों में पुन: उपयोग किया गया था और इस बात की कोई गारंटी नहीं है कि टीबीबी वर्कर थ्रेड किस तरह के कार्यों को उठाएगा, मैं इसे ठीक काम करता हूं। यद्यपि ध्यान दें कि टीबीबी फ्रीजिंग सामान के साथ कुछ ऐतिहासिक मुद्दे एक धागे में एक धागे पर बनाए गए हैं (जाहिरा तौर पर धागा निजी ढेर और आवंटन और निपटान के उपभोक्ता-उपभोक्ता पैटर्न के साथ एक क्लासिक समस्या। टीबीबी का दावा है कि यह आवंटनकर्ता इन मुद्दों से बचता है लेकिन मुझे अन्यथा नहीं देखा गया है) । शायद नए संस्करणों में तय किया गया है।)
versions बजे

@ArtoBendiken: आपके लिंक पर डाउनलोड लिंक मान्य नहीं लगता है।
ईनपोकलम

81

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

EASTL - इलेक्ट्रॉनिक आर्ट्स स्टैंडर्ड टेम्पलेट लाइब्रेरी


14
EASTL लिंक के लिए +1: "गेम डेवलपर्स के बीच एसटीएल की सबसे बुनियादी कमजोरी [एसएलडी] एसटीडी एलोकेटर डिजाइन है, और यह इस कमजोरी है कि ईएएसटीएल के निर्माण में सबसे बड़ा योगदान कारक था।"
20

65

मैं एक एमएमएपी-एलोकेटर पर काम कर रहा हूं जो वैक्टर को मेमोरी-मैप की गई फ़ाइल से मेमोरी का उपयोग करने की अनुमति देता है। लक्ष्य में वेक्टर होते हैं जो स्टोरेज का उपयोग करते हैं जो सीधे एमएमएपी द्वारा मैप की गई वर्चुअल मेमोरी में होते हैं। हमारी समस्या यह है कि वास्तव में बड़ी फ़ाइलों (> 10GB) की मेमोरी को बिना कॉपी ओवरहेड के पढ़ने में सुधार किया जाता है, इसलिए मुझे इस कस्टम एलोकेटर की आवश्यकता है।

अब तक मेरे पास एक कस्टम आवंटनकर्ता का कंकाल है (जो कि std :: आवंटनकर्ता से प्राप्त होता है), मुझे लगता है कि यह खुद को आवंटित करने वाले लिखने के लिए एक अच्छा प्रारंभिक बिंदु है। जो कुछ भी आप चाहते हैं, उस कोड के इस टुकड़े का उपयोग करने के लिए स्वतंत्र महसूस करें:

#include <memory>
#include <stdio.h>

namespace mmap_allocator_namespace
{
        // See StackOverflow replies to this answer for important commentary about inheriting from std::allocator before replicating this code.
        template <typename T>
        class mmap_allocator: public std::allocator<T>
        {
public:
                typedef size_t size_type;
                typedef T* pointer;
                typedef const T* const_pointer;

                template<typename _Tp1>
                struct rebind
                {
                        typedef mmap_allocator<_Tp1> other;
                };

                pointer allocate(size_type n, const void *hint=0)
                {
                        fprintf(stderr, "Alloc %d bytes.\n", n*sizeof(T));
                        return std::allocator<T>::allocate(n, hint);
                }

                void deallocate(pointer p, size_type n)
                {
                        fprintf(stderr, "Dealloc %d bytes (%p).\n", n*sizeof(T), p);
                        return std::allocator<T>::deallocate(p, n);
                }

                mmap_allocator() throw(): std::allocator<T>() { fprintf(stderr, "Hello allocator!\n"); }
                mmap_allocator(const mmap_allocator &a) throw(): std::allocator<T>(a) { }
                template <class U>                    
                mmap_allocator(const mmap_allocator<U> &a) throw(): std::allocator<T>(a) { }
                ~mmap_allocator() throw() { }
        };
}

इसका उपयोग करने के लिए, एसटीएल कंटेनर को निम्नानुसार घोषित करें:

using namespace std;
using namespace mmap_allocator_namespace;

vector<int, mmap_allocator<int> > int_vec(1024, 0, mmap_allocator<int>());

इसका उपयोग उदाहरण के लिए किया जा सकता है जब भी मेमोरी आवंटित की जाती है। Neccessary रिबंड स्ट्रक्चर क्या है, वरना वेक्टर कंटेनर सुपरक्लासेस को आवंटित / डीलॉलेट विधियों का उपयोग करता है।

अद्यतन: मेमोरी मैपिंग आवंटन अब https://github.com/johannesthoma/mmap_allocator पर उपलब्ध है और LGPL है। अपनी परियोजनाओं के लिए इसका इस्तेमाल करने के लिए स्वतंत्र महसूस करें।


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

25

मैं एक MySQL स्टोरेज इंजन के साथ काम कर रहा हूँ जो अपने कोड के लिए c ++ का उपयोग करता है। हम स्मृति के लिए MySQL के साथ प्रतिस्पर्धा करने के बजाय MySQL मेमोरी सिस्टम का उपयोग करने के लिए एक कस्टम एलोकेटर का उपयोग कर रहे हैं। यह हमें यह सुनिश्चित करने की अनुमति देता है कि हम मेमोरी का उपयोग कर रहे हैं क्योंकि उपयोगकर्ता ने MySQL का उपयोग करने के लिए कॉन्फ़िगर किया है, और "अतिरिक्त" नहीं।


21

यह ढेर के बजाय एक मेमोरी पूल का उपयोग करने के लिए कस्टम एलोकेटर्स का उपयोग करने के लिए उपयोगी हो सकता है। यह कई अन्य लोगों के बीच एक उदाहरण है।

ज्यादातर मामलों के लिए, यह निश्चित रूप से समय से पहले का अनुकूलन है। लेकिन यह कुछ संदर्भों (एम्बेडेड उपकरणों, गेम आदि) में बहुत उपयोगी हो सकता है।


3
या, जब वह मेमोरी पूल साझा किया जाता है।
एंथनी

9

मैंने एक कस्टम STL आवंटनकर्ता के साथ C ++ कोड नहीं लिखा है, लेकिन मैं C ++ में लिखे गए वेबसर्वर की कल्पना कर सकता हूं, जो HTTP अनुरोध का जवाब देने के लिए आवश्यक अस्थायी डेटा के स्वचालित विलोपन के लिए एक कस्टम आवंटनकर्ता का उपयोग करता है। रिऐक्शन उत्पन्न होने के बाद कस्टम एलोकेटर एक बार में सभी अस्थायी डेटा को फ्री कर सकता है।

कस्टम आवंटनकर्ता (जो मैंने उपयोग किया है) के लिए एक और संभव उपयोग मामला यह साबित करने के लिए एक इकाई परीक्षण लिख रहा है कि एक फ़ंक्शन का व्यवहार उसके इनपुट के कुछ हिस्से पर निर्भर नहीं करता है। कस्टम आवंटनकर्ता मेमोरी क्षेत्र को किसी भी पैटर्न के साथ भर सकता है।


5
ऐसा लगता है कि पहला उदाहरण विध्वंसक का काम है, न कि आवंटनकर्ता का।
माइकल डोरस्ट

2
यदि आप ढेर से मेमोरी की प्रारंभिक सामग्री के आधार पर अपने कार्यक्रम के बारे में चिंतित हैं, तो वेलग्रिंड में एक त्वरित (यानी रात भर!) आपको एक या दूसरे तरीके से जाने देगा।
cdyson37

3
@anthropomorphic: विध्वंसक और कस्टम आवंटनकर्ता एक साथ काम करेंगे, विध्वंसक पहले चलेगा, फिर कस्टम आवंटनकर्ता को हटाएगा, जो अभी तक (...) को निःशुल्क नहीं कहेगा, लेकिन मुफ्त (...) कहा जाएगा बाद में, जब अनुरोध पूरा हो गया है। यह डिफॉल्ट एलोकेशन करने वाले से तेज हो सकता है और पता स्थान विखंडन को कम कर सकता है।
अंक

8

जब GPU या अन्य सह-प्रोसेसर के साथ काम करते हैं तो कभी-कभी मुख्य मेमोरी में डेटा संरचनाओं को एक विशेष तरीके से आवंटित करना फायदेमंद होता है । स्मृति को आवंटित करने का यह विशेष तरीका एक सुविधाजनक फैशन में कस्टम आवंटनकर्ता में लागू किया जा सकता है।

त्वरक का उपयोग करते समय त्वरक रनटाइम के माध्यम से कस्टम आवंटन क्यों फायदेमंद हो सकता है:

  1. कस्टम आवंटन के माध्यम से त्वरक रनटाइम या ड्राइवर को मेमोरी ब्लॉक के बारे में सूचित किया जाता है
  2. इसके अलावा ऑपरेटिंग सिस्टम यह सुनिश्चित कर सकता है कि मेमोरी का आवंटित ब्लॉक पेज-लॉक किया गया है (कुछ इस पिन को मेमोरी कहते हैं ), यानी ऑपरेटिंग सिस्टम के वर्चुअल मेमोरी सबसिस्टम पेज को स्मृति के भीतर या बाहर नहीं ले जा सकता है और न ही हटा सकता है।
  3. यदि 1. और 2. पृष्ठ-लॉक किए गए मेमोरी ब्लॉक और एक्सेलेरेटर के बीच डेटा ट्रांसफर और होल्ड किया जाता है, तो रनटाइम सीधे डेटा को मुख्य मेमोरी में एक्सेस कर सकता है क्योंकि यह जानता है कि यह कहां है और यह सुनिश्चित कर सकता है कि ऑपरेटिंग सिस्टम ने नहीं किया इसे हटाओ / हटाओ
  4. यह एक मेमोरी कॉपी को सेव करता है जो मेमोरी के साथ होता है जो कि एक नॉन-पेज-लॉक तरीके से आवंटित किया गया था: डेटा को मुख्य मेमोरी में पेज-लॉक स्टेजिंग क्षेत्र में कॉपी किया जाना है जिसमें एक्सीलेटर के साथ डेटा ट्रांसफर को आरंभ किया जा सकता है (डीएमए के माध्यम से) )

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

7

मैं यहाँ कस्टम एलोकेटर का उपयोग कर रहा हूँ; आप यह भी कह सकते हैं कि यह अन्य कस्टम डायनेमिक मेमोरी प्रबंधन के आसपास काम करना था ।

पृष्ठभूमि: हमारे पास मॉलॉक, कॉलोक, फ्री और ऑपरेटर के विभिन्न वेरिएंट नए और डिलीट करने के लिए ओवरलोड हैं, और लिंकर खुशी से एसटीएल का उपयोग करता है। यह हमें स्वचालित छोटी वस्तु पूलिंग, रिसाव का पता लगाने, आवंटन को भरने, मुफ्त भरने, संतरी के साथ पैडिंग आवंटन, कुछ एलोकस के लिए कैश-लाइन संरेखण और मुफ्त में देरी जैसी चीजें करने देता है।

समस्या यह है, हम एक एम्बेडेड वातावरण में चल रहे हैं - वास्तव में एक विस्तारित अवधि में रिसाव का पता लगाने के लिए पर्याप्त मेमोरी नहीं है। कम से कम, मानक रैम में नहीं - कस्टम आवंटन कार्यों के माध्यम से कहीं और उपलब्ध रैम का एक और ढेर है।

समाधान: एक कस्टम एलोकेटर लिखें जो विस्तारित हीप का उपयोग करता है, और केवल इसका उपयोग करें मेमोरी लीक ट्रैकिंग आर्किटेक्चर के इंटर्नल में किया जाता है ... बाकी सभी सामान्य नए / हटाए गए अधिभार को लीक ट्रैकिंग करते हैं। यह ट्रैकर पर नज़र रखने से बचता है (और अतिरिक्त पैकिंग कार्यक्षमता भी प्रदान करता है, हम ट्रैकर नोड्स के आकार को जानते हैं)।

हम इसका उपयोग फ़ंक्शन लागत प्रोफाइलिंग डेटा रखने के लिए भी करते हैं, इसी कारण से; प्रत्येक फ़ंक्शन कॉल और वापसी के लिए प्रविष्टि लिखना, साथ ही साथ थ्रेड स्विच, महंगी तेजी से प्राप्त कर सकते हैं। कस्टम एलोकेटर फिर से हमें एक बड़े डिबग मेमोरी क्षेत्र में छोटे एलोकेशन देता है।


5

मैं अपने कार्यक्रम के एक हिस्से में आवंटन / डीलक्लोशंस की संख्या की गणना करने और यह मापने में कितना समय लगता है, के लिए एक कस्टम आवंटनकर्ता का उपयोग कर रहा हूं। ऐसे और भी तरीके हैं जिन्हें हासिल किया जा सकता है लेकिन यह तरीका मेरे लिए बहुत सुविधाजनक है। यह विशेष रूप से उपयोगी है कि मैं अपने कंटेनर के केवल सबसेट के लिए कस्टम आवंटनकर्ता का उपयोग कर सकता हूं।


4

एक आवश्यक स्थिति: जब कोड लिखना जो मॉड्यूल (EXE / DLL) की सीमाओं के पार होना चाहिए, तो यह आवश्यक है कि आपके आवंटन और विलोपन केवल एक ही मॉड्यूल में होते रहें।

जहाँ मैं इस में भाग गया वह विंडोज पर एक प्लगइन वास्तुकला था। यह आवश्यक है कि, उदाहरण के लिए, यदि आप DLL की सीमा के पार एक std :: string पास करते हैं, तो स्ट्रिंग का कोई भी पुनरावृत्ति उस ढेर से होता है, जहाँ से इसकी उत्पत्ति हुई है, DLL में ढेर नहीं जो अलग हो सकता है *।

* यह वास्तव में इस से अधिक जटिल है, जैसे कि आप गतिशील रूप से सीआरटी से लिंक कर रहे हैं यह किसी भी तरह से काम कर सकता है। लेकिन अगर प्रत्येक डीएलएल में सीआरटी के लिए एक स्थिर लिंक है, तो आप दर्द की दुनिया में जा रहे हैं, जहां प्रेत आवंटन त्रुटियां लगातार होती हैं।


यदि आप DLL सीमाओं के पार वस्तुओं को पास करते हैं, तो आपको बहु-थ्रेडेड (डीबग) DLL (/ MD (d)) सेटिंग का उपयोग करना चाहिए। C ++ को मॉड्यूल समर्थन को ध्यान में रखकर नहीं बनाया गया था। वैकल्पिक रूप से आप COM इंटरफेस के पीछे सब कुछ ढाल सकते हैं और CoTaskMemAlloc का उपयोग कर सकते हैं। यह प्लगइन इंटरफेस का उपयोग करने का सबसे अच्छा तरीका है जो एक विशिष्ट संकलक, एसटीएल या विक्रेता के लिए बाध्य नहीं हैं।
Gast128

पुराने लोगों के लिए नियम है: यह मत करो। DLL API में STL प्रकारों का उपयोग न करें। और डीएलएल एपीआई सीमाओं के पार डायनेमिक मेमोरी फ्री जिम्मेदारी पास न करें। कोई C ++ ABI नहीं है - इसलिए यदि आप प्रत्येक DLL को C API के रूप में मानते हैं, तो आप संभावित समस्याओं की एक पूरी श्रेणी से बचते हैं। "सी ++ ब्यूटी" की कीमत पर, बिल्कुल। या जैसा कि अन्य टिप्पणी से पता चलता है: COM का उपयोग करें। बस सादा C ++ एक बुरा विचार है।
BitTickler

3

मैंने जिस समय का उपयोग किया है, उसका एक उदाहरण बहुत ही संसाधन युक्त एम्बेडेड सिस्टम के साथ काम कर रहा था। कहते हैं कि आपके पास 2 k का RAM मुफ़्त है और आपके प्रोग्राम को कुछ मेमोरी का उपयोग करना है। आपको कहीं-कहीं 4-5 दृश्यों को संग्रहीत करने की आवश्यकता है जो कि स्टैक पर नहीं हैं और इसके अतिरिक्त आपको उन चीजों पर बहुत सटीक पहुंच की आवश्यकता है जहां ये चीजें संग्रहीत होती हैं, यह एक ऐसी स्थिति है जहां आप अपने खुद के आवंटनकर्ता लिखना चाहते हैं। डिफ़ॉल्ट कार्यान्वयन मेमोरी को ख़राब कर सकते हैं, यह अस्वीकार्य हो सकता है यदि आपके पास पर्याप्त मेमोरी नहीं है और आप अपने प्रोग्राम को पुनः आरंभ नहीं कर सकते हैं।

एक परियोजना जिस पर मैं काम कर रहा था वह कुछ कम शक्ति वाले चिप्स पर AVR-GCC का उपयोग कर रही थी। हमें परिवर्तनीय लंबाई के 8 अनुक्रमों को संग्रहीत करना था लेकिन एक ज्ञात अधिकतम के साथ। स्मृति प्रबंधन के मानक पुस्तकालय कार्यान्वयनMalloc / free के चारों ओर एक पतला आवरण होता है, जो उस आवंटित किए गए टुकड़े के अंत के पिछले हिस्से के पिछले हिस्से के लिए एक पॉइंटर के साथ मेमोरी के प्रत्येक आबंटित ब्लॉक को जोड़कर वस्तुओं को रखने का स्थान रखता है। स्मृति के एक नए टुकड़े को आवंटित करते समय मानक आवंटनकर्ता को अगले खंड को खोजने के लिए स्मृति के प्रत्येक टुकड़े पर चलना पड़ता है जो उपलब्ध है जहां स्मृति का अनुरोधित आकार फिट होगा। एक डेस्कटॉप प्लेटफ़ॉर्म पर यह कुछ वस्तुओं के लिए बहुत तेज़ होगा लेकिन आपको यह ध्यान रखना होगा कि इनमें से कुछ माइक्रोकंट्रोलर तुलना में बहुत धीमे और आदिम हैं। इसके अतिरिक्त स्मृति विखंडन समस्या एक बड़ी समस्या थी जिसका मतलब था कि वास्तव में हमारे पास एक अलग दृष्टिकोण लेने के अलावा कोई विकल्प नहीं था।

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

वहाँ कई बार मैं एम्बेडेड सिस्टम के संदर्भ में अपने खुद के कस्टम आवंटन लिख सकता है, उदाहरण के लिए अगर अनुक्रम के लिए स्मृति मुख्य RAM में नहीं है क्योंकि अक्सर इन प्लेटफार्मों पर मामला हो सकता है


3

आंद्रेई अलेक्जेंड्रेस्कु के कैप्पकॉन 2015 के लिए अप्रचलित लिंक आवंटनकर्ताओं पर बात:

https://www.youtube.com/watch?v=LIb3L4vKZ7U

अच्छी बात यह है कि बस उन्हें तैयार करने से आप उन विचारों के बारे में सोचते हैं कि आप उनका उपयोग कैसे करेंगे :-)


2

साझा मेमोरी के लिए यह महत्वपूर्ण है कि न केवल कंटेनर हेड, बल्कि इसमें मौजूद डेटा भी साझा मेमोरी में स्टोर हो।

की संभाजक बूस्ट :: Interprocess एक अच्छा उदाहरण है। हालाँकि, जैसा कि आप यहाँ पढ़ सकते हैं कि यह सब पर्याप्त नहीं है, सभी एसटीएल कंटेनरों को साझा मेमोरी को संगत बनाने के लिए (विभिन्न प्रक्रियाओं में अलग-अलग मैपिंग ऑफ़सेट के कारण, पॉइंटर्स "ब्रेक" हो सकता है)।


2

कुछ समय पहले मुझे यह समाधान मेरे लिए बहुत उपयोगी लगा: एसटीएल कंटेनरों के लिए फास्ट सी ++ 11 आवंटन । यह VS2017 (~ 5x) और साथ ही GCC (~ 7x) पर STL कंटेनरों को थोड़ा गति देता है। यह मेमोरी पूल पर आधारित एक विशेष उद्देश्य आवंटन है। यह एसटीएल कंटेनरों के साथ उपयोग किया जा सकता है केवल उस तंत्र के लिए धन्यवाद जो आप पूछ रहे हैं।


1

मैं व्यक्तिगत रूप से लोकी का उपयोग करता हूं :: छोटी वस्तुओं के लिए मेमोरी उपयोग का अनुकूलन करने के लिए एलोकेटर / स्मॉलऑबजेक्ट - यह अच्छी दक्षता और संतोषजनक प्रदर्शन दिखाता है यदि आपको वास्तव में छोटी वस्तुओं (1 से 256 बाइट्स) की मध्यम मात्रा के साथ काम करना है। अगर हम कई अलग-अलग आकारों की छोटी वस्तुओं के मध्यम मात्रा के आवंटन के बारे में बात करते हैं, तो यह मानक C ++ नए / डिलीट आवंटन की तुलना में ~ 30 गुना अधिक कुशल हो सकता है। इसके अलावा, "QuickHeap" नामक कुलपति-विशिष्ट समाधान है, यह सबसे अच्छा संभव प्रदर्शन लाता है (केवल आवंटित करें और पढ़े जाने वाले ब्लॉक को आवंटित करें और ब्लॉक किए गए पते को लिखें और क्रमशः वापस लौट आए / जाएं, 99 तक) (9)% मामले - सेटिंग्स और इनिशियलाइज़ेशन पर निर्भर करता है), लेकिन एक उल्लेखनीय ओवरहेड की कीमत पर - इसे दो पॉइंटर्स प्रति सीमा और प्रत्येक नए मेमोरी ब्लॉक के लिए एक अतिरिक्त की आवश्यकता होती है। यह

मानक C ++ नया / हटाएं कार्यान्वयन के साथ मुद्दा यह है कि यह आमतौर पर C मॉलोक / मुक्त आवंटन के लिए सिर्फ एक आवरण है, और यह 1024+ बाइट्स की तरह मेमोरी के बड़े ब्लॉक के लिए अच्छा काम करता है। यह प्रदर्शन के मामले में एक उल्लेखनीय ओवरहेड है और कभी-कभी, मैपिंग के लिए उपयोग की जाने वाली अतिरिक्त मेमोरी भी। इसलिए, ज्यादातर मामलों में कस्टम आवंटन को प्रदर्शन को अधिकतम करने और / या छोटी (small1024 बाइट्स) वस्तुओं को आवंटित करने के लिए आवश्यक अतिरिक्त मेमोरी की मात्रा को कम करने के लिए लागू किया जाता है।


1

एक ग्राफिक्स सिमुलेशन में, मैंने कस्टम आवंटनकर्ताओं के लिए उपयोग किया है

  1. संरेखण बाधाओं कि std::allocator सीधे समर्थन नहीं करती थीं।
  2. अल्पकालिक (बस इस फ्रेम) और लंबे समय तक रहने वाले आवंटन के लिए अलग-अलग पूल का उपयोग करके विखंडन को कम करना।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.