Ich habe eine große Anzahl von Funktionen mit insgesamt rund 2,8 GB Objektcode (leider führt kein Weg daran vorbei, wissenschaftliches Rechnen ...)
Wenn ich versuche, sie zu verknüpfen, erhalte ich (erwartete) relocation truncated to fit: R_X86_64_32S
Fehler, die ich durch Angabe des Compiler-Flags umgehen wollte -mcmodel=medium
. Alle zusätzlich verknüpften Bibliotheken, auf die ich Einfluss habe, werden mit dem -fpic
Flag kompiliert .
Trotzdem bleibt der Fehler bestehen und ich gehe davon aus, dass einige Bibliotheken, mit denen ich verknüpfe, nicht mit PIC kompiliert wurden.
Hier ist der Fehler:
/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
Und Systembibliotheken, gegen die ich verlinke:
-lgfortran -lm -lrt -lpthread
Gibt es Hinweise, wo Sie nach dem Problem suchen können?
EDIT: Zunächst einmal vielen Dank für die Diskussion ... Zur Verdeutlichung habe ich Hunderte von Funktionen (jede ca. 1 MB groß in separaten Objektdateien) wie folgt:
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;
}
Das Objekt s
ist relativ klein und behält die erforderlichen Konstanten x14, x15, ..., ds0, ... usw. bei, während ti
nur ein Double aus einer externen Bibliothek zurückgegeben wird. Wie Sie sehen können, csc[]
handelt es sich um eine vorberechnete Wertekarte, die auch in separaten Objektdateien (wiederum Hunderte mit jeweils ca. 1 MB Größe) der folgenden Form ausgewertet wird:
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));
}
// ...
}
Das ist alles. Der letzte Schritt besteht dann nur darin, alle diese aufzurufen func[i]
und das Ergebnis zusammenzufassen.
In Bezug auf die Tatsache, dass dies ein ganz besonderer und ungewöhnlicher Fall ist: Ja, das ist es. Damit müssen sich die Menschen auseinandersetzen, wenn sie versuchen, hochpräzise Berechnungen für die Teilchenphysik durchzuführen.
EDIT2: Ich sollte auch hinzufügen, dass x12, x13 usw. keine wirklichen Konstanten sind. Sie werden auf bestimmte Werte gesetzt, alle diese Funktionen werden ausgeführt und das Ergebnis zurückgegeben. Anschließend wird ein neuer Satz von x12, x13 usw. ausgewählt, um den nächsten Wert zu erzeugen. Und das muss 10 ^ 5 bis 10 ^ 6 mal gemacht werden ...
EDIT3: Vielen Dank für die Vorschläge und die bisherige Diskussion ... Ich werde versuchen, die Schleifen bei der Codegenerierung irgendwie aufzurollen, nicht sicher, wie genau das geht, um ehrlich zu sein, aber das ist die beste Wahl.
Übrigens habe ich nicht versucht, mich dahinter zu verstecken "das ist wissenschaftliches Rechnen - keine Möglichkeit zur Optimierung". Es ist nur so, dass die Basis für diesen Code etwas ist, das aus einer "Black Box" stammt, auf die ich keinen wirklichen Zugriff habe, und außerdem hat das Ganze mit einfachen Beispielen großartig funktioniert, und ich fühle mich hauptsächlich überwältigt von dem, was in einem realen passiert Weltanwendung ...
EDIT4: Ich habe es also geschafft, die Codegröße der csc
Definitionen durch Vereinfachung der Ausdrücke in einem Computeralgebrasystem ( Mathematica ) um etwa ein Viertel zu reduzieren . Ich sehe jetzt auch eine Möglichkeit, es um eine weitere Größenordnung oder so zu reduzieren, indem ich einige andere Tricks anwende, bevor ich den Code generiere (was diesen Teil auf ungefähr 100 MB reduzieren würde), und ich hoffe, dass diese Idee funktioniert.
Nun zu Ihren Antworten: Ich versuche, die Schleifen im func
s wieder aufzurollen , wo ein CAS nicht viel hilft, aber ich habe bereits einige Ideen. Wenn Sie beispielsweise die Ausdrücke nach Variablen wie sortieren x12, x13,...
, analysieren Sie die csc
s mit Python und generieren Sie Tabellen, die sie miteinander in Beziehung setzen. Dann kann ich diese Teile zumindest als Schleifen erzeugen. Da dies bisher die beste Lösung zu sein scheint, bezeichne ich dies als die beste Antwort.
Ich möchte jedoch auch VJo Ehre machen. GCC 4.6 funktioniert in der Tat viel besser, produziert kleineren Code und ist schneller. Die Verwendung des großen Modells funktioniert mit dem Code wie er ist. Technisch gesehen ist dies die richtige Antwort, aber eine Änderung des gesamten Konzepts ist ein viel besserer Ansatz.
Vielen Dank für Ihre Vorschläge und Hilfe. Wenn jemand interessiert ist, werde ich das endgültige Ergebnis veröffentlichen, sobald ich bereit bin.
BEMERKUNGEN: Nur einige Anmerkungen zu einigen anderen Antworten: Der Code, den ich ausführen möchte, stammt nicht aus einer Erweiterung einfacher Funktionen / Algorithmen und dummem unnötigem Abrollen. Was tatsächlich passiert, ist, dass das, womit wir beginnen, ziemlich komplizierte mathematische Objekte sind und diese Ausdrücke in eine numerisch berechenbare Form bringen. Das Problem liegt tatsächlich in der zugrunde liegenden physikalischen Theorie. Die Komplexität von Zwischenausdrücken skaliert faktoriell, was bekannt ist, aber wenn all diese Dinge zu etwas physikalisch Messbarem kombiniert werden - einem Beobachtbaren -, läuft es nur auf eine Handvoll sehr kleiner Funktionen hinaus, die die Grundlage der Ausdrücke bilden. (Es gibt definitiv etwas "Falsches" in dieser Hinsicht mit dem Allgemeinen und nur verfügbarAnsatz, der als "Störungstheorie" bezeichnet wird) Wir versuchen, diesen Ansatz auf eine andere Ebene zu bringen, die analytisch nicht mehr realisierbar ist und bei der die Grundlage der benötigten Funktionen nicht bekannt ist. Also versuchen wir es so brutal zu erzwingen. Nicht der beste Weg, aber hoffentlich einer, der am Ende zu unserem Verständnis der vorliegenden Physik beiträgt ...
LAST EDIT:
Dank all Ihrer Vorschläge habe ich es geschafft, die Codegröße erheblich zu reduzieren, indem ich Mathematica und eine Modifikation des Codegenerators für das func
s etwas in Anlehnung an die Top-Antwort verwendet habe :)
Ich habe die csc
Funktionen mit Mathematica vereinfacht und auf 92 MB reduziert. Dies ist der irreduzible Teil. Die ersten Versuche haben ewig gedauert, aber nach einigen Optimierungen dauert dies nun in etwa 10 Minuten auf einer einzelnen CPU.
Die Auswirkung auf das func
s war dramatisch: Die gesamte Codegröße für sie beträgt ungefähr 9 MB, sodass der Code jetzt im Bereich von 100 MB liegt. Jetzt ist es sinnvoll, Optimierungen zu aktivieren und die Ausführung ist recht schnell.
Nochmals vielen Dank für Ihre Vorschläge, ich habe viel gelernt.
mmap
zur Laufzeit aus den Quelldateien und stattdessen selbst aus einer externen Binärdatei verschieben.