犰狳库中方括号[]和圆括号()的区别
Posted
技术标签:
【中文标题】犰狳库中方括号[]和圆括号()的区别【英文标题】:Armadillo library difference between square brackets [] and parenthesis () 【发布时间】:2020-06-25 12:48:13 【问题描述】:犰狳库为element access提供了3种方式:
-
通过
()
;
通过[]
;
通过at()
;
我注意到使用它们时的性能有所不同。我测试了下面的代码:
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;
结果是:
-
通过
()
0.0008 秒;
通过[]
0.0003 秒;
通过at()
0.0007 秒;
有人可以评论给定的结果吗?
我使用 Windows 10 x64、MSVC 2017、发布模式、Qt 5.14.2
我在config.hpp
中设置了#define ARMA_NO_DEBUG
【问题讨论】:
犰狳documentation 声明#define ARMA_NO_DEBUG
不是在您的代码中的所有错误都被检测和删除之前是一个好主意。
【参考方案1】:
答案主要在您提供的链接中:
".at(n)
或[n]
与 (n) 相同,但没有边界检查。除非您的代码经过彻底调试,否则不建议使用。"
所以答案的第一部分是 .at(n)
和 [n]
可能比 (n)
稍快一些,但安全性较低,这可能就是为什么 ()
访问在您的测试中花费的时间最长。
但是[n]
和.at(n)
是相同的,您看到的时间差异只是您运行或计时测试方式的相同人工制品。这并不奇怪,因为基准测试是出了名的困难,它不仅仅是在你正在做的一些时间循环中运行一些东西的问题。 (实际上这甚至可能是您看到()
时差的真正原因。)
此约定与 STL 容器的不同之处令人困惑:通常 []
未选中,.at()
已选中,而用于索引的 ()
根本不存在。
还有(i,j)
和.at(i,j)
,还有(i,j,k)
和.at(i,j,k)
,但没有[i,j]
或[i,j,k]
。
所以.at()
和[]
看似多余的存在的原因是[]
不能用于一个以上的索引(但可能仍然适用于一个索引的情况,因为它要多得多自然比.at()
)。
链接中没有提到这一点,但这是因为 C++ 不允许使用多个参数重载 operator[]
函数,所以这总是会被解释为 [(i,j)]
最终被评估为 [i]
- j
被评估(例如,如果它是一个函数调用),然后被默默地丢弃!
实际上,检查索引访问不太可能成为大多数应用程序的瓶颈,并且在许多情况下,编译器无论如何都可能完全优化掉(至少在发布模式下)。所以我的建议是始终使用圆括号 mat(ind)
表示法。
【讨论】:
感谢您的回答,但我在配置文件中设置了#define ARMA_NO_DEBUG
。那应该关闭所有边界检查。我也可以使用[i,j]
索引并且它可以工作
在这种情况下,您看到的整个时间差异是由于随机波动造成的。尝试用完全相同的索引方法复制粘贴三次替换三种不同的索引方法,您肯定会看到相同的波动。
至于[i,j]
索引,我保证这不会起作用,在C++ 中是不可能的。作为额外的证据,Armadillo 文档显然不支持它,.at()
存在的全部原因是允许使用多个参数检查索引。它会编译,但会给出不正确的结果:实际上,j
完全被忽略了,原因是我在答案中说的,而且当您为二维矩阵提供一个索引时,犰狳会进行线性索引。 [编辑:或者可能是 i
被忽略了,但重点是一样的。]
是的,[i,j]
索引给了我错误的结果。谢谢!以上是关于犰狳库中方括号[]和圆括号()的区别的主要内容,如果未能解决你的问题,请参考以下文章