Errore di compilazione GCC con> 2 GB di codice


108

Ho un numero enorme di funzioni per un totale di circa 2,8 GB di codice oggetto (sfortunatamente non c'è niente da fare, calcolo scientifico ...)

Quando provo a collegarli, ottengo relocation truncated to fit: R_X86_64_32Serrori (previsti) , che speravo di aggirare specificando il flag del compilatore -mcmodel=medium. Tutte le librerie collegate in aggiunta alle quali ho il controllo vengono compilate con il -fpicflag.

Tuttavia, l'errore persiste e presumo che alcune librerie a cui mi collego non siano compilate con PIC.

Ecco l'errore:

/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

E le librerie di sistema a cui mi collego contro:

-lgfortran -lm -lrt -lpthread

Qualche indizio su dove cercare il problema?

EDIT: Prima di tutto, grazie per la discussione ... Per chiarire un po ', ho centinaia di funzioni (ciascuna di circa 1 MB di dimensione in file oggetto separati) come questa:

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;
}

L'oggetto sè relativamente piccolo e mantiene le costanti necessarie x14, x15, ..., ds0, ..., ecc. Mentre tirestituisce solo un double da una libreria esterna. Come puoi vedere, csc[]è una mappa di valori precalcolata che viene anche valutata in file oggetto separati (di nuovo centinaia con circa ~ 1 MB di dimensione ciascuno) della seguente forma:

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));
    }

    // ...
}

Questo è tutto. Il passaggio finale quindi consiste solo nel chiamare tutti quelli func[i]e sommare il risultato.

Riguardo al fatto che questo è un caso piuttosto speciale e insolito: Sì, lo è. Questo è ciò che le persone devono affrontare quando cercano di eseguire calcoli ad alta precisione per la fisica delle particelle.

EDIT2: dovrei anche aggiungere che x12, x13, ecc. Non sono realmente costanti. Sono impostati su valori specifici, tutte quelle funzioni vengono eseguite e il risultato restituito, quindi viene scelto un nuovo set di x12, x13, ecc. Per produrre il valore successivo. E questo deve essere fatto da 10 ^ 5 a 10 ^ 6 volte ...

EDIT3: Grazie per i suggerimenti e la discussione fino ad ora ... cercherò di tirare su i loop sulla generazione del codice in qualche modo, non sono sicuro di come farlo esattamente, ad essere onesti, ma questa è la scommessa migliore.

A proposito, non ho cercato di nascondermi dietro "questo è calcolo scientifico - nessun modo per ottimizzare". È solo che la base di questo codice è qualcosa che esce da una "scatola nera" a cui non ho accesso reale e, inoltre, il tutto ha funzionato alla grande con esempi semplici e mi sento principalmente sopraffatto da ciò che accade in un applicazione mondiale ...

EDIT4: Quindi, sono riuscito a ridurre la dimensione del codice delle cscdefinizioni di circa un quarto semplificando le espressioni in un sistema di computer algebra ( Mathematica ). Ora vedo anche un modo per ridurlo di un altro ordine di grandezza o giù di lì applicando alcuni altri trucchi prima di generare il codice (che porterebbe questa parte a circa 100 MB) e spero che questa idea funzioni.

Ora relativo alle tue risposte: sto cercando di ripristinare nuovamente i loop in funcs, dove un CAS non aiuta molto, ma ho già alcune idee. Ad esempio, ordinando le espressioni in base a variabili come x12, x13,..., analizza le cscs con Python e genera tabelle che le mettono in relazione tra loro. Quindi posso almeno generare queste parti come loop. Poiché questa sembra essere la soluzione migliore finora, la contrassegno come la migliore risposta.

Tuttavia, vorrei dare credito anche a VJo. GCC 4.6 funziona davvero molto meglio, produce codice più piccolo ed è più veloce. L'uso del modello grande funziona con il codice così com'è. Quindi tecnicamente questa è la risposta corretta, ma cambiare l'intero concetto è un approccio molto migliore.

Grazie a tutti per i vostri suggerimenti e aiuto. Se qualcuno è interessato, pubblicherò il risultato finale non appena sarò pronto.

OSSERVAZIONI: solo alcune osservazioni per alcune altre risposte: il codice che sto cercando di eseguire non ha origine da un'espansione di semplici funzioni / algoritmi e da stupidi e inutili srotoli. Quello che realmente accade è che le cose con cui iniziamo sono oggetti matematici piuttosto complicati e portarli in una forma numericamente computabile genera queste espressioni. Il problema sta in realtà nella teoria fisica sottostante. La complessità delle espressioni intermedie scala fattorialmente, il che è ben noto, ma quando si combina tutto questo a qualcosa di misurabile fisicamente - un osservabile - si riduce solo a una manciata di funzioni molto piccole che costituiscono la base delle espressioni. (C'è sicuramente qualcosa di "sbagliato" in questo senso con il generale e solo disponibileansatz che si chiama "teoria delle perturbazioni") Cerchiamo di portare questa ansatz ad un altro livello, che non è più fattibile analiticamente e dove non si conosce la base delle funzioni necessarie. Quindi proviamo a forzare in questo modo. Non il modo migliore, ma si spera che aiuti con la nostra comprensione della fisica a portata di mano alla fine ...

ULTIMA MODIFICA: Grazie a tutti i tuoi suggerimenti, sono riuscito a ridurre notevolmente la dimensione del codice, utilizzando Mathematica e una modifica del generatore di codice per funcs un po 'sulla falsariga della risposta in alto :)

Ho semplificato le cscfunzioni con Mathematica, portandole a 92 MB. Questa è la parte irriducibile. I primi tentativi sono durati un'eternità, ma dopo alcune ottimizzazioni questo ora viene eseguito in circa 10 minuti su una singola CPU.

L'effetto sui messaggi di posta funcelettronica è stato drammatico: l'intera dimensione del codice è ridotta a circa 9 MB, quindi il codice ora ammonta a un totale di 100 MB. Ora ha senso attivare le ottimizzazioni e l'esecuzione è abbastanza veloce.

Ancora grazie a tutti per i vostri suggerimenti, ho imparato molto.


17
Se hai così tanti dati, dovresti spostarli fuori dai file sorgente e invece mmapda un binario esterno in fase di esecuzione.
R .. GitHub SMETTA DI AIUTARE IL GHIACCIO

3
Potresti fornire un esempio di una (o due) di queste funzioni? Questo sembra davvero strano. Puoi anche caricare queste funzioni in modo dinamico con la funzione dl *.
Patrick Schlüter

7
@bbtrb: Il mio primo istinto è simile a quello di R .., sembra un problema di progettazione. Certo, non so cosa sia comune nei circoli di informatica scientifica, ma non ho mai sentito di qualcuno che cerchi di collegare un file oggetto da 2,8 GB, o qualcosa di lontanamente vicino ad esso, e non sono sicuro che GCC lo supporterebbe davvero. Francamente, mi aspetto che qualsiasi blob di codice di quelle dimensioni sia spaghetti puri.
Nicholas Knight

46
non è assolutamente possibile che la soluzione ottimale per il problema coinvolga 2 GB di file oggetto.
David Heffernan

35
non mettere i tuoi dati in codice
David Heffernan

Risposte:


53

Quindi, hai già un programma che produce questo testo:

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] -...

e

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 -...

giusto?

Se tutte le tue funzioni hanno un "formato" simile (moltiplica n numeri m volte e aggiungi i risultati - o qualcosa di simile) allora penso che tu possa farlo:

  • cambia il programma generatore per produrre offset invece di stringhe (cioè invece della stringa "s.ds0" produrrà offsetof(ProcessVars, ds0)
  • creare una serie di tali offset
  • scrivere un valutatore che accetti l'array sopra e gli indirizzi di base dei puntatori della struttura e produca un risultato

L'array + analizzatore rappresenterà la stessa logica di una delle tue funzioni, ma solo l'analizzatore sarà codice. L'array è "dati" e può essere generato in fase di esecuzione o salvato su disco e leggere i blocchi o con un file mappato in memoria.

Per il vostro esempio particolare in func1 immaginare come si potrebbe riscrivere la funzione tramite un valutatore se si ha accesso al l'indirizzo di base di se csced anche un vettore, come la rappresentazione delle costanti e gli offset è necessario aggiungere agli indirizzi di base per raggiungere x14, ds8ecsc[51370]

È necessario creare una nuova forma di "dati" che descriva come elaborare i dati effettivi che si passa al numero enorme di funzioni.


45

L' ABI x86-64 utilizzato da Linux definisce un "modello grande" specificamente per evitare tali limitazioni di dimensione, che include i tipi di rilocazione a 64 bit per GOT e PLT. (Vedere la tabella nella sezione 4.4.2 e le sequenze di istruzioni in 3.5.5 che mostrano come vengono utilizzate.)

Dato che le tue funzioni occupano 2,8 GB, sei sfortunato, perché gcc non supporta modelli di grandi dimensioni. Quello che puoi fare è riorganizzare il tuo codice in modo tale da consentirti di dividerlo in librerie condivise che collegheresti dinamicamente.

Se ciò non è possibile, come qualcuno ha suggerito, invece di inserire i tuoi dati in codice (compilarlo e collegarlo), poiché è enorme, puoi caricarlo in fase di esecuzione (come un normale file o puoi mmaparlo).

MODIFICARE

Sembra che il modello grande sia supportato da gcc 4.6 (vedere questa pagina ). Puoi provarlo, ma quanto sopra si applica comunque alla riorganizzazione del codice.


Quindi quello che stai dicendo è che quando raggrupperei i file oggetto in diverse piccole librerie condivise, supererei i limiti?
bbtrb

3
@bbtrb Giusto. Ma cercherò ancora un altro modo per implementare le tue funzioni. Scommetto che la tua compilation impiega un'eternità
BЈовић

18
WTF? Questo codice deve essere generato da qualche script; nessuno scrive a mano megabyte di codice! La stessa logica che genera il codice potrebbe essere utilizzata anche per eseguire il calcolo.
zvrba

6
Consiglio vivamente di provare gcc 4.6, è molto probabile che produca codice superiore per questo programma rispetto a gcc 4.1; potrebbe anche essere in grado di comprimere l'intera cosa in 2 GB senza che tu debba fare nulla di intelligente, eliminando il problema (prova le combinazioni di -Os, -fwhole-program e -flto - con questo volume di codice, l'ottimizzazione per le dimensioni è ottimizzazione per la velocità). Tuttavia, se ciò non aiuta abbastanza, dovresti anche essere consapevole che affinché il modello grande funzioni, dovrai ricostruire almeno una parte della libreria C nel modello grande (crt * .o, libc_nonshared.a e libpthread_nonshared.a).
zwol

1
Anche il collegamento statico @bdonlan è una possibilità.
zvrba

37

Con un programma di questo tipo, è molto probabile che i mancati riscontri nella cache per il codice superino i costi del ciclo in fase di esecuzione. Ti consiglio di tornare al tuo generatore di codice e di fargli generare una rappresentazione compatta per ciò che vuole che venga valutato (cioè, una che probabilmente si adatterà alla D-cache), quindi eseguirlo con un interprete nel tuo programma. Potresti anche vedere se riesci a escludere i kernel più piccoli che hanno ancora un numero significativo di operazioni, quindi usarli come "istruzioni" nel codice interpretato.


21

L'errore si verifica perché hai troppo CODICE, non dati! Ciò è indicato, ad esempio, da __libc_csu_fini(che è una funzione) a cui si fa riferimento _starte il trasferimento viene troncato per adattarsi. Ciò significa che_start (il vero punto di ingresso del programma) sta tentando di chiamare quella funzione tramite un offset SIGNED a 32 bit, che ha solo un intervallo di 2 GB. Poiché la quantità totale del codice oggetto è ~ 2,8 GB, i fatti vengono verificati.

Se potessi riprogettare le tue strutture dati, gran parte del tuo codice potrebbe essere "compresso" riscrivendo le enormi espressioni come semplici loop.

Inoltre, è possibile eseguire il calcolo csc[]in un programma diverso, memorizzare i risultati in un file e caricarli quando necessario.


Potresti fornire un esempio di come riscriveresti le funzioni con semplici cicli? Non ti seguo esattamente. csc[]deve essere calcolato molto spesso e vorrei evitare l'I / O del disco.
bbtrb

4
@bbtr: Ad esempio, per func1sopra, qualcosa come: for (int i = 0; i < N; ++i) expr += constants[i].*s.x14*s.x15*csc[49300 + i];.
HighCommander4

@ HighCommander4: assolutamente, sono d'accordo. È appena sopra la mia testa come generare qualcosa di simile automaticamente. Forse con un array separato che memorizza gli indici ...
bbtrb

2
@bbtrb: Dal momento che non esiste un modo strano che qualcuno abbia scritto abbastanza sorgente per produrre a mano 2,8 GB di codice oggetto, specialmente con nomi di simboli così poco mnemonici, deve essere stato utilizzato un generatore di codice . Lavora con quello.
Donal Fellows

15

Penso che tutti siano d'accordo che dovrebbe esserci un modo diverso di fare quello che vuoi fare. Compilare centinaia di megabyte (gigabyte?) Di codice, collegarlo a un eseguibile di dimensioni multi-gigabyte ed eseguirlo sembra molto inefficiente.

Se capisco correttamente il tuo problema, usi una sorta di generatore di codice, G, per generare un mucchio di funzioni func1...Nche prendono un mucchio di mappe csc1...Mcome input. Quello che vuoi fare è calcolare csc1...Med eseguire un ciclo di 1.000.000 di volte per diversi input e ogni volta trovare s = func1 + func2 + ... + funcN. Tuttavia, non hai specificato come fucn1...Nsono correlati csc1...M.

Se tutto ciò è vero, sembra che dovresti essere in grado di capovolgere il problema in un modo diverso che può potenzialmente essere molto più gestibile e forse anche più veloce (cioè lasciare che la cache della tua macchina funzioni effettivamente).

Oltre al problema pratico delle dimensioni dei file oggetto, il programma corrente non sarà efficiente poiché non localizza l'accesso ai dati (troppe mappe enormi) e non ha l'esecuzione di codice localizzato (troppe funzioni molto lunghe).

Che ne dici di suddividere il tuo programma in 3 fasi: la fase 1 crea csc1...Me memorizza. Fase 2 crearne uno funcalla volta, eseguirlo 1.000.000 di volte con ogni input e memorizzare i risultati. La fase 3 trova la somma dei risultati dei risultati memorizzati func1...Nper ogni esecuzione di 1.000.000 di volte. La parte buona di questa soluzione è che può essere facilmente messa in parallelo su più macchine indipendenti.

Modifica: @bbtrb, potresti rendere disponibili uno func e un csc da qualche parte? Sembrano essere molto regolari e comprimibili. Ad esempio, func1 sembra essere solo una somma di espressioni ciascuna composta da 1 coefficiente, 2 indici per le variabili in se 1 indice in csc. Quindi può essere ridotto a un bel loop. Se rendi disponibili esempi completi, sono sicuro che si possono trovare modi per comprimerli in loop anziché in espressioni lunghe.


Sì, hai capito bene :) Ci sono diversi problemi con il tuo suggerimento: 1. i peggiori funcdipendono da quasi tutti csci se quei numeri devono essere calcolati anche 10 ^ 6 volte. 2. L'input sarà ottenuto da un integratore Monte Carlo adattivo, il che significa che l'integratore deve conoscere il risultato completo in ogni punto per essere in grado di ridurre l'errore risultante raffinando la mesh in prossimità del punto, se necessario. 3. Le grandi espressioni per cscpersistere ...
bbtrb

1
Quindi significa che non puoi calcolare ciascuno cscin ogni iterazione indipendentemente dagli altri? Se fossero indipendenti, potresti comunque eseguire ciascuno 10 ^ 6 volte e memorizzare i risultati. Tuttavia, se ci sono dipendenze tra di loro, forse è necessario scoprire quale è correlata a quale, qualcosa come un grafico delle dipendenze, e quindi provare a vedere se è possibile suddividerlo in più sottografi indipendenti. Tutto sommato penso che la chiave sia spezzare il problema in molteplici, indipendenti, sotto-problemi.
AlefSin

5

Se leggo correttamente i tuoi errori, ciò che ti fa trascinare il limite è la sezione dati inizializzata (se fosse il codice, avresti molti più errori IMHO). Hai grandi matrici di dati globali? In tal caso, ristrutturerei il programma in modo che vengano allocati dinamicamente. Se i dati vengono inizializzati, li leggo da un file di configurazione.

BTW vedendo questo:

(.text + 0x20): riferimento indefinito a "main"

Penso che tu abbia un altro problema.


1
Sì hai ragione, stupido errore, ma non risolve gli altri errori.
bbtrb

3

Mi sembra che il codice stia facendo l'integrazione numerica usando una sorta di metodo di profondità adattivo. Sfortunatamente, il generatore di codice (o meglio l'autore del generatore di codice) è così stupido da generare una funzione per patch piuttosto che una per tipo di patch. In quanto tale, ha prodotto troppo codice per essere compilato, e anche se potesse essere compilato la sua esecuzione sarebbe dolorosa perché nulla è mai condiviso da nessuna parte. (Potete immaginare il dolore derivante dal dover caricare ogni pagina del codice oggetto dal disco perché nulla viene mai condiviso e quindi è sempre un candidato per il sistema operativo da eliminare. Per non parlare delle cache di istruzioni, che saranno inutili.)

La soluzione è smettere di srotolare tutto; per questo tipo di codice, si desidera massimizzare la condivisione poiché il sovraccarico di istruzioni aggiuntive per accedere ai dati in schemi più complessi verrà comunque assorbito dal costo di gestione del (presumibilmente) grande insieme di dati sottostante. È anche possibile che il generatore di codice lo faccia anche per impostazione predefinita e che lo scienziato abbia visto alcune opzioni per lo srotolamento (con la nota che queste a volte migliorano la velocità) e le abbia attivate tutte in una volta e ora insiste affinché questo pasticcio risultante sia accettato dal computer, piuttosto che accettare le reali restrizioni della macchina e utilizzare la versione numericamente corretta generata di default. Ma se il generatore di codice non lo fa, procuratene uno che lo farà (o hackererà il codice esistente).

In conclusione : la compilazione e il collegamento di 2,8 GB di codice non funziona e non dovrebbe essere forzato a funzionare. Trova un altro modo.


3

Un paio di suggerimenti: - Ottimizza per dimensioni (-Os). Effettua le chiamate di funzione inline, normali chiamate di funzione. Abilita pool di stringhe.

Prova a suddividere le cose in diverse DLL (oggetti condivisi, .so per Linux, .dylib per Mac OS X). Assicurati che possano essere scaricati. Quindi implementare qualcosa per caricare le cose su richiesta e liberarle quando non sono necessarie.

In caso contrario, dividi il tuo codice in diversi eseguibili e usa qualcosa per comunicare tra loro (pipe, socket, persino scrittura / lettura su file). Goffo, ma quali opzioni hai?

Totalmente alternativa: - Usa un linguaggio dinamico con JIT . Proprio sopra la mia testa - usa LuaJIT - e riscrivi (rigeneri?) Molte di queste espressioni in Lua , o altri linguaggi e runtime simili che consentono la raccolta dei rifiuti del codice.

LuaJIT è abbastanza efficiente, a volte battendo C / C ++ per certe cose, ma spesso molto vicino (a volte può essere lento a causa della scarsa raccolta dei rifiuti ancora lì). Controlla tu stesso:

http://luajit.org/performance_x86.html

Scarica il scimark2.luafile da lì e confrontalo con la versione "C" (google it) - spesso i risultati sono molto vicini.


2

Il linker sta tentando di generare offset di rilocazione a 32 bit all'interno di un file binario che in qualche modo ha superato queste limitazioni. Prova a ridurre i requisiti di spazio degli indirizzi del programma principale.

Puoi dividere parte / la maggior parte del codice oggetto in una o più librerie (compilate anche con -fpic / -fPIC)? Quindi genera un binario non statico che si collega a queste librerie. Le librerie vivranno in blocchi di memoria discreti e gli offset di riposizionamento saranno dinamici / assoluti (64 bit) anziché relativi (32 bit).


2

Quelle espressioni mi sembrano molto simili a una serie alternata. Non so come sia il resto del codice, ma non sembra che sarebbe così difficile derivare l'espressione generatrice. Probabilmente ne varrebbe la pena anche al momento dell'esecuzione, soprattutto se hai 2,8 GB di codice srotolato da 2 KB.


1

Questo sembra il risultato della generazione di codice andata male, forse per algebra simbolica e / o srotolamento manuale. È noto che le manipolazioni simboliche crescono in modo esponenziale nella profondità dell'albero delle espressioni o del grafo computazionale. È probabile che qui sia possibile utilizzare la differenziazione automatica, il che ridurrebbe la dimensione del codice e velocizzerebbe notevolmente l'esecuzione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.