J'ai un grand nombre de fonctions totalisant environ 2,8 Go de code objet (malheureusement, il n'y a pas moyen de contourner, calcul scientifique ...)
Lorsque j'essaye de les lier, j'obtiens des relocation truncated to fit: R_X86_64_32S
erreurs (attendues) , que j'espérais contourner en spécifiant l'indicateur du compilateur -mcmodel=medium
. Toutes les bibliothèques liées en plus que je contrôle sont compilées avec le -fpic
drapeau.
Pourtant, l'erreur persiste et je suppose que certaines bibliothèques vers lesquelles je lie ne sont pas compilées avec PIC.
Voici l'erreur:
/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
Et les bibliothèques système avec lesquelles je lie:
-lgfortran -lm -lrt -lpthread
Des indices où chercher le problème?
EDIT: Tout d'abord, merci pour la discussion ... Pour clarifier un peu, j'ai des centaines de fonctions (chacune d'environ 1 Mo de taille dans des fichiers objets séparés) comme ceci:
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'objet s
est relativement petit et conserve les constantes nécessaires x14, x15, ..., ds0, ..., etc. tout en renvoyant ti
simplement un double d'une bibliothèque externe. Comme vous pouvez le voir, csc[]
est une carte précalculée de valeurs qui est également évaluée dans des fichiers objets séparés (encore des centaines avec environ ~ 1 Mo de taille chacun) de la forme suivante:
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));
}
// ...
}
C'est à peu près ça. La dernière étape consiste alors simplement à appeler tous ceux-ci func[i]
et à résumer le résultat.
Concernant le fait qu'il s'agit d'un cas assez particulier et inhabituel: Oui, c'est le cas. C'est à cela que les gens doivent faire face lorsqu'ils essaient de faire des calculs de haute précision pour la physique des particules.
EDIT2: Je devrais également ajouter que x12, x13, etc. ne sont pas vraiment des constantes. Ils sont définis sur des valeurs spécifiques, toutes ces fonctions sont exécutées et le résultat est renvoyé, puis un nouvel ensemble de x12, x13, etc. est choisi pour produire la valeur suivante. Et cela doit être fait 10 ^ 5 à 10 ^ 6 fois ...
EDIT3: Merci pour les suggestions et la discussion jusqu'à présent ... J'essaierai de rouler les boucles lors de la génération de code d'une manière ou d'une autre, je ne sais pas comment faire exactement, pour être honnête, mais c'est le meilleur pari.
BTW, je n'ai pas essayé de me cacher derrière "c'est de l'informatique scientifique - aucun moyen d'optimiser". C'est juste que la base de ce code est quelque chose qui sort d'une «boîte noire» où je n'ai pas vraiment accès et, de plus, tout a très bien fonctionné avec des exemples simples, et je me sens principalement dépassé par ce qui se passe dans un vrai application mondiale ...
EDIT4: Donc, j'ai réussi à réduire la taille du code des csc
définitions d'environ un quart en simplifiant les expressions dans un système d'algèbre informatique ( Mathematica ). Je vois maintenant aussi un moyen de le réduire d'un autre ordre de grandeur ou plus en appliquant quelques autres astuces avant de générer le code (ce qui ramènerait cette partie à environ 100 Mo) et j'espère que cette idée fonctionne.
Maintenant lié à vos réponses: j'essaye de remonter les boucles dans le func
s, où un CAS n'aidera pas beaucoup, mais j'ai déjà quelques idées. Par exemple, trier les expressions par les variables telles que x12, x13,...
, analyser les csc
s avec Python et générer des tables qui les relient les unes aux autres. Ensuite, je peux au moins générer ces parties sous forme de boucles. Comme cela semble être la meilleure solution à ce jour, je la marque comme la meilleure réponse.
Cependant, j'aimerais également rendre hommage à VJo. GCC 4.6 fonctionne en effet beaucoup mieux, produit du code plus petit et est plus rapide. L'utilisation du grand modèle fonctionne au code tel quel. Donc, techniquement, c'est la bonne réponse, mais changer tout le concept est une bien meilleure approche.
Merci à tous pour vos suggestions et votre aide. Si quelqu'un est intéressé, je publierai le résultat final dès que je serai prêt.
REMARQUES: Juste quelques remarques à quelques autres réponses: Le code que j'essaie d'exécuter ne provient pas d'une expansion de fonctions / algorithmes simples et d'un déroulement inutile et stupide. Ce qui se passe en fait, c'est que les choses avec lesquelles nous commençons sont des objets mathématiques assez compliqués et les amener à une forme calculable numériquement génère ces expressions. Le problème réside en fait dans la théorie physique sous-jacente. La complexité des expressions intermédiaires évolue de manière factorielle, ce qui est bien connu, mais lorsque l'on combine tout cela en quelque chose de physiquement mesurable - un observable - cela se résume à seulement une poignée de très petites fonctions qui forment la base des expressions. (Il y a certainement quelque chose de "mal" à cet égard avec le général et uniquement disponibleansatz qui est appelé "théorie des perturbations") Nous essayons d'amener cet ansatz à un autre niveau, qui n'est plus réalisable analytiquement et où la base des fonctions nécessaires n'est pas connue. Nous essayons donc de le forcer brutalement comme ça. Ce n'est pas le meilleur moyen, mais j'espère que celui qui nous aidera à comprendre la physique à portée de main à la fin ...
DERNIÈRE MODIFICATION:
Grâce à toutes vos suggestions, j'ai réussi à réduire considérablement la taille du code, en utilisant Mathematica et une modification du générateur de code pour les func
s un peu dans le sens de la réponse du haut :)
J'ai simplifié les csc
fonctions avec Mathematica, en les ramenant à 92 Mo. C'est la partie irréductible. Les premières tentatives ont pris une éternité, mais après quelques optimisations, cela dure maintenant environ 10 minutes sur un seul processeur.
L'effet sur les func
s était dramatique: la taille totale du code pour eux est réduite à environ 9 Mo, de sorte que le code totalise maintenant dans la plage de 100 Mo. Il est maintenant logique d'activer les optimisations et l'exécution est assez rapide.
Encore une fois, merci à tous pour vos suggestions, j'ai beaucoup appris.
mmap
vous-même à partir d'un binaire externe au moment de l'exécution.