Armadillo库中方括号[]和小括号()的区别
Armadillo library difference between square brackets [] and parenthesis ()
Armadillo 库为 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
答案大部分在你给出的link中:
- "
.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()
和 []
看似多余的存在的原因是 []
不可用于多个索引(但大概仍然可用于一个-index 大小写,因为它比 .at()
). 自然得多
- 这在 link 中没有提到,但那是因为 C++ 不允许用多个参数重载
operator[]
函数,所以这最终总是被解释为 [(i,j)]
最终被评估为 [i]
- j
被评估(例如,如果它是一个函数调用)但随后被默默地丢弃!
实际上,检查索引访问在大多数应用程序中不太可能成为瓶颈,并且在许多情况下可能会被编译器完全优化掉(至少在发布模式下)。所以我的建议是始终使用圆括号 mat(ind)
表示法。
Armadillo 库为 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
答案大部分在你给出的link中:
- "
.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()
和[]
看似多余的存在的原因是[]
不可用于多个索引(但大概仍然可用于一个-index 大小写,因为它比.at()
). 自然得多
- 这在 link 中没有提到,但那是因为 C++ 不允许用多个参数重载
operator[]
函数,所以这最终总是被解释为[(i,j)]
最终被评估为[i]
-j
被评估(例如,如果它是一个函数调用)但随后被默默地丢弃!
- 所以
实际上,检查索引访问在大多数应用程序中不太可能成为瓶颈,并且在许多情况下可能会被编译器完全优化掉(至少在发布模式下)。所以我的建议是始终使用圆括号 mat(ind)
表示法。