提问者:小点点

犰狳文库方括号[]与括号()之间的差异


犰狳库提供了3种元素访问方式:

  1. 通过()
  2. 通过[]
  3. 通过位于()

我注意到在使用它们时,它们的性能是不同的。 我测试了下面的代码:

size_t n_row = 500, n_col = 500;

{ // ()
    wall_clock timer;
    mat matrix(n_row, n_col, fill::zeros);
    timer.tic();
    for (size_t i = 0; i < n_row; i++){
        for (size_t j = 0; j < n_col; j++){
            matrix(i, j) = i+j;
        }
    }
    std::cout << timer.toc() << std::endl;
}

{ // []
    wall_clock timer;
    mat matrix(n_row, n_col, fill::zeros);
    timer.tic();
    for (size_t i = 0; i < n_row; i++){
        for (size_t j = 0; j < n_col; j++){
            matrix[i, j] = i+j;
        }
    }
    std::cout << timer.toc() << std::endl;
}

{ // .at()
    wall_clock timer;
    mat matrix(n_row, n_col, fill::zeros);
    timer.tic();
    for (size_t i = 0; i < n_row; i++){
        for (size_t j = 0; j < n_col; j++){
            matrix.at(i, j) = i+j;
        }
    }
    std::cout << timer.toc() << std::endl;
}

结果是:

  1. 通过()0.0008秒;
  2. 通过[]0.0003秒;
  3. 通过在()0.0007秒;

有谁能对给定的结果作出评论吗? 我使用Windows 10 x64,MSVC 2017,发布模式,Qt 5.14.2我在config.hpp中设置#define arma_no_debug


共1个答案

匿名用户

答案大多在你给出的链接中:

  • .at(n)[n]作为(n),但不进行界限检查。除非您的代码已完全调试,否则不建议使用。”
      因此,答案的第一部分是,.at(n)[n]可能比(n)稍快,但安全性较低,这可能就是为什么()访问在您的测试中花费的时间最长。
    • 但是[n].at(n)是相同的,您所看到的时间上的差异只是您运行测试或为测试计时的方式造成的。 这并不奇怪,因为基准测试是出了名的困难,它不仅仅是像您正在做的那样用一些时间在循环中运行一些东西的问题。 (实际上,这甚至可能是您在().)
    • 中看到的时间差的真正原因
    • 此约定与STL容器有令人困惑的不同:通常[]未被选中,.at()被选中,而用于索引的()根本不存在。
    • 所以,.at()[]似乎都很少存在的原因是,[]不能用于多个索引(但可以推测,它仍然可以用于一个索引的情况,因为它比.at()自然得多)。
    • 链接中没有提到这一点,但这是因为C++不允许重载带有多个参数的运算符[]函数,因此这将始终被解释为[(i,j)],最终被计算为[i]-j被计算(例如,如果它是一个函数调用),但随后被无声无息地丢弃!

    实际上,在大多数应用程序中,检查索引访问极不可能成为瓶颈,而且在许多情况下,编译器可能会完全优化掉(至少在发布模式下)。 因此,我的建议是始终使用圆括号mat(ind)表示法。