【问题标题】:Trivial Eigen3 Tensor program does not build without -On没有 -On 就无法构建平凡的 Eigen3 张量程序
【发布时间】:2020-03-03 06:19:23
【问题描述】:

我正在尝试使用 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 模块有关的所有代码,即 main 中“return”上方和 cwiseSqrt() 行下方的所有内容,以及 include 语句,代码构建和产生预期的输出。

【问题讨论】:

    标签: c++ compiler-optimization tensor eigen3


    【解决方案1】:

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

    在启用优化的情况下编译时,g++ 将优化掉未调用的函数(在全局命名空间之外),因此不会出现链接器错误。您可能想尝试-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,您需要与-lrt 链接——也许您的设置就是这种情况:

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

    【讨论】:

    • 所以,澄清一下,当我不使用 Tensor 模块中的某些东西时,示例代码中不会出现这种情况,只是来自常规特征的东西,这意味着常规特征永远不会调用 clock_gettime 函数但是 Tensor 在某个地方(但不是对 MWE 或我的真实代码重要的地方)?
    • 你应该得到这个行为,只要你#include 来自张量模块的东西,不管你是否真的使用它。一旦你真正使用了张量模块中的东西,它本身使用clock_gettime,你的问题就不会消失,即使你进行了优化编译。
    猜你喜欢
    • 1970-01-01
    • 2019-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-28
    相关资源
    最近更新 更多