为什么std::array<std::string, 65536> a = {};在Core i7 9700K处理器上使用-O3进行gcc编译需要花费超过17分钟的时间?
我偶然发现了gcc的问题,我在头文件std::array中用std::strings 空初始化了a ,而不是在源文件中的专用构造函数中进行了初始化。该文件包含在多个位置,这导致了几乎无限的优化循环。随着-O0它迅速完成,但是-O1我在核心i7-9700K处理器上等待了一个多小时,而gcc仍在运行。
最后,我将问题缩小到std::array<std::string, N>其中N某个大数字的空初始化。对于其他类型的其他非平凡构造函数,在编译时间随元素数量线性增加的情况下,也可能会遇到类似的问题。像下面的例子。
#include <array>
struct A {
A() : i(0) {}
int i;
};
int main() {
std::array<A, 65536> a = {};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为了自己解决这个问题,我将上面的代码编译为汇编代码。与-O0组装的样子的展开for呼叫的循环给构造与线作为阵列尺寸的约4倍的数量。启用优化时,似乎完全消除了初始化。
#include <array>
#include <string>
int main() {
std::array<std::string, 65536> a = {};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,当用替换数组的内容时std::string,std::string即使启用了优化,编译器似乎也无法删除的初始化。
我想这就是为什么我的初始构建陷入了无休止的优化循环的原因的一部分,但是它不能完全解释它,也不能解释为什么clang似乎能更好地处理这一问题。有没有人可以进一步阐明这个问题?
我尝试了几个gcc版本,从gcc-6到gcc-8。即使使用gcc-4.9,也需要花费一些时间,但花费的时间并不多,大约需要4.5分钟。在-stdlib = libstdc ++中使用clang会产生0m0,120s的编译时间。