Armadillo 不执行交换优化
Armadillo does not perform swap optimization
如何交换犰狳对象,例如arma::vec
s,没有交换内容?
void f5()
{
arma::vec x(10);
arma::vec y(10);
std::cout << &x[2] << ", " << &y[2] << "\n";
x.swap(y);
std::cout << &x[2] << ", " << &y[2];
}
以上代码输出
0x24fbe50, 0x24fbef0
0x24fbe50, 0x24fbef0
谢谢!
看起来犰狳的交换在内部是一个小于特定数组大小的 memcpy(根据 op <=16)。
@OZ17 的答案的小扩展。
Armadillo 似乎在本地 mem_local
存储大小小于 16 的数据,在 mem
指出的区域存储更大的数据
From GDB:
> p x
{
<arma::Mat<double>> = {
<arma::Base<double, arma::Mat<double> >> = {
<arma::Base_inv_yes<arma::Mat<double> >> = {<No data fields>},
<arma::Base_eval_Mat<double, arma::Mat<double> >> = {<No data fields>},
<arma::Base_trans_default<arma::Mat<double> >> = {<No data fields>}, <No data fields>},
members of arma::Mat<double>:
n_rows = 1,
n_cols = 10,
n_elem = 10,
vec_state = 2,
mem_state = 0,
mem = 0x7fffffffb830,
mem_local = {0 <repeats 16 times>},
static is_col = false,
static is_row = false
},
members of arma::Row<double>:
static is_col = false,
static is_row = false
}
和一个形象化的小例子:
arma::rowvec x(10,arma::fill::ones);
arma::rowvec y(10,arma::fill::zeros);
std::cout << "Size=10" << std::endl;
std::cout << "&x=" << x.memptr() << ", x[0..4]=" << x.subvec(1,5);
std::cout << "&y=" << y.memptr() << ", y[0..4]=" << y.subvec(1,5);
x.swap(y);
std::cout << "x.swap(y)" << std::endl;
std::cout << "&x=" << x.memptr() << ", x[0..4]=" << x.subvec(1,5);
std::cout << "&y=" << y.memptr() << ", y[0..4]=" << y.subvec(1,5);
arma::rowvec x2(17,arma::fill::ones);
arma::rowvec y2(17,arma::fill::zeros);
std::cout << "\nSize=17" << std::endl;
std::cout << "&x=" << x2.memptr() << ", x[0..4]=" << x2.subvec(1,5);
std::cout << "&y=" << y2.memptr() << ", y[0..4]=" << y2.subvec(1,5);
x2.swap(y2);
std::cout << "x.swap(y)" << std::endl;
std::cout << "&x=" << x2.memptr() << ", x[0..4]=" << x2.subvec(1,5);
std::cout << "&y=" << y2.memptr() << ", y[0..4]=" << y2.subvec(1,5);
示例的输出显示在两种情况下都交换了内容,但对于小数组,它交换了本地内存区域,对于较大的情况,它交换了内存指针。
Size=10
&x=0x7fffffffb830, x[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000
&y=0x7fffffffb8e0, y[0..4]= 0 0 0 0 0
x.swap(y)
&x=0x7fffffffb830, x[0..4]= 0 0 0 0 0
&y=0x7fffffffb8e0, y[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000
Size=17
&x=0x5555557d7fd0, x[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000
&y=0x5555557d8060, y[0..4]= 0 0 0 0 0
x.swap(y)
&x=0x5555557d8060, x[0..4]= 0 0 0 0 0
&y=0x5555557d7fd0, y[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000
如何交换犰狳对象,例如arma::vec
s,没有交换内容?
void f5()
{
arma::vec x(10);
arma::vec y(10);
std::cout << &x[2] << ", " << &y[2] << "\n";
x.swap(y);
std::cout << &x[2] << ", " << &y[2];
}
以上代码输出
0x24fbe50, 0x24fbef0
0x24fbe50, 0x24fbef0
谢谢!
看起来犰狳的交换在内部是一个小于特定数组大小的 memcpy(根据 op <=16)。
@OZ17 的答案的小扩展。
Armadillo 似乎在本地 mem_local
存储大小小于 16 的数据,在 mem
From GDB:
> p x
{
<arma::Mat<double>> = {
<arma::Base<double, arma::Mat<double> >> = {
<arma::Base_inv_yes<arma::Mat<double> >> = {<No data fields>},
<arma::Base_eval_Mat<double, arma::Mat<double> >> = {<No data fields>},
<arma::Base_trans_default<arma::Mat<double> >> = {<No data fields>}, <No data fields>},
members of arma::Mat<double>:
n_rows = 1,
n_cols = 10,
n_elem = 10,
vec_state = 2,
mem_state = 0,
mem = 0x7fffffffb830,
mem_local = {0 <repeats 16 times>},
static is_col = false,
static is_row = false
},
members of arma::Row<double>:
static is_col = false,
static is_row = false
}
和一个形象化的小例子:
arma::rowvec x(10,arma::fill::ones);
arma::rowvec y(10,arma::fill::zeros);
std::cout << "Size=10" << std::endl;
std::cout << "&x=" << x.memptr() << ", x[0..4]=" << x.subvec(1,5);
std::cout << "&y=" << y.memptr() << ", y[0..4]=" << y.subvec(1,5);
x.swap(y);
std::cout << "x.swap(y)" << std::endl;
std::cout << "&x=" << x.memptr() << ", x[0..4]=" << x.subvec(1,5);
std::cout << "&y=" << y.memptr() << ", y[0..4]=" << y.subvec(1,5);
arma::rowvec x2(17,arma::fill::ones);
arma::rowvec y2(17,arma::fill::zeros);
std::cout << "\nSize=17" << std::endl;
std::cout << "&x=" << x2.memptr() << ", x[0..4]=" << x2.subvec(1,5);
std::cout << "&y=" << y2.memptr() << ", y[0..4]=" << y2.subvec(1,5);
x2.swap(y2);
std::cout << "x.swap(y)" << std::endl;
std::cout << "&x=" << x2.memptr() << ", x[0..4]=" << x2.subvec(1,5);
std::cout << "&y=" << y2.memptr() << ", y[0..4]=" << y2.subvec(1,5);
示例的输出显示在两种情况下都交换了内容,但对于小数组,它交换了本地内存区域,对于较大的情况,它交换了内存指针。
Size=10
&x=0x7fffffffb830, x[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000
&y=0x7fffffffb8e0, y[0..4]= 0 0 0 0 0
x.swap(y)
&x=0x7fffffffb830, x[0..4]= 0 0 0 0 0
&y=0x7fffffffb8e0, y[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000
Size=17
&x=0x5555557d7fd0, x[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000
&y=0x5555557d8060, y[0..4]= 0 0 0 0 0
x.swap(y)
&x=0x5555557d8060, x[0..4]= 0 0 0 0 0
&y=0x5555557d7fd0, y[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000