没有 -On 就无法构建简单的 Eigen3 张量程序

Trivial Eigen3 Tensor program does not build without -On

我正在尝试使用不受 eigen3 支持的 Tensor 模块编写软件。我已经编写了一段简单的代码,它将使用 VectorXd 的简单应用程序构建(只需将其打印到标准输出),并且还将使用 Tensor 的类似应用程序代替 VectorXd 来构建,但是当我不这样做时将不会构建抛出一个优化标志(-On)。请注意,我的构建来自使用 conda-forge 编译器的 conda 环境,因此下面的 g++ 是从 conda forge for ubuntu 获得的 g++。如果认为这是问题所在,它会在下面的错误消息中说明它的名字。

我觉得这与我正在尝试编写的程序无关,但以防万一我包含了一个似乎会产生错误的 mwe.cpp。代码如下:

#include <eigen3/Eigen/Dense>
#include <eigen3/unsupported/Eigen/CXX11/Tensor>
#include <iostream>

using namespace Eigen;
using namespace std;

int main(int argc, char const *argv[])
{
    VectorXd v(6);
    v << 1, 2, 3, 4, 5, 6;
    cout << v.cwiseSqrt() << "\n";
    Tensor<double, 1> t(6);
    for (auto i=0; i<v.size(); i++){
        t(i) = v(i);
    }
    cout << "\n";
    for (auto i=0; i<t.size(); i++){
        cout << t(i) << " ";
    }
    cout << "\n";
    return 0;
}

如果上面的代码编译时没有任何优化,比如:

g++ -I ~/miniconda3/envs/myenv/include/ mwe.cpp -o mwe

我收到以下编译器错误:

/home/myname/miniconda3/envs/myenv/bin/../lib/gcc/x86_64-conda_cos6-linux-gnu/7.3.0/../../../../x86_64-conda_cos6-linux-gnu/bin/ld: /tmp/cc2q8gj4.o: in function `Eigen::internal::(anonymous namespace)::get_random_seed()':
mwe.cpp:(.text+0x15): undefined reference to `clock_gettime'
collect2: error: ld returned 1 exit status

如果我要求 'n' 优化级别,如下所示:

g++ -I ~/miniconda3/envs/loos/include/ -On mwe.cpp -o mwe

程序毫无怨言地构建,我得到了预期的输出:

$ ./mwe 
      1
1.41421
1.73205
      2
2.23607
2.44949

1 2 3 4 5 6 

我不知道为什么这个小程序,或者我正在尝试编写的真实程序,会尝试为任何东西获取随机种子。任何意见,将不胜感激。我想在没有优化的情况下构建的原因是调试更容易。我实际上认为所有这一切都是由调试标志引起的,但我意识到我的构建工具的调试设置没有要求优化并将其缩小到明显的原因。如果我抛出 -g -O1 我看不到错误。

显然,如果要注释掉与 Tensor 模块有关的所有代码,那就是 'return' 上面和 cwiseSqrt() 行下面的 main 中的所有内容,以及 include 语句,代码构建并产生预期的输出。

从技术上讲,这是一个 linker 错误(g++ 调用编译器以及 linker,具体取决于命令行参数)。如果从某个地方调用外部定义的函数,即使从未到达代码,您也会得到 linker-errors。

在启用优化的情况下进行编译时,g++ 将优化掉未调用的函数(在全局命名空间之外),因此不会出现 linker 错误。您可能想尝试 -Og 而不是 -O1 以获得更好的调试体验。

以下代码应产生类似的行为:

int foo(); // externally defined

namespace { // anonymous namespace
// defined inside this module, but never called
int bar() {
    return foo();
}
}

int main() {
    // if you un-comment this line, the
    // optimized version will fail as well:
    // ::bar();
}

根据 man clock_gettime,如果您的 glibc 版本早于 2.17,您需要 link 和 -lrt —— 也许您的设置就是这种情况:

g++ -I ~/miniconda3/envs/myenv/include/ mwe.cpp -o mwe -lrt