2009-04-27 5 views
5

मैं हाल ही में सी ++ में गहराई से जा रहा हूं और मेरी बग जटिल लगती है।सी ++: यह कैसे संभव है कि डेटा पढ़ने से स्मृति प्रभावित हो सके?

मेरे पास ऑब्जेक्ट्स का वेक्टर है, प्रत्येक ऑब्जेक्ट में फ्लोट्स का वेक्टर होता है। मैंने फैसला किया कि मुझे एक और फ्लैट सरणी बनाने की ज़रूरत है जिसमें सभी वस्तुओं के सभी फ्लोट वैल्यू हों। यह उससे थोड़ा अधिक जटिल है लेकिन समस्या का सारांश यह है कि जैसे ही मैं अपनी वस्तुओं के माध्यम से फ्लोट मूल्यों को निकालने के माध्यम से लूप करता हूं, कुछ बिंदु पर वस्तुओं का मेरा वेक्टर बदल जाता है, या कुछ अजीब तरीके से दूषित हो जाता है। (मेरे पठन ऑपरेशन सभी कॉन्स फ़ंक्शन हैं)

एमपीआईआई के साथ एक और उदाहरण था। मैं बस शुरू कर रहा था इसलिए मैं सिर्फ अपनी ही मेमोरी के साथ दो अलग-अलग नोड्स पर एक ही कोड चलाने के लिए चाहता था और बिना डेटा हस्तांतरण के, सभी बहुत ही सरल। मेरे आश्चर्य के लिए मुझे सेगमेंटेशन त्रुटियां मिलीं और घंटों के ट्रैकिंग के बाद, मैंने पाया कि एक चर का एक असाइनमेंट पूर्ण रूप से पूर्ण रूप से भिन्न चर सेट कर रहा था।

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

अद्यतन: यहां कोड का एक सेगमेंट है, मैंने मूल रूप से पोस्ट नहीं किया क्योंकि मुझे यकीन नहीं है कि पूरे सिस्टम को समझे बिना इसे कितना निकाला जा सकता है।

एक चीज जो मैंने अभी पाया वह यह था कि जब मैंने अपने फ्लैट सरणी को मान निर्दिष्ट करना बंद कर दिया और इसके बजाय बस cout'ed, seg त्रुटियां गायब हो गईं। तो शायद मैं अपनी सरणी को गलत घोषित कर रहा हूं, लेकिन अगर मैं भी था तो मुझे यकीन नहीं है कि यह ऑब्जेक्ट वेक्टर को कैसे प्रभावित करेगा।

flatFitness = new float(popSize); 

अद्यतन 2:

void xlMasterSlaveGpuEA::FillFlatGenes() { 
    int stringLength = pop->GetGenome(0).GetLength(); 
    for (int i=0;i<pop->GetPopSize();i++) 
     for (int j=0;j<stringLength;j++) 
      flatGenes[(i*stringLength)+j]<< pop->GetGenome(i).GetFloatGene(j); 
} 

float xlVectorGenome::GetFloatGene(unsigned int i) const { 
    return GetGene(i); 
} 

मेरी फ्लैट सरणी एक सदस्य समारोह

float * flatFitness; 

तो जैसे निर्माता में initailsed है

मैं बस का कहना है कि करना चाहते हैं उपरोक्त दो उदाहरण संबंधित नहीं हैं, पहला वाला बहु थ्रेड नहीं है। दूसरा एमपीआई उदाहरण तकनीकी रूप से है, लेकिन एमपीआई को स्मृति वितरित किया गया है और मैंने जानबूझकर सबसे सरल कार्यान्वयन का प्रयास किया जो मैं सोच सकता था, जो दोनों मशीनें स्वतंत्र रूप से कोड चल रही हैं। लेकिन वहाँ एक अतिरिक्त विस्तार है, मैं एक condtional कह

if node 1 then do bottom half of loop 

if node 1 then do top half 

फिर स्मृति अलग करना चाहिए, वे काम किया जाना चाहिए के रूप में यदि वे एक दूसरे के बारे में कुछ भी नहीं पता .. लेकिन यह सशर्त को दूर करने और बनाने दोनों छोरों कर में डाल सभी क्यूब्स, त्रुटि

+0

आप अपने कोड का एक संक्षिप्त संस्करण पोस्ट कर सकते हैं? यह हो सकता है कि यह क्या हो रहा है, यह बताने में बहुत मुश्किल है। – tgamblin

+0

आप पाश कोड जहां वेक्टर में वस्तुओं पुनरावृति पोस्ट कर सके ... संभवतः आप स्मृति पर वहाँ कदम कर रहे हैं? – Balk

+1

पढ़ें ऑपरेशन मूल्यों को नहीं बदलते हैं। आपके कोड में कुछ और होना चाहिए। आपका दूसरा उदाहरण गलत स्थान पर इंगित चर के एक सामान्य स्थिति है। – fbinder

उत्तर

14

यह एक सरणी निर्माता नहीं है:

float * flatFitness; 
flatFitness = new float(popSize); 

आप यहां ढेर पर एक फ्लोट बना रहे हैं, मूल्य popSize के साथ शुरू किया गया है। आप तैरता की एक सरणी चाहते हैं तो आप कोष्ठकों के बजाय कोष्ठक उपयोग करने की आवश्यकता:

float *flatFitness = new float[popSize]; 

यह आसानी से समस्याओं को आप का वर्णन कारण हो सकता है। यह भी ध्यान रखें कि जब आप सरणियों बनाते हैं, आप delete [] (अंततः) का उपयोग कर हटाने की आवश्यकता:

delete [] flatFitness; 

तुम सिर्फ delete उपयोग करते हैं, यह काम हो सकता है, लेकिन व्यवहार अनिर्धारित रहता है।

आप पूरी तरह सरणी सिंटेक्स के उपयोग से बचना चाहते हैं, क्यों std::vector का उपयोग नहीं? आप इस तरह popSize तत्वों का एक वेक्टर बना सकते हैं:

#include <vector> 

std::vector<float> flatFitness(popSize); 

यह स्वचालित रूप से जब यह क्षेत्र से बाहर हो जाता है मुक्त हो जाएगा, तो आप new के बारे में या delete में चिंता करने की जरूरत नहीं है।

अद्यतन (पुन: टिप्पणी): आप पहले से ही अपने कोड में कहीं std::vectors उपयोग कर रहे हैं, std::vector::swap() पर एक नज़र डालें। आप नकल बातें पूरी तरह से बचने के लिए और सिर्फ CUDA के लिए बफरिंग और प्रसंस्करण तुम यहाँ क्या कर रहे हैं के बीच आगे पीछे एक जोड़ी वैक्टर स्वैप कर सकता है।

+0

धन्यवाद, मैं इसे – zenna

+0

से देख सकता हूं कि मैं std :: vectors से डेटा निकाल रहा हूं क्योंकि मुझे इसे CUDA के माध्यम से GPU को भेजने की आवश्यकता है। शायद – zenna

+0

वेक्टर :: स्वैप() पर एक और अधिक सुरुचिपूर्ण तरीका है। आप यहां कुछ वैक्टरों को तुरंत चालू करने में सक्षम हो सकते हैं, फिर उन लोगों के साथ उन्हें स्वैप करें जिन्हें आप CUDA के लिए उपयोग करते हैं ताकि आपको कोई भी प्रतिलिपि करने की आवश्यकता न हो। बस सुनिश्चित करें कि वे आकार बदलने() या कन्स्ट्रक्टर (उपरोक्त के रूप में) का उपयोग करके सही आकार हैं, या आप उस स्मृति में लिखना समाप्त कर सकते हैं जो आपके पास नहीं है। – tgamblin

0

मुझे संदेह है कि आपके पास बहु-थ्रेडिंग या स्मृति भ्रष्टाचार के मुद्दे हैं जिन्हें आप जानते नहीं हैं। आपके द्वारा वर्णित व्यवहार किसी भी प्रकार का मानक, डिज़ाइन, वांछनीय व्यवहार नहीं है।

+0

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

+1

शायद, सिवाय इसके कि उसने कभी नहीं कहा कि वह धागे का उपयोग कर रहा था। एमपीआई प्रक्रिया-स्तर समांतरता है जबतक कि आप इसे किसी और चीज़ से जोड़ते हैं। – tgamblin

+0

हे, वहाँ कोई कोड पोस्ट किया जब मैंने जवाब था। –

-1

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

संपादित (अपने अद्यतन के आधार पर):

यह दोषपूर्ण हो सकता है: stringLength बाहरी लूप के बाहर आरंभ नहीं हो जाता है, लेकिन यह है कि बाहरी पाश दौरान अपडेट करने की आवश्यकता की तरह यह लग रहा है:

int stringLength = pop->GetGenome(0).GetLength(); 
for (int i=0;i<pop->GetPopSize();i++) 
    for (int j=0;j<stringLength;j++) 
     flatGenes[(i*stringLength)+j]<< pop->GetGenome(i).GetFloatGene(j); 

सुझाए गए फिक्स:

for (int i=0;i<pop->GetPopSize();i++) { 
    int stringLength = pop->GetGenome(i).GetLength(); 
    for (int j=0;j<stringLength;j++) { 
     flatGenes[(i*stringLength)+j]<< pop->GetGenome(i).GetFloatGene(j); 
    } 
} 
संबंधित मुद्दे