【问题标题】:C++: Time for filling an array is too longC++:填充数组的时间太长
【发布时间】:2013-04-21 08:17:28
【问题描述】:

我们正在编写一个将一些数据写入数组的方法 (myFunc)。数组必须是类 (MyClass) 的字段。 示例:

class MyClass {
public:
  MyClass(int dimension);
  ~MyClass();

  void myFunc();

protected:

  float* _nodes;
};

MyClass::MyClass(int dimension){
 _nodes = new float[dimension];
}

void MyClass::myFunc(){
 for (int i = 0; i < _dimension; ++i)
  _nodes[i] = (i % 2 == 0) ? 0 : 1;
}

方法 myFunc 被调用近 10000 次,大约需要 9-10 秒(使用其他方法)。

但如果我们将 myFunc 定义为:

void MyClass::myFunc(){
 float* test = new float[_dimension];
 for (int i = 0; i < _dimension; ++i)
     test[i] = (i % 2 == 0) ? 0 : 1;
}

我们的程序运行得更快 - 大约需要 2-3 秒(如果它的调用次数接近 10000 次)。

提前致谢!

【问题讨论】:

  • 我们正在调试模式下编译
  • 如果这是 Debug 构建,则在访问成员变量时所有赌注都关闭。
  • 叹息...为什么在 95% 的“为什么我的代码很慢”的问题中,人们在编译时没有进行优化?有什么意义?
  • 基本上,试图了解在调试模式下编译的代码的性能是没有意义的,试图“修复”这类“问题”会适得其反。
  • 这是什么意思:“大约需要 9-10 秒(使用其他方法)”。还有什么方法?您希望我们如何分析我们未见过的方法?发布您在发布模式下测试并看到问题的最小完整示例,您可能在此处有一个实际问题。

标签: c++ arrays class pointers methods


【解决方案1】:

这可能会有所帮助(无论哪种情况)

for (int i = 0; i < _dimension; )
{
    test[i++] = 0.0f;
    test[i++] = 1.0f;
}

我假设_dimension 是偶数,但如果不是,则很容易修复。

【讨论】:

    【解决方案2】:

    如果你想加快调试模式,也许帮助编译器,试试

    void MyClass::myFunc(){
       float* const nodes = _nodes;
       const int dimension = _dimension;
       for (int i = 0; i < dimension; ++i)
           nodes[i] = (i % 2 == 0) ? 0.0f : 1.0f;
    }
    

    当然,实际上你应该专注于使用发布模式来处理所有与性能相关的事情。

    【讨论】:

    • 感谢 Daniel,但将 0 更改为 0.0f 和 1 更改为 1.0f(和类似的)并没有帮助
    • @user2303872 重点是添加和使用nodesdimension 而不是_nodes_dimension 循环!
    【解决方案3】:

    在您的示例代码中,您没有在构造函数中初始化 _dimension,而是在 MyFunc 中使用它。因此,即使您只分配了几千个条目,您也可能会在数组中填充数百万个条目。在有效的示例中,您使用相同的维度来创建和填充数组,因此在这种情况下您可能会正确初始化它..

    只需确保 _dimension 已正确初始化即可。

    【讨论】:

      【解决方案4】:

      这在大多数机器上更快。

      void MyClass::myFunc(){
          float* const nodes = _nodes;
          const int dimension = _dimension;
          if(dimension < 2){
              if(dimension < 1)
                  return;
              nodes[0] = 0.0f;
              return;
          }
          nodes[0] = 0.0f;
          nodes[1] = 1.0f;
          for (int i = 2; ; i <<= 1){
              if( (i << 1) < dimension ){
                  memcpy(nodes + i, nodes, i * sizeof(float));
              }else{
                  memcpy(nodes + i, nodes, (dimension - i) * sizeof(float));
                  break;
              }
          }
      }
      

      【讨论】:

      • 如果维度为
      • 提前想起来也很容易。现在为时已晚,飞机坠毁了。
      • @6502 我知道它会崩溃!我只想发布一个最小的代码!
      【解决方案5】:

      试试这个:

      memset(test, 0, sizeof(float) * _dimension));
      for (int i = 1; i < _dimension; i += 2)
      {
          test[i] = 1.0f;
      }
      

      您也可以运行一次并将数组存储在静态位置。 对于每次连续迭代,您无需任何计算即可处理存储的数据。

      【讨论】:

      • 在大多数现代计算机中两次通过内存会变慢
      • @6502 这取决于 memset 的实现。而且不是两倍而是1.5倍
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-11
      • 2018-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-20
      • 1970-01-01
      相关资源
      最近更新 更多