2011-12-30 14 views
24

जब मैं अपना सीयूडीए प्रोग्राम चलाता हूं जो केवल वैश्विक स्मृति (20 एम से नीचे) आवंटित करता है, तो मुझे "स्मृति से बाहर" त्रुटि मिलती है। (अन्य लोगों की पोस्ट से, मुझे लगता है कि समस्या स्मृति विखंडन से संबंधित है) मैं इस समस्या को समझने की कोशिश करता हूं, और महसूस करता हूं कि मेरे पास CUDA स्मृति प्रबंधन से संबंधित कुछ प्रश्न हैं।सीयूडीए मेमोरी कैसे प्रबंधित की जाती है?

  1. क्या सीयूडीए में वर्चुअल मेमोरी अवधारणा है?

  2. यदि समाप्ति के बाद, केवल एक कर्नेल को सीयूडीए पर चलाने की अनुमति है, तो क्या यह सभी मेमोरी का उपयोग या आवंटित किया जाएगा? यदि नहीं, तो जब ये स्मृति मुक्त हो गई?

  3. यदि कुडा पर एक से अधिक कर्नेल चलाने की अनुमति है, तो वे कैसे सुनिश्चित कर सकते हैं कि वे जिस स्मृति का उपयोग करते हैं, वह ओवरलैप नहीं होता है?

किसी को भी मदद कर सकते हैं मुझे इन सवालों के जवाब? धन्यवाद

संपादित करें 1: ऑपरेटिंग सिस्टम: x86_64 जीएनयू/लिनक्स CUDA संस्करण: 4.0 डिवाइस: Geforce 200, यह GPUs मशीन से जुड़ी में से एक है, और मुझे नहीं लगता कि यह एक प्रदर्शन उपकरण है।

संपादित करें 2: कुछ शोध करने के बाद मुझे निम्नलिखित मिला। मुझे सही करने के लिए स्वतंत्र महसूस करें।

  1. CUDA प्रत्येक होस्ट थ्रेड के लिए एक संदर्भ बनाएगा। यह संदर्भ जानकारी को बनाए रखेगा जैसे स्मृति के किस हिस्से (पूर्व आवंटित स्मृति या गतिशील रूप से आवंटित स्मृति) इस एप्लिकेशन के लिए आरक्षित किया गया है ताकि अन्य एप्लिकेशन इसे लिख न सके। जब यह एप्लिकेशन समाप्त होता है (कर्नेल नहीं), स्मृति का यह भाग जारी किया जाएगा।

  2. सीयूडीए मेमोरी एक लिंक सूची द्वारा बनाए रखा जाता है। जब किसी एप्लिकेशन को स्मृति आवंटित करने की आवश्यकता होती है, तो यह देखने के लिए कि यह निरंतर स्मृति खंड आवंटन के लिए उपलब्ध है या नहीं, यह लिंक सूची के माध्यम से जाएगा। यदि यह इस तरह के एक हिस्से को खोजने में विफल रहता है, तो "स्मृति से बाहर" त्रुटि उपयोगकर्ताओं को रिपोर्ट करेगी, भले ही कुल उपलब्ध स्मृति आकार अनुरोधित स्मृति से अधिक हो। और यह स्मृति विखंडन से संबंधित समस्या है।

  3. cuMemGetInfo आपको बताएगा कि कितनी मेमोरी मुफ्त है, लेकिन यह आवश्यक नहीं है कि आप मेमोरी विखंडन के कारण अधिकतम आवंटन में कितनी मेमोरी आवंटित कर सकें।

  4. Vista प्लेटफार्म (डब्लूडीडीएम) पर, जीपीयू मेमोरी वर्चुअलाइजेशन संभव है। यही है, कई अनुप्रयोग लगभग पूरी GPU मेमोरी आवंटित कर सकते हैं और डब्लूडीडीएम मुख्य मेमोरी में डेटा को स्वैप करने का प्रबंधन करेगा।

नए प्रश्न: 1. यदि स्मृति संदर्भ में सुरक्षित पूरी तरह से जारी किया जाएगा के बाद आवेदन समाप्त कर दिया गया, स्मृति विखंडन मौजूद नहीं चाहिए। स्मृति में कुछ प्रकार का डेटा छोड़ा जाना चाहिए। 2. क्या GPU स्मृति को पुन: स्थापित करने का कोई तरीका है?

+0

क्या आप इस ऑपरेटिंग सिस्टम, जीपीयू और क्यूडा संस्करण का उपयोग कर रहे हैं, और क्या GPU एक डिस्प्ले या गैर डिस्प्ले डिवाइस शामिल करने के लिए प्रश्न संपादित कर सकते हैं। यह आपके प्रश्न के सही उत्तर पर असर डालेगा। – talonmies

+0

अतिरिक्त प्रश्नों के उत्तर देने के लिए - उपयोगकर्ता देखे जाने योग्य विखंडन * संदर्भ के भीतर * होता है, और GPU के भीतर मेमोरी मैपिंग को बदलने का कोई तरीका नहीं है, जिसे होस्ट होस्ट द्वारा नियंत्रित किया जाता है। – talonmies

+0

जैसा कि आप समझाते हैं, एक संदर्भ आवंटन संदर्भ स्थिर आवंटन, संदर्भ उपयोगकर्ता आवंटन और CUDA संदर्भ रनटाइम ढेर से बना है। मुझे लगता है कि संदर्भ स्थिर आवंटन और संदर्भ उपयोगकर्ता आवंटन का आकार पूर्व निर्धारित है। इसलिए, मुझे लगता है कि स्मृति विखंडन का एकमात्र कारण संदर्भ रनटाइम ढेर है जो केवल फर्मि वास्तुकला पर है। क्या वो सही है? मुझे लगता है कि सिस्टम संदर्भ रनटाइम ढेर के लिए स्मृति का एक हिस्सा आवंटित करेगा ताकि इन-कर्नेल गतिशील स्मृति आवंटन सक्षम हो। – xhe8

उत्तर

24

डिवाइस स्मृति रनटाइम पर अपने कोड के लिए उपलब्ध मूल रूप से

Free memory = total memory 
       - display driver reservations 
       - CUDA driver reservations 
       - CUDA context static allocations (local memory, constant memory, device code) 
       - CUDA context runtime heap (in kernel allocations, recursive call stack, printf buffer, only on Fermi and newer GPUs) 
       - CUDA context user allocations (global memory, textures) 

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

क्या हो सकता है यह देखने का सबसे अच्छा तरीका है कि कोई होस्ट कोड नहीं है, जिसमें कोई डिवाइस कोड नहीं है जो संदर्भ स्थापित करता है और cudaMemGetInfo पर कॉल करता है। यह आपको दिखाएगा कि डिवाइस पर न्यूनतम संदर्भ ओवरहेड के साथ डिवाइस कितनी मेमोरी है। फिर आपको समस्याग्रस्त कोड चलाएं, उसी cudaMemGetInfo को पहले cudaMalloc कॉल से पहले कॉल करें जो आपको आपके संदर्भ का उपयोग कर रहे स्मृति की मात्रा देगा। यह आपको याद दिला सकता है कि स्मृति कहां जा रही है। यह बहुत ही असंभव है कि अगर आप पहले cudaMalloc कॉल पर विफलता प्राप्त कर रहे हैं तो विखंडन समस्या है।

+0

talonmies को सही करने के लिए धन्यवाद। यह बहुत ही उपयोगी है। एक और सवाल, क्या यह संभव है कि डिवाइस मेमोरी में कई संदर्भ मौजूद हों? – xhe8

+0

हां यह संभव है, लेकिन दिया गया धागा किसी दिए गए डिवाइस पर केवल एक ही संदर्भ रख सकता है। सामान्य परिदृश्य एक ही समय में एक ही जीपीयू पर चलाने की कोशिश कर रहे दो प्रक्रियाओं, या एक बहुप्रचारित ऐप दो धागे के साथ दो संदर्भों को खोलने की कोशिश करेगा। उत्तरार्द्ध CUDA 4 में ऐसा करने के लिए बहुत कठिन होता है। – talonmies

+0

फिर एकाधिक संदर्भों के लिए स्मृति आवंटित करने के लिए किस तंत्र का उपयोग किया जाता है? सिस्टम कैसे सुनिश्चित कर सकता है कि विभिन्न संदर्भों को स्मृति के विभिन्न भाग आवंटित किए जाएंगे? – xhe8

4
  1. जीपीयू ऑफ-चिप मेमोरी वैश्विक, स्थानीय और निरंतर स्मृति में अलग हो गई है। यह तीन स्मृति प्रकार वर्चुअल मेमोरी अवधारणा हैं। ग्लोबल मेमोरी सभी धागे के लिए नि: शुल्क है, स्थानीय केवल एक थ्रेड के लिए है (ज्यादातर पंजीकरण स्पिलिंग के लिए उपयोग किया जाता है) और निरंतर मेमोरी वैश्विक मेमोरी कैश की जाती है (मेजबान कोड से केवल लिखने योग्य)। CUDA सी प्रोग्रामिंग गाइड से 5.3.2 पर एक नज़र डालें।

  2. संपादित करें: हटाया

  3. मेमोरी cudaMalloc ओवरलैप कभी नहीं करता है के माध्यम से आवंटित। स्मृति के लिए रनटाइम के दौरान आवंटित कर्नेल पर्याप्त स्मृति उपलब्ध होना चाहिए। यदि आप स्मृति से बाहर हैं और कर्नेल (केवल मुझसे अनुमान लगाते हैं) शुरू करने का प्रयास करते हैं तो आपको "अज्ञात त्रुटि" त्रुटि संदेश प्राप्त करना चाहिए। ड्राइवर कर्नेल को शुरू करने और/या निष्पादित करने में असमर्थ था।

+0

आपके उत्तर के लिए धन्यवाद। लेकिन मुझे लगता है कि मैं अधिक निम्न स्तर की व्याख्या चाहता हूं। मैंने अन्य पदों से सीखा है कि सीयूडीए मेमोरी प्रबंधन में संदर्भों और कुछ डेटा संरचनाओं से निपटने के लिए कुछ है, लेकिन मैं अधिक स्पष्टीकरण चाहता हूं ताकि मैं अपने कार्यक्रम में स्मृति समस्या का पता लगा सकूं। – xhe8

+0

आपका दूसरा उत्तर ज्यादातर गलत है। एक डिवाइस पर संदर्भ स्थापित होने पर कर्नेल स्कोप मेमोरी * पूर्व आवंटित * ​​है। स्थानीय मेमोरी की सामग्री केवल कर्नेल रन की अवधि के लिए मान्य होती है, लेकिन एक संदर्भ स्थापित होने पर स्मृति स्वयं आरक्षित होती है। गतिशील स्मृति को रनटाइम ढेर से आवंटित किया जाता है जो संदर्भ प्रतिष्ठान समय पर भी आरक्षित होता है और यह संदर्भ के जीवन के लिए सुलभ और वैध रहता है, कर्नेल नहीं। यदि आवश्यक हो तो डिफ़ॉल्ट आकार से रनटाइम पर ढेर आकार में हेरफेर करने के लिए एक एपीआई कॉल है। – talonmies

+0

@talonmies मुझे आपकी जानकारी के लिए धन्यवाद –