Tengo una gran cantidad de funciones que suman alrededor de 2.8 GB de código objeto (desafortunadamente no hay forma de evitarlo, computación científica ...)
Cuando trato de vincularlos, obtengo relocation truncated to fit: R_X86_64_32S
errores (esperados) , que esperaba evitar especificando el indicador del compilador -mcmodel=medium
. Todas las bibliotecas que están vinculadas además de las que tengo control se compilan con la -fpic
bandera.
Aún así, el error persiste y supongo que algunas bibliotecas con las que me vinculo no están compiladas con PIC.
Aquí está el error:
/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
Y las bibliotecas del sistema con las que me vinculo:
-lgfortran -lm -lrt -lpthread
¿Alguna pista de dónde buscar el problema?
EDITAR: En primer lugar, gracias por la discusión ... Para aclarar un poco, tengo cientos de funciones (cada una de aproximadamente 1 MB de tamaño en archivos de objetos separados) como esta:
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;
}
El objeto s
es relativamente pequeño y mantiene las constantes necesarias x14, x15, ..., ds0, ..., etc., mientras que ti
solo devuelve un doble de una biblioteca externa. Como puede ver, csc[]
es un mapa precalculado de valores que también se evalúa en archivos de objetos separados (nuevamente cientos con aproximadamente ~ 1 MB de tamaño cada uno) de la siguiente 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));
}
// ...
}
Eso es todo. El paso final entonces consiste en llamar a todos esos func[i]
y resumir el resultado.
En cuanto al hecho de que este es un caso bastante especial e inusual: sí, lo es. Esto es lo que la gente tiene que afrontar cuando intenta hacer cálculos de alta precisión para la física de partículas.
EDIT2: También debería agregar que x12, x13, etc. no son realmente constantes. Se establecen en valores específicos, se ejecutan todas esas funciones y se devuelve el resultado, y luego se elige un nuevo conjunto de x12, x13, etc. para producir el siguiente valor. Y esto debe hacerse de 10 ^ 5 a 10 ^ 6 veces ...
EDIT3: Gracias por las sugerencias y la discusión hasta ahora ... Intentaré enrollar los bucles sobre la generación de código de alguna manera, no estoy seguro de cómo hacerlo exactamente, para ser honesto, pero esta es la mejor opción.
Por cierto, no traté de esconderme detrás de "esto es computación científica, no hay forma de optimizar". Es solo que la base de este código es algo que sale de una "caja negra" a la que no tengo acceso real y, además, todo funcionó muy bien con ejemplos simples, y principalmente me siento abrumado con lo que sucede en un aplicación mundial ...
EDIT4: Entonces, me las arreglé para reducir el tamaño del código de las csc
definiciones en aproximadamente un cuarto simplificando expresiones en un sistema de álgebra por computadora ( Mathematica ). Ahora veo también alguna forma de reducirlo en otro orden de magnitud aplicando algunos otros trucos antes de generar el código (lo que reduciría esta parte a unos 100 MB) y espero que esta idea funcione.
Ahora relacionado con sus respuestas: estoy tratando de volver a enrollar los bucles en el func
s, donde un CAS no ayudará mucho, pero ya tengo algunas ideas. Por ejemplo, ordenar las expresiones por variables como x12, x13,...
, analizar la csc
s con Python y generar tablas que las relacionen entre sí. Entonces puedo al menos generar estas partes como bucles. Como esta parece ser la mejor solución hasta ahora, la marco como la mejor respuesta.
Sin embargo, también me gustaría darle crédito a VJo. De hecho, GCC 4.6 funciona mucho mejor, produce un código más pequeño y es más rápido. El uso del modelo grande funciona en el código tal cual. Entonces, técnicamente, esta es la respuesta correcta, pero cambiar todo el concepto es un enfoque mucho mejor.
Gracias a todos por sus sugerencias y ayuda. Si alguien está interesado, voy a publicar el resultado final tan pronto como esté listo.
OBSERVACIONES: Solo algunos comentarios a algunas otras respuestas: El código que estoy tratando de ejecutar no se origina en una expansión de funciones / algoritmos simples y un desenrollado innecesario estúpido. Lo que realmente sucede es que las cosas con las que comenzamos son objetos matemáticos bastante complicados y llevarlos a una forma numéricamente computable genera estas expresiones. El problema radica en realidad en la teoría física subyacente. La complejidad de las expresiones intermedias escala factorialmente, lo cual es bien conocido, pero cuando se combinan todas estas cosas con algo físicamente medible, un observable, solo se reduce a un puñado de funciones muy pequeñas que forman la base de las expresiones. (Definitivamente hay algo "incorrecto" a este respecto con el general y solo disponibleansatz que se llama "teoría de la perturbación") Tratamos de llevar este ansatz a otro nivel, que ya no es factible analíticamente y donde se desconoce la base de las funciones necesarias. Así que tratamos de usar la fuerza bruta de esta manera. No es la mejor manera, pero es de esperar que al final ayude con nuestra comprensión de la física en cuestión ...
ÚLTIMA EDICIÓN:
Gracias a todas sus sugerencias, me las arreglé para reducir considerablemente el tamaño del código, usando Mathematica y una modificación del generador de código para la func
s algo similar a la respuesta principal :)
He simplificado las csc
funciones con Mathematica, reduciéndolas a 92 MB. Esta es la parte irreductible. Los primeros intentos tomaron una eternidad, pero después de algunas optimizaciones, esto ahora se ejecuta en aproximadamente 10 minutos en una sola CPU.
El efecto en los func
s fue dramático: el tamaño total del código para ellos se redujo a aproximadamente 9 MB, por lo que el código ahora totaliza en el rango de 100 MB. Ahora tiene sentido activar las optimizaciones y la ejecución es bastante rápida.
Nuevamente, gracias a todos por sus sugerencias, he aprendido mucho.
mmap
su lugar , sacarlos usted mismo de un binario externo en tiempo de ejecución.