我有大量的函数,总计大约 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 MB),如下所示:
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
仅从外部库返回一个 double。如您所见,csc[]
它是一个预先计算的值映射,它也在以下形式的单独对象文件中进行评估(同样数百个,每个大约 1 MB 大小):
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]
并总结结果。
关于这是一个相当特殊和不寻常的情况:是的。这是人们在尝试对粒子物理进行高精度计算时必须应对的问题。
编辑2:
我还应该补充一点,x12、x13 等并不是真正的常数。它们被设置为特定值,运行所有这些函数并返回结果,然后选择一组新的 x12、x13 等来生成下一个值。这必须做 10 5到 10 6次...
编辑3:
感谢您到目前为止的建议和讨论......我会尝试以某种方式在代码生成时滚动循环,说实话,不确定如何做到这一点,但这是最好的选择。
顺便说一句,我并没有试图隐藏“这是科学计算——无法优化”。
只是这段代码的基础是来自一个“黑匣子”的东西,我无法真正访问,而且,整个事情在简单的例子中效果很好,我主要对现实中发生的事情感到不知所措世界应用...
编辑4:
csc
因此,通过简化计算机代数系统 ( Mathematica )中的表达式,我设法将定义的代码大小减少了大约四分之一。我现在还看到了一些方法,通过在生成代码之前应用一些其他技巧(这将使这部分减少到大约 100 MB),将它减少另一个数量级左右,我希望这个想法有效。
现在与您的答案有关:
我试图在 s 中再次将循环回滚func
,CAS 不会有太大帮助,但我已经有了一些想法。例如,按变量对表达式进行排序,用 Pythonx12, x13,...
解析csc
s 并生成将它们相互关联的表。然后我至少可以将这些部分生成为循环。由于这似乎是迄今为止最好的解决方案,我将其标记为最佳答案。
但是,我也想感谢 VJo。GCC 4.6 确实工作得更好,生成的代码更小并且速度更快。使用大型模型按原样处理代码。所以从技术上讲,这是正确的答案,但改变整个概念是一种更好的方法。
谢谢大家的建议和帮助。如果有人感兴趣,我会在准备好后立即发布最终结果。
评论:
只是对其他一些答案的一些评论:我试图运行的代码并不是源于简单函数/算法的扩展和愚蠢的不必要的展开。实际发生的是,我们开始的东西是非常复杂的数学对象,将它们转化为可数值计算的形式会生成这些表达式。问题实际上在于潜在的物理理论。中间表达式的复杂性是众所周知的,但是当将所有这些东西组合成物理上可测量的东西——一个可观察的——时,它只是归结为只有少数非常小的函数构成了表达式的基础。(在这方面,通用且唯一可用的ansatz肯定存在“错误”这被称为“微扰理论”)我们试图将这个 ansatz 带到另一个层次,这在分析上不再可行,并且所需函数的基础是未知的。所以我们尝试像这样暴力破解它。不是最好的方法,但希望能帮助我们最终理解手头的物理学……
最后编辑:
感谢您的所有建议,我已经设法大大减少了代码大小,使用 Mathematica 并修改了func
s 的代码生成器,有点类似于最佳答案:)
我已经csc
使用 Mathematica 简化了函数,将其缩小到 92 MB。这是不可约的部分。第一次尝试花了很长时间,但经过一些优化后,现在在单个 CPU 上运行大约 10 分钟。
对func
s 的影响是巨大的:它们的整个代码大小降低到大约 9 MB,因此现在代码总计在 100 MB 范围内。现在打开优化是有意义的,并且执行速度非常快。
再次感谢大家的建议,我学到了很多。