【问题标题】:Initializing a vector of structs takes large compile time初始化结构的矢量需要大编译时间
【发布时间】:2015-01-13 05:25:17
【问题描述】:

我正在用 C++11 编写一个程序,它分析国际象棋的位置并计算一些有趣的统计数据。我正在加载的数据被格式化成一个结构

struct board{
  board(long int hash1,long int hash2);
};

我将所有内容都存储在另一个结构中

struct data_struct{
  vector<board> allboards;
  void read_data(char* filename);
  //other member functions
};

以前我从文本文件中读取数据,但我正在使用文件 I/O 很昂贵的计算机集群,并且我必须使用不同的设置但相同的数据多次执行相同的程序。所以我认为硬编码数据并重载data_struct的默认构造函数会更有效。所以在一个单独的源文件中我有一个构造函数

data_struct::data_struct(){
  allboards.push_back(board(2315678,6235756));
  allboards.push_back(board(464135138,1563135));
  \\5000 more lines like this 
}

数字无关紧要,它们是董事会状态的散列表示。我的问题是编译这段代码需要很长时间。我认为问题在于我调用了板 5000 次的构造函数,因为如果我将散列硬编码为数组,编译时间不会超过几秒钟。但是,程序必须在执行时将这些数组转换为向量,这是不优雅的,并且浪费内存和时间。有没有一种优雅的方法来解决这个问题,例如使用初始化列表?

编辑:我正在使用启用了 -O3 和 -fexpensive-optimizations 的 Mingw-w64 进行编译。如果没有优化,它不会变得更快。

【问题讨论】:

  • 澄清一下;是编译程序还是运行程序的问题?如果运行缓慢,请尝试调用 reserve() 计算预期大小。
  • 问题是编译时间。它不是很大,但超过一分钟,它在开发/调试代码时大大减慢了我的速度。
  • 您能否显示创建data_struct 变量的代码?您是否在启用内联的情况下进行编译?编译器可能会尝试在编译时解析构造函数调用。
  • 40KB 的文件 I/O 很贵?!
  • @David Schwartz,我正在运行这个程序数千到数万次,所以它加起来了。此外,不断拖动文本文件很烦人,将其放入编译器可以使代码美观且可移植。另外,我正在努力成为一个更好的程序员,所以学习“正确”的方法会很好:)

标签: c++ c++11 vector constructor initialization


【解决方案1】:

如果数据不变,我建议使用structs 的staticconst 数组。

数组将在main 之前以最有效的方式初始化。编译器可以创建一个数据表,您的代码可以直接访问该数据表。

如果你真的需要一个向量,你可以从数组中构造一个向量。

【讨论】:

    【解决方案2】:

    C++ 11?我会替换你的 data_struct 构造函数

    data_struct::data_struct(){
      allboards.emplace_back(2315678, 6235756);
      allboards.emplace_back(464135138, 1563135);
      \\5000 more lines like this 
    }
    

    ... 作为最便宜的解决方案。它可以在一定程度上缩短编译器时间,并且绝对应该有助于加快运行时间。

    为了获得更好的改进,您可以考虑initialization list,这样您就可以根据需要以任意多的对提供所有这些数字,但这需要对 data_struct 构造函数进行大量重做。看看下面的主题...您最终可能希望将其转换为

    data_struc someChessData;
    someChessData.allboards =
    {
    {2315678, 6235756},
    {464135138, 1563135},
    ...,
    {more_n1, more_n2}
    };
    

    更新:当然是初始化列表,我在上面做了修复,只是尝试用这种结构分配所有板。

    【讨论】:

    • 为什么你认为 emplace_back 会比 push_back 编译得更快?
    • 我对 C++11 比较陌生,所以对初始化列表没有太多经验。初始化结构向量的最简洁方法是什么(尤其是考虑到编译时)?
    • 由于 all_boards 是一个 std::vector (它是一个模板),每个 push_back() 调用都会吐出一些需要时间编译的代码。不过应该不多,除非它编译为调试模式。不过初始化列表应该很便宜。
    • @NeilKirk 我想它可能会稍微减少解析时间,但如果它在 1000 行的规模上很重要的话,我想知道
    • 太棒了!切换到 emplace_back() 确实将编译过程加快了 3 倍。接下来我将尝试初始化列表。
    猜你喜欢
    • 1970-01-01
    • 2020-01-08
    • 1970-01-01
    • 2012-05-30
    • 1970-01-01
    • 2018-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多