GCC कोड के> 2 GB के साथ त्रुटि संकलित करता है


108

मेरे पास ऑब्जेक्ट कोड के लगभग 2.8 GB के कुल कार्यों की एक बड़ी संख्या है (दुर्भाग्य से इसके आसपास कोई रास्ता नहीं है, वैज्ञानिक कंप्यूटिंग ...)

जब मैं उन्हें लिंक करने की कोशिश करता हूं, तो मुझे (अपेक्षित) relocation truncated to fit: R_X86_64_32Sत्रुटियां मिलती हैं, जो मुझे कंपाइलर ध्वज को निर्दिष्ट करने से रोकने की उम्मीद थी -mcmodel=medium। सभी पुस्तकालय जो इसके अलावा मेरे नियंत्रण से जुड़े हैं, को -fpicध्वज के साथ संकलित किया गया है ।

फिर भी, त्रुटि बनी रहती है, और मुझे लगता है कि मेरे द्वारा लिंक किए गए कुछ पुस्तकालयों को PIC के साथ संकलित नहीं किया गया है।

यहाँ त्रुटि है:

/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crt1.o: In function `_start':
(.text+0x12): relocation truncated to fit: R_X86_64_32S against symbol `__libc_csu_fini'     defined in .text section in /usr/lib64/libc_nonshared.a(elf-init.oS)
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crt1.o: In function `_start':
(.text+0x19): relocation truncated to fit: R_X86_64_32S against symbol `__libc_csu_init'    defined in .text section in /usr/lib64/libc_nonshared.a(elf-init.oS)
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crti.o: In function    `call_gmon_start':
(.text+0x7): relocation truncated to fit: R_X86_64_GOTPCREL against undefined symbol      `__gmon_start__'
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/crtbegin.o: In function `__do_global_dtors_aux':
crtstuff.c:(.text+0xb): relocation truncated to fit: R_X86_64_PC32 against `.bss' 
crtstuff.c:(.text+0x13): relocation truncated to fit: R_X86_64_32 against symbol `__DTOR_END__' defined in .dtors section in /usr/lib/gcc/x86_64-redhat-linux/4.1.2/crtend.o
crtstuff.c:(.text+0x19): relocation truncated to fit: R_X86_64_32S against `.dtors'
crtstuff.c:(.text+0x28): relocation truncated to fit: R_X86_64_PC32 against `.bss'
crtstuff.c:(.text+0x38): relocation truncated to fit: R_X86_64_PC32 against `.bss'
crtstuff.c:(.text+0x3f): relocation truncated to fit: R_X86_64_32S against `.dtors'
crtstuff.c:(.text+0x46): relocation truncated to fit: R_X86_64_PC32 against `.bss'
crtstuff.c:(.text+0x51): additional relocation overflows omitted from the output
collect2: ld returned 1 exit status
make: *** [testsme] Error 1

और सिस्टम लाइब्रेरी मैं के खिलाफ लिंक:

-lgfortran -lm -lrt -lpthread

कोई सुराग जहां समस्या के लिए देखने के लिए?

संपादित करें: सबसे पहले, चर्चा के लिए धन्यवाद ... थोड़ा स्पष्ट करने के लिए, मेरे पास सैकड़ों कार्य हैं (प्रत्येक लगभग 1 एमबी अलग-अलग ऑब्जेक्ट फ़ाइलों में आकार में) जैसे:

double func1(std::tr1::unordered_map<int, double> & csc, 
             std::vector<EvaluationNode::Ptr> & ti, 
             ProcessVars & s)
{
    double sum, prefactor, expr;

    prefactor = +s.ds8*s.ds10*ti[0]->value();
    expr =       ( - 5/243.*(s.x14*s.x15*csc[49300] + 9/10.*s.x14*s.x15*csc[49301] +
           1/10.*s.x14*s.x15*csc[49302] - 3/5.*s.x14*s.x15*csc[49303] -
           27/10.*s.x14*s.x15*csc[49304] + 12/5.*s.x14*s.x15*csc[49305] -
           3/10.*s.x14*s.x15*csc[49306] - 4/5.*s.x14*s.x15*csc[49307] +
           21/10.*s.x14*s.x15*csc[49308] + 1/10.*s.x14*s.x15*csc[49309] -
           s.x14*s.x15*csc[51370] - 9/10.*s.x14*s.x15*csc[51371] -
           1/10.*s.x14*s.x15*csc[51372] + 3/5.*s.x14*s.x15*csc[51373] +
           27/10.*s.x14*s.x15*csc[51374] - 12/5.*s.x14*s.x15*csc[51375] +
           3/10.*s.x14*s.x15*csc[51376] + 4/5.*s.x14*s.x15*csc[51377] -
           21/10.*s.x14*s.x15*csc[51378] - 1/10.*s.x14*s.x15*csc[51379] -
           2*s.x14*s.x15*csc[55100] - 9/5.*s.x14*s.x15*csc[55101] -
           1/5.*s.x14*s.x15*csc[55102] + 6/5.*s.x14*s.x15*csc[55103] +
           27/5.*s.x14*s.x15*csc[55104] - 24/5.*s.x14*s.x15*csc[55105] +
           3/5.*s.x14*s.x15*csc[55106] + 8/5.*s.x14*s.x15*csc[55107] -
           21/5.*s.x14*s.x15*csc[55108] - 1/5.*s.x14*s.x15*csc[55109] -
           2*s.x14*s.x15*csc[55170] - 9/5.*s.x14*s.x15*csc[55171] -
           1/5.*s.x14*s.x15*csc[55172] + 6/5.*s.x14*s.x15*csc[55173] +
           27/5.*s.x14*s.x15*csc[55174] - 24/5.*s.x14*s.x15*csc[55175] +
           // ...
           ;

        sum += prefactor*expr;
    // ...
    return sum;
}

ऑब्जेक्ट sअपेक्षाकृत छोटा है और आवश्यक स्थिरांक x14, x15, ..., ds0, ..., इत्यादि को रखता है जबकि tiबाहरी पुस्तकालय से केवल एक डबल रिटर्न देता है। जैसा कि आप देख सकते हैं, csc[]मूल्यों का एक पूर्व-निर्मित नक्शा है जिसका मूल्यांकन अलग-अलग ऑब्जेक्ट फ़ाइलों में भी किया गया है (फिर से प्रत्येक के बारे में ~ 1 एमबी आकार के साथ सैकड़ों):

void cscs132(std::tr1::unordered_map<int,double> & csc, ProcessVars & s)
{
    {
    double csc19295 =       + s.ds0*s.ds1*s.ds2 * ( -
           32*s.x12pow2*s.x15*s.x34*s.mbpow2*s.mWpowinv2 -
           32*s.x12pow2*s.x15*s.x35*s.mbpow2*s.mWpowinv2 -
           32*s.x12pow2*s.x15*s.x35*s.x45*s.mWpowinv2 -
           32*s.x12pow2*s.x25*s.x34*s.mbpow2*s.mWpowinv2 -
           32*s.x12pow2*s.x25*s.x35*s.mbpow2*s.mWpowinv2 -
           32*s.x12pow2*s.x25*s.x35*s.x45*s.mWpowinv2 +
           32*s.x12pow2*s.x34*s.mbpow4*s.mWpowinv2 +
           32*s.x12pow2*s.x34*s.x35*s.mbpow2*s.mWpowinv2 +
           32*s.x12pow2*s.x34*s.x45*s.mbpow2*s.mWpowinv2 +
           32*s.x12pow2*s.x35*s.mbpow4*s.mWpowinv2 +
           32*s.x12pow2*s.x35pow2*s.mbpow2*s.mWpowinv2 +
           32*s.x12pow2*s.x35pow2*s.x45*s.mWpowinv2 +
           64*s.x12pow2*s.x35*s.x45*s.mbpow2*s.mWpowinv2 +
           32*s.x12pow2*s.x35*s.x45pow2*s.mWpowinv2 -
           64*s.x12*s.p1p3*s.x15*s.mbpow4*s.mWpowinv2 +
           64*s.x12*s.p1p3*s.x15pow2*s.mbpow2*s.mWpowinv2 +
           96*s.x12*s.p1p3*s.x15*s.x25*s.mbpow2*s.mWpowinv2 -
           64*s.x12*s.p1p3*s.x15*s.x35*s.mbpow2*s.mWpowinv2 -
           64*s.x12*s.p1p3*s.x15*s.x45*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.p1p3*s.x25*s.mbpow4*s.mWpowinv2 +
           32*s.x12*s.p1p3*s.x25pow2*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.p1p3*s.x25*s.x35*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.p1p3*s.x25*s.x45*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.p1p3*s.x45*s.mbpow2 +
           64*s.x12*s.x14*s.x15pow2*s.x35*s.mWpowinv2 +
           96*s.x12*s.x14*s.x15*s.x25*s.x35*s.mWpowinv2 +
           32*s.x12*s.x14*s.x15*s.x34*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.x14*s.x15*s.x35*s.mbpow2*s.mWpowinv2 -
           64*s.x12*s.x14*s.x15*s.x35pow2*s.mWpowinv2 -
           32*s.x12*s.x14*s.x15*s.x35*s.x45*s.mWpowinv2 +
           32*s.x12*s.x14*s.x25pow2*s.x35*s.mWpowinv2 +
           32*s.x12*s.x14*s.x25*s.x34*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.x14*s.x25*s.x35pow2*s.mWpowinv2 -
           // ...

       csc.insert(cscMap::value_type(192953, csc19295));
    }

    {
       double csc19296 =      // ... ;

       csc.insert(cscMap::value_type(192956, csc19296));
    }

    // ...
}

यह इसके बारे में। अंतिम चरण तो बस उन सभी को कॉल करने func[i]और परिणाम को संक्षेप में शामिल करने के लिए है।

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

EDIT2: मुझे यह भी जोड़ना चाहिए कि x12, x13, आदि वास्तव में स्थिरांक नहीं हैं। वे विशिष्ट मानों पर सेट होते हैं, उन सभी कार्यों को चलाया जाता है और परिणाम वापस आ जाता है, और फिर अगले मूल्य का उत्पादन करने के लिए x12, x13, आदि का एक नया सेट चुना जाता है। और यह 10 ^ 5 से 10 ^ 6 बार करना होगा ...

EDIT3: अब तक के सुझावों और चर्चा के लिए धन्यवाद ... मैं कोशिश करूंगा कि किसी भी तरह कोड जेनरेशन पर लूप रोल करूं, यकीन नहीं हो रहा है कि यह कैसे होगा, ईमानदार होना चाहिए, लेकिन यह सबसे अच्छा दांव है।

BTW, मैं "यह वैज्ञानिक कंप्यूटिंग है - अनुकूलन का कोई तरीका नहीं" के पीछे छिपाने की कोशिश नहीं की। यह सिर्फ इतना है कि इस कोड का आधार कुछ ऐसा है जो एक "ब्लैक बॉक्स" से निकलता है, जहां मेरे पास कोई वास्तविक पहुंच नहीं है और इसके अलावा, पूरी चीज ने सरल उदाहरणों के साथ बहुत अच्छा काम किया है, और मैं मुख्य रूप से एक वास्तविक में क्या होता है से अभिभूत महसूस करता हूं विश्व अनुप्रयोग ...

EDIT4: तो, मैंने cscकंप्यूटर बीजगणित प्रणाली ( Mathematica ) में अभिव्यक्तियों को सरल करके एक के बाद एक परिभाषाओं के कोड आकार को कम करने में कामयाबी हासिल की है । मैं अब इसे कोड के निर्माण से पहले कुछ अन्य ट्रिक्स लागू करके या इसे कम करने का कोई तरीका देखता हूं (जो कि इस हिस्से को लगभग 100 एमबी तक लाएगा) और मुझे उम्मीद है कि यह विचार काम करेगा।

अब आपके उत्तरों से संबंधित: मैं लूप्स को फिर से funcएस में रोल करने की कोशिश कर रहा हूं , जहां कैस ज्यादा मदद नहीं करेगा, लेकिन मेरे पास पहले से ही मेरे विचार हैं। उदाहरण के लिए, जैसे चर द्वारा भावों को x12, x13,...छाँटना, cscपायथन के साथ s को पार्स करना और उन तालिकाओं को उत्पन्न करना जो उन्हें एक दूसरे से संबंधित करते हैं। फिर मैं कम से कम इन भागों को छोरों के रूप में उत्पन्न कर सकता हूं। जैसा कि यह अब तक का सबसे अच्छा समाधान प्रतीत होता है, मैं इसे सर्वश्रेष्ठ उत्तर के रूप में चिह्नित करता हूं।

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

आपके सुझाव और मदद के लिए आप सभी का धन्यवाद। अगर किसी को दिलचस्पी है, तो मैं तैयार होते ही अंतिम परिणाम पोस्ट करने जा रहा हूं।

टिप्पणी: कुछ अन्य जवाबों के लिए बस कुछ टिप्पणी: मैं जिस कोड को चलाने की कोशिश कर रहा हूं, वह सरल कार्यों / एल्गोरिदम के विस्तार में नहीं है और अनावश्यक अनावश्यक घूमना है। वास्तव में क्या होता है कि हम जो सामान शुरू करते हैं वह बहुत जटिल गणितीय वस्तुएं होती हैं और उन्हें संख्यात्मक रूप से गणना करने योग्य रूप में लाती है । समस्या वास्तव में अंतर्निहित भौतिक सिद्धांत में निहित है। मध्यवर्ती अभिव्यक्तियों की जटिलता तथ्यात्मक रूप से तराजू है, जो अच्छी तरह से ज्ञात है, लेकिन जब भौतिक रूप से औसत दर्जे का कुछ करने के लिए इस सामान को जोड़ते हैं - तो यह केवल एक मुट्ठी भर छोटे कार्यों को उबालता है जो अभिव्यक्तियों का आधार बनाते हैं। (सामान्य के साथ इस संबंध में निश्चित रूप से कुछ "गलत" है और केवल उपलब्ध हैansatz जिसे "गड़बड़ी सिद्धांत" कहा जाता है) हम इस ansatz को दूसरे स्तर पर लाने की कोशिश करते हैं, जो कि विश्लेषणात्मक रूप से संभव नहीं है और जहां आवश्यक कार्यों का आधार ज्ञात नहीं है। तो हम इसे इस तरह से बल देने की कोशिश करते हैं। सबसे अच्छा तरीका नहीं है, लेकिन उम्मीद है कि अंत में भौतिकी की हमारी समझ में मदद करता है ...

पिछले संस्करण: आपके सभी सुझावों के लिए धन्यवाद, मैंने मैथमैटिका और funcशीर्ष उत्तर की तर्ज पर कुछ हद तक कोड जनरेटर के संशोधन का उपयोग करके कोड आकार को काफी कम करने में कामयाब रहा है :)

मैंने cscMathematica के साथ कार्यों को सरल किया है , इसे 92 एमबी तक लाया है। यह इर्रिडिएबल पार्ट है। पहले प्रयास ने हमेशा के लिए ले लिया, लेकिन कुछ अनुकूलन के बाद अब यह एक सीपीयू पर लगभग 10 मिनट चलता है।

funcएस पर प्रभाव नाटकीय था: उनके लिए पूरे कोड का आकार लगभग 9 एमबी तक है, इसलिए कोड अब 100 एमबी की सीमा में है। अब यह अनुकूलन को चालू करने के लिए समझ में आता है और निष्पादन काफी तेज है।

फिर से, आप सभी को आपके सुझावों के लिए धन्यवाद, मैंने बहुत कुछ सीखा है।


17
यदि आपके पास इतना डेटा है, तो आपको इसे स्रोत फ़ाइलों से बाहर ले जाना चाहिए और इसके बजाय mmapयह रनटाइम के दौरान बाहरी बाइनरी से खुद को निकालना होगा ।
आर .. गिटहब स्टॉप हेल्पिंग ICE

3
क्या आप इन कार्यों में से एक (या दो) का उदाहरण दे सकते हैं? यह वास्तव में अजीब लग रहा है। आप इन कार्यों को dl * फ़ंक्शन के साथ गतिशील रूप से लोड कर सकते हैं।
पैट्रिक श्ल्टर

7
@bbtrb: मेरी पहली वृत्ति R .. के समान है, यह एक डिजाइन समस्या की तरह लगता है। जाहिर है, मुझे नहीं पता कि वैज्ञानिक कंप्यूटिंग सर्किलों में क्या आम है, लेकिन मैंने कभी किसी को 2.8GB ऑब्जेक्ट फ़ाइल, या इसके करीब कुछ भी लिंक करने की कोशिश के बारे में नहीं सुना है, और मुझे यकीन नहीं है कि जीसीसी वास्तव में इसका समर्थन करेगा। सच कहूँ, मुझे लगता है कि शुद्ध स्पेगेटी होने के लिए उस आकार के किसी भी कोड बूँद की उम्मीद होगी।
निकोलस नाइट

46
वहाँ बिल्कुल कोई रास्ता नहीं है कि समस्या के लिए इष्टतम समाधान 2gb वस्तु फ़ाइल शामिल है।
डेविड हेफर्नन

35
अपना डेटा कोड में न रखें
डेविड हेफ़रनन

जवाबों:


53

तो, आपके पास पहले से ही एक प्रोग्राम है जो इस पाठ का निर्माण करता है:

prefactor = +s.ds8*s.ds10*ti[0]->value();
expr = ( - 5/243.*(s.x14*s.x15*csc[49300] + 9/10.*s.x14*s.x15*csc[49301] +
       1/10.*s.x14*s.x15*csc[49302] - 3/5.*s.x14*s.x15*csc[49303] -...

तथा

double csc19295 =       + s.ds0*s.ds1*s.ds2 * ( -
       32*s.x12pow2*s.x15*s.x34*s.mbpow2*s.mWpowinv2 -
       32*s.x12pow2*s.x15*s.x35*s.mbpow2*s.mWpowinv2 -
       32*s.x12pow2*s.x15*s.x35*s.x45*s.mWpowinv2 -...

सही?

यदि आपके सभी कार्यों में एक समान "प्रारूप" है (संख्या n बार m गुणा करें और परिणाम जोड़ें - या कुछ समान) तो मुझे लगता है कि आप यह कर सकते हैं:

  • स्ट्रिंग के बजाय आउटपुट ऑफ़सेट पर जनरेटर प्रोग्राम को बदलें (यानी स्ट्रिंग "s.ds0" के बजाय यह उत्पादन करेगा offsetof(ProcessVars, ds0)
  • ऐसे ऑफसेट की एक सरणी बनाएं
  • एक मूल्यांकनकर्ता लिखें जो ऊपर दिए गए सरणी और संरचना के संकेत के आधार पते को स्वीकार करता है और एक परिणाम पैदा करता है

सरणी + मूल्यांकनकर्ता आपके कार्यों में से एक के रूप में एक ही तर्क का प्रतिनिधित्व करेगा, लेकिन केवल मूल्यांकनकर्ता कोड होगा। सरणी "डेटा" है और इसे या तो रनटाइम पर उत्पन्न किया जा सकता है या डिस्क पर सहेजा जा सकता है और आई चंक्स पढ़ सकता है या मेमोरी मैप की गई फ़ाइल के साथ।

Func1 में अपने विशेष उदाहरण के लिए कल्पना कैसे आप एक मूल्यांकनकर्ता के माध्यम से समारोह को फिर से लिखने होगा यदि आप के आधार का पता करने के लिए जाने की अनुमति थी sऔर cscऔर भी स्थिरांक और ऑफसेट आप आधार पतों को जोड़ने के लिए करने के लिए प्राप्त करने की आवश्यकता के प्रतिनिधित्व की तरह एक वेक्टर x14, ds8तथाcsc[51370]

आपको "डेटा" का एक नया रूप बनाने की आवश्यकता है जो यह वर्णन करेगा कि आप अपने विशाल कार्यों को पास करने वाले वास्तविक डेटा को कैसे संसाधित करें।


45

X86-64 ABI लिनक्स द्वारा इस्तेमाल किया एक "बड़े मॉडल" विशेष रूप से इस तरह के आकार सीमाओं, जो मिला है और PLT के लिए 64-बिट स्थानांतरण प्रकार शामिल हैं से बचने के लिए परिभाषित करता है। (खंड 4.4.2 में तालिका देखें, और 3.5.5 में निर्देश अनुक्रम जो बताते हैं कि उनका उपयोग कैसे किया जाता है।)

चूंकि आपके कार्य 2.8 जीबी पर कब्जा कर रहे हैं, आप भाग्य से बाहर हैं, क्योंकि जीसीसी बड़े मॉडल का समर्थन नहीं करते हैं। आप क्या कर सकते हैं, अपने कोड को इस तरह से पुनर्गठित करना है जो आपको इसे साझा पुस्तकालयों में विभाजित करने की अनुमति देगा जिसे आप लिंक को डायनामिक करेंगे।

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

संपादित करें

बड़े मॉडल की तरह लगता है gcc 4.6 ( इस पृष्ठ को देखें ) द्वारा समर्थित है । आप यह कोशिश कर सकते हैं, लेकिन ऊपर अभी भी अपने कोड को पुनर्गठित करने के बारे में लागू होता है।


तो आप क्या कह रहे हैं कि जब मैं ऑब्जेक्ट फ़ाइलों को कई छोटे साझा पुस्तकालयों में समूहित करूंगा, तो मैं सीमाओं को पार करूंगा?
18

3
@bbtrb अधिकार। लेकिन मैं अभी भी आपके कार्यों को लागू करने के दूसरे तरीके की खोज करूंगा। मुझे यकीन है कि आपका संकलन हमेशा के लिए लेता है
B'овић

18
WTF? यह कोड कुछ स्क्रिप्ट द्वारा उत्पन्न किया जाना चाहिए; कोई भी हाथ से कोड की मेगाबाइट नहीं लिखता है! समान तर्क जो कोड उत्पन्न करता है , का उपयोग संगणना को चलाने के लिए भी किया जा सकता है।
झवरा

6
मैं दृढ़ता से gcc 4.6 को आज़माने की सलाह देता हूँ, यह gcc 4.1 की तुलना में इस कार्यक्रम के लिए बेहतर कोड तैयार करने की बहुत संभावना है; यह पूरी तरह से 2GB में पूरी तरह से निचोड़ने में सक्षम हो सकता है आपके पास कुछ भी चालाक करने के लिए, समस्या को समाप्त करने की कोशिश (-Os, -fwhole- प्रोग्राम और -फ्लो के संयोजन) - कोड की इस मात्रा के साथ, आकार के लिए अनुकूलन है। गति के लिए अनुकूलन)। हालाँकि, यदि वह पर्याप्त मदद नहीं करता है, तो आपको यह भी पता होना चाहिए कि बड़े मॉडल को काम करने के लिए, आपको बड़े मॉडल (crt * .o, libc_nonsared.a) में C लाइब्रेरी के कम से कम हिस्से का पुनर्निर्माण करना होगा। , और libpthread_nonsared.a)।
zwol

1
@bdonlan स्टेटिक लिंकिंग भी एक संभावना है।
झवरा

37

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


21

त्रुटि तब होती है क्योंकि आपके पास बहुत अधिक CODE है, डेटा नहीं! यह उदाहरण के लिए इंगित किया गया है __libc_csu_fini(जो एक फ़ंक्शन है) से संदर्भित किया जा रहा है _startऔर स्थानांतरण को फिट करने के लिए छोटा किया गया है। इस का मतलब है कि_start (प्रोग्राम का सही प्रवेश बिंदु) उस फ़ंक्शन को SIGNED 32-बिट ऑफ़सेट के माध्यम से कॉल करने का प्रयास कर रहा है, जिसमें केवल 2 जीबी की सीमा है। चूँकि आपके ऑब्जेक्ट कोड की कुल राशि ~ 2.8 GB है, इसलिए तथ्य जांचते हैं।

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

इसके अलावा, आप csc[]एक अलग कार्यक्रम में गणना कर सकते हैं, परिणामों को एक फ़ाइल में संग्रहीत कर सकते हैं, और केवल आवश्यक होने पर उन्हें लोड कर सकते हैं।


क्या आप एक उदाहरण प्रदान कर सकते हैं कि आप सरल लूप के साथ फ़ंक्शंस को कैसे लिखेंगे? मैं तुम्हारा बिल्कुल पालन नहीं करता। csc[]बहुत बार गणना की जाती है और मैं डिस्क I / O से बचना चाहूंगा।
bbtrb

4
@bbtr: उदाहरण के लिए, func1ऊपर, कुछ इस तरह for (int i = 0; i < N; ++i) expr += constants[i].*s.x14*s.x15*csc[49300 + i];:।
20 नवंबर को हाईकमांडर 4

@ HighCommander4: बिल्कुल, मैं सहमत हूं। यह मेरे सिर के ठीक ऊपर है कि स्वचालित रूप से इस तरह से कुछ कैसे उत्पन्न किया जाए। शायद एक अलग सरणी के साथ जो सूचकांकों को संग्रहीत करता है ...
bbtrb

2
@bbtrb: चूंकि कोई भयावह तरीका नहीं है कि किसी ने हाथ से 2.8GB ऑब्जेक्ट कोड का उत्पादन करने के लिए पर्याप्त स्रोत लिखा हो, विशेष रूप से इस तरह के संयुक्त राष्ट्र के प्रतीक नामों के साथ, एक कोड जनरेटर का उपयोग किया गया होगा । उसी के साथ काम करो।
डोनल फेलो

15

मुझे लगता है कि हर कोई इससे सहमत है कि आप जो करना चाहते हैं, उसे करने का एक अलग तरीका होना चाहिए। कोड के सैकड़ों मेगाबाइट (गीगाबाइट्स?) को संकलित करना, इसे बहु-गीगाबाइट आकार के निष्पादन योग्य में जोड़ना और इसे चलाना बहुत ही अयोग्य लगता है।

यदि मैं आपकी समस्या को सही ढंग से समझता हूं, तो आप कुछ प्रकार के कोड जनरेटर का उपयोग करते हैं, जी, कार्यों का एक गुच्छा उत्पन्न करने के लिए func1...Nजो csc1...Mइनपुट के रूप में नक्शे का एक गुच्छा लेते हैं । आप जो भी करना चाहते हैं csc1...M, उसकी गणना और अलग-अलग इनपुट्स के लिए 1,000,000 बार लूप चलाएं और हर बार खोजें s = func1 + func2 + ... + funcN। आपने यह निर्दिष्ट नहीं किया कि कैसे fucn1...Nसंबंधित हैं csc1...M

यदि यह सब सच है, तो ऐसा लगता है कि आपको समस्या को अपने सिर पर अलग-अलग तरीके से चालू करने में सक्षम होना चाहिए जो संभवतः अधिक प्रबंधनीय हो सकता है और यहां तक ​​कि संभवतः तेज भी हो सकता है (यानी आपकी मशीन के कैश को वास्तव में कार्य करने के लिए)।

ऑब्जेक्ट फ़ाइलों के आकार की व्यावहारिक समस्या के अलावा, आपका वर्तमान कार्यक्रम कुशल नहीं होगा क्योंकि यह डेटा तक पहुंच का स्थानीयकरण नहीं करता है (बहुत सारे विशाल नक्शे) और इसका कोई स्थानीय कोड निष्पादन नहीं है (बहुत अधिक लंबे कार्य)।

अपने कार्यक्रम को 3 चरण में तोड़ने के बारे में: चरण 1 का निर्माण csc1...Mऔर उन्हें संग्रहीत करना। चरण 2 funcएक समय में एक निर्माण करता है, इसे प्रत्येक इनपुट के साथ 1,000,000 बार चलाएं और परिणामों को संग्रहीत करें। चरण 3 func1...N1,000,000 बार के प्रत्येक रन के लिए संग्रहीत परिणामों के परिणामों का योग पाते हैं । इस समाधान के बारे में अच्छी बात यह है कि इसे कई स्वतंत्र मशीनों के समानांतर आसानी से बनाया जा सकता है।

संपादित करें: @bbtrb, क्या आप एक func और एक csc उपलब्ध कर सकते हैं? वे अत्यधिक नियमित और संकुचित होने लगते हैं। उदाहरण के लिए, func1 में केवल प्रत्येक गुणांक का योग है, जिसमें प्रत्येक में 1 गुणांक, 2 अनुक्रमणिका में चर और 1 अनुक्रमणिका में csc है। तो यह एक अच्छा पाश को कम किया जा सकता है। यदि आप पूर्ण उदाहरण उपलब्ध कराते हैं, तो मुझे यकीन है कि लंबी अभिव्यक्तियों के बजाय उन्हें लूप में संकुचित करने के तरीके खोजे जा सकते हैं।


हां, आप सही ढंग से समझते हैं :) आपके सुझाव के साथ कई समस्याएं हैं: 1. सबसे खराब funcलगभग सभी cscs पर निर्भर है और उन संख्याओं को 10 ^ 6 बार, भी गणना करना है। 2. इनपुट एक अनुकूली मोंटे कार्लो इंटीग्रेटर से प्राप्त किया जाएगा, जिसका अर्थ है कि इंटीग्रेटर को प्रत्येक बिंदु पर पूर्ण परिणाम जानना होगा, यदि आवश्यक हो तो बिंदु के आसपास के क्षेत्र में मेष को परिष्कृत करके परिणामी त्रुटि को कम करने में सक्षम होना चाहिए। 3. csc
दृढ़ता के

1
तो क्या इसका मतलब है कि आप cscप्रत्येक पुनरावृत्ति में प्रत्येक की गणना दूसरों से स्वतंत्र नहीं कर सकते हैं? यदि वे स्वतंत्र थे, तो भी आप प्रत्येक को एक 10 ^ 6 बार चला सकते हैं और परिणामों को संग्रहीत कर सकते हैं। हालांकि, अगर उनके बीच निर्भरताएं हैं, तो शायद आपको यह पता लगाने की जरूरत है कि कौन सा किस से संबंधित है, एक निर्भरता ग्राफ की तरह कुछ, और फिर यह देखने की कोशिश करें कि क्या आप इसे कई स्वतंत्र उप-ग्राफ़ में तोड़ सकते हैं। सब मुझे लगता है कि कुंजी समस्या को कई, स्वतंत्र, उप-समस्याओं में तोड़ना है।
एलेफ्सिन

5

यदि मैं आपकी त्रुटियों को सही ढंग से पढ़ता हूं, तो आपको सीमा से अधिक ले जाने वाला डेटा आरंभिक डेटा अनुभाग है (यदि यह कोड था, तो आपके पास IMHO अधिक त्रुटियां होंगी)। क्या आपके पास वैश्विक डेटा के बड़े सरणियाँ हैं? यदि यह मामला है, तो मैं कार्यक्रम का पुनर्गठन करूंगा ताकि उन्हें गतिशील रूप से आवंटित किया जाए। यदि डेटा को इनिशियलाइज़ किया गया है, तो मैं इसे एक कॉन्फ़िगरेशन फ़ाइल से पढ़ूँगा।

BTW यह देखकर:

(.text + 0x20): `मुख्य 'के लिए अपरिभाषित संदर्भ

मुझे लगता है कि आपको एक और समस्या है।


1
हां, आप सही हैं, बेवकूफ गलती हैं, लेकिन यह अन्य त्रुटियों को हल नहीं करता है।
19

3

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

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

निचला रेखा: 2.8GB कोड को संकलित करना और लिंक करना काम नहीं करता है और इसे काम करने के लिए मजबूर नहीं किया जाना चाहिए। दूसरा रास्ता खोजो।


3

सुझावों का एक जोड़ा: - आकार (-O) के लिए ऑप्टिमाइज़ करें। अपने इनलाइन फ़ंक्शन कॉल, सामान्य फ़ंक्शन कॉल करें। स्ट्रिंग पूलिंग सक्षम करें।

चीजों को अलग-अलग DLL में साझा करने का प्रयास करें (साझा ऑब्जेक्ट, .so के लिए लिनक्स, .dylib for Mac OS X)। सुनिश्चित करें कि वे अनलोड किए जा सकते हैं। फिर मांग पर चीजों को लोड करने के लिए कुछ लागू करें, और ज़रूरत न होने पर उन्हें मुक्त करें।

यदि नहीं, तो अपने कोड को अलग-अलग निष्पादनयोग्य में विभाजित करें, और उनके बीच संवाद करने के लिए कुछ का उपयोग करें (पाइप, सॉकेट, यहां तक ​​कि लिखने / पढ़ने के लिए फ़ाइल)। अनाड़ी, लेकिन आपके पास क्या विकल्प हैं?

पूरी तरह से वैकल्पिक: - JIT के साथ एक गतिशील भाषा का उपयोग करें । मेरे सिर के ठीक ऊपर - LuaJIT का उपयोग करें - और फिर से लिखना (पुन: उत्पन्न करना) Lua में इन अभिव्यक्तियों का एक बहुत , या अन्य ऐसी भाषाएं और रनटाइम जो कोड को कचरा एकत्र करने की अनुमति देते हैं।

LuaJIT काफी कुशल है, कभी-कभी कुछ चीजों के लिए C / C ++ की पिटाई होती है, लेकिन अक्सर बहुत करीब (कभी-कभी खराब कचरा संग्रह के कारण धीमा हो सकता है)। खुद के लिए जाँच करें:

http://luajit.org/performance_x86.html

scimark2.luaफ़ाइल को वहां से डाउनलोड करें , और "सी" संस्करण (इसे गूगल करें) के साथ तुलना करें - अक्सर परिणाम बहुत करीब होते हैं।


2

लिंकर एक द्विआधारी के भीतर 32-बिट स्थानांतरण स्थान उत्पन्न करने का प्रयास कर रहा है जो किसी तरह इन सीमाओं को पार कर गया है। मुख्य प्रोग्राम की पता स्थान आवश्यकताओं को कम करने का प्रयास करें।

क्या आप कुछ / अधिकांश ऑब्जेक्ट कोड को एक या अधिक पुस्तकालयों में विभाजित कर सकते हैं (-fpic / -fPIC के साथ संकलित)? फिर एक गैर-स्थिर बाइनरी उत्पन्न करें जो इन कामों के खिलाफ लिंक करता है। लाइब्रेरी असतत मेमोरी ब्लॉक्स में रहेंगी और आपका रिलोकेशन ऑफ़सेट रिश्तेदार (32-बिट) के बजाय डायनेमिक / एब्सोल्यूट (64-बिट) होगा।


2

वे भाव मेरे लिए एक वैकल्पिक श्रृंखला की तरह दिखते हैं। मुझे नहीं पता कि बाकी कोड कैसा दिखता है, लेकिन ऐसा नहीं लगता है कि यह उत्पन्न करने वाले अभिव्यक्ति को प्राप्त करने के लिए कठिन होगा। शायद यह निष्पादन के समय भी इसके लायक होगा, खासकर यदि आपके पास 2 KB अनियंत्रित कोड का 2.8 जीबी है।


1

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.