我有大量的功能,总计约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]
,并对结果求和。
关于这是一个非常特殊且不寻常的情况:是的。这是人们在尝试进行粒子物理学的高精度计算时必须应付的。
EDIT2:我还应该补充一点,x12,x13等不是真正的常数。将它们设置为特定值,运行所有这些函数并返回结果,然后选择一组新的x12,x13等来生成下一个值。这必须完成10 ^ 5至10 ^ 6次...
EDIT3:到目前为止,感谢您的建议和讨论...老实说,我将尝试以某种方式在代码生成时汇总循环,不确定如何做到这一点,但这是最好的选择。
顺便说一句,我没有试图掩盖“这是科学计算-没有优化的方法”。只是该代码的基础是从“黑匣子”中提取出来的,在这里我没有真正的访问权限,而且,通过简单的示例,整个过程效果很好,而我主要感到不满意实际发生的事情世界应用...
EDIT4:因此,csc
通过简化计算机代数系统(Mathematica)中的表达式,我设法将定义的代码大小减少了大约四分之一。我现在也看到了某种方法来将其减少另一个数量级,或者通过在生成代码之前应用一些其他技巧来减少它(这将使这一部分减少到大约100 MB),我希望这个想法行得通。
现在与您的答案有关:我正在尝试在func
s中重新循环,CAS并没有多大帮助,但是我已经有了一些想法。例如,使用变量如排序表达式,用Python x12, x13,...
解析csc
s并生成将它们相互关联的表。然后,我至少可以将这些部分生成为循环。由于这似乎是迄今为止最好的解决方案,因此我将其标记为最佳答案。
但是,我还要感谢VJo。GCC 4.6确实工作多好,生成较小的代码和更快。使用大型模型按原样运行代码。因此,从技术上讲,这是正确的答案,但是更改整个概念是一种更好的方法。
谢谢大家的建议和帮助。如果有人感兴趣,我将在准备好后立即发布最终结果。
备注:对其他答案的一些评论:我尝试运行的代码并非源自简单函数/算法的扩展以及愚蠢的不必要的展开。实际发生的是,我们开始的工作是相当复杂的数学对象,并将它们转换为可数字计算的形式会生成这些表达式。问题实际上出在潜在的物理理论上。众所周知,中间表达式的复杂度会按比例缩放,但是当将所有这些东西组合为可物理测量的东西(可观察到的东西)时,它只能归结为构成表达式基础的少数几个很小的函数。(在这方面,在一般情况下肯定存在“错误”,并且只能使用ansatz,被称为“扰动理论”)我们试图将这种ansatz提升到一个新的水平,这在分析上已经不再可行,并且所需功能的基础未知。因此,我们尝试像这样暴力破解它。并不是最好的方法,但希望最终可以帮助我们更好地理解手边的物理...
最后编辑:
由于您的所有建议,我设法使用Mathematica并针对func
s 修改了代码生成器,从而大大减少了代码大小:
我csc
使用Mathematica 简化了功能,将其减小到92 MB。这是不可还原的部分。第一次尝试花了很多时间,但是经过一些优化后,现在可以在单个CPU上运行大约10分钟。
对func
s 的影响是巨大的:它们的整个代码大小降低到大约9 MB,因此现在的代码总数为100 MB。现在,打开优化很有意义,并且执行速度非常快。
再次感谢大家的建议,我学到了很多东西。
mmap
在运行时将其从源文件中移出,而自己从外部二进制文件中移出。