如何 "move" Eigen::VectorXd
How to "move" Eigen::VectorXd s
我最近 post 的一位评论者告诉我,我需要更好地利用 c++11 移动语义来处理代码中的瓶颈。以下是需要修复的简化版本。
#include <iostream>
#include <Eigen/Dense>
#include <vector>
void makeCopy(std::vector<Eigen::VectorXd> &oldV){
int n = oldV.size();
std::vector<Eigen::VectorXd> mandatoryCopy;
mandatoryCopy.resize(n);
for(int i = 0; i < n; i++){
mandatoryCopy[i] = oldV[i];
}
// swap the two
oldV = mandatoryCopy;
}
int main(int argc, char **argv)
{
// starting vector
int len(1000);
Eigen::VectorXd placeHolder(50);
std::vector<Eigen::VectorXd> v(len, placeHolder);
// copy it a bunch of times
for(int iter = 0; iter < 1000; ++iter){
std::cout << "iter: " << iter << "\n";
makeCopy(v);
}
return 0;
}
问题:在makeCopy
的for循环中,oldV[i]
是一个左值,所以我怎么能做类似mandatoryCopy[i]&& = oldV[i]
的事情呢?这是主要的瓶颈,对吧?我在想 mandatoryCopy[i]&& = std::move(oldV[i])
之类的东西,但这显然无法编译。
编辑
按照@vsoftco的建议,我试过了
std::vector<Eigen::VectorXd> makeCopy2(std::vector<Eigen::VectorXd> oldV){
int n = oldV.size();
std::vector<Eigen::VectorXd> mandatoryCopy;
mandatoryCopy.resize(n);
for(int i = 0; i < n; i++){
mandatoryCopy[i] = oldV[i];
}
return mandatoryCopy;
}
但我发现它比较慢。 @vsoftco 和@ggael 都提到 return 修改后的复制参数会更快,而不是再次复制,我同意,但我怀疑这对我的实际代码是否可行。我可以稍后再问这个问题,但这将是一个单独的 question/thread.
你没有看对线。如果一份副本是强制性的,那么你就无法摆脱它。尽管如此,最好避免 for 循环和 right:
std::vector<Eigen::VectorXd> mandatoryCopy = oldV;
另一方面,您可以通过将 oldV=mandatoryCopy
替换为:
来省略第二个副本
std::swap(oldV,mandatoryCopy);
这将执行便宜的指针交换。你得到:
void makeCopy(std::vector<Eigen::VectorXd> &oldV){
std::vector<Eigen::VectorXd> V = oldV;
// do something with V
std::swap(oldV,V);
}
对于函数式风格,在你的第二个例子中,你必须直接使用已经是副本的参数:
std::vector<Eigen::VectorXd> makeCopy2(std::vector<Eigen::VectorXd> V){
// do something with V
return V;
}
并用 v = makeCopy2(v);
.
调用它
不要忘记使用 -std=c++11
进行编译以获得移动语义副本。
最后,将您的 vector<VectorXd>
打包在 MatrixXd
中可能会更好。这将显着减少内存分配的数量:
void makeCopy3(MatrixXd &oldV){
int n = oldV.cols();
MatrixXd V = oldV;
for(int i = 0; i < n; i++){
V.col(i) *= 0.99;
}
oldV.swap(V); // or oldV = std::move(V); with c++11 enabled
}
我最近 post 的一位评论者告诉我,我需要更好地利用 c++11 移动语义来处理代码中的瓶颈。以下是需要修复的简化版本。
#include <iostream>
#include <Eigen/Dense>
#include <vector>
void makeCopy(std::vector<Eigen::VectorXd> &oldV){
int n = oldV.size();
std::vector<Eigen::VectorXd> mandatoryCopy;
mandatoryCopy.resize(n);
for(int i = 0; i < n; i++){
mandatoryCopy[i] = oldV[i];
}
// swap the two
oldV = mandatoryCopy;
}
int main(int argc, char **argv)
{
// starting vector
int len(1000);
Eigen::VectorXd placeHolder(50);
std::vector<Eigen::VectorXd> v(len, placeHolder);
// copy it a bunch of times
for(int iter = 0; iter < 1000; ++iter){
std::cout << "iter: " << iter << "\n";
makeCopy(v);
}
return 0;
}
问题:在makeCopy
的for循环中,oldV[i]
是一个左值,所以我怎么能做类似mandatoryCopy[i]&& = oldV[i]
的事情呢?这是主要的瓶颈,对吧?我在想 mandatoryCopy[i]&& = std::move(oldV[i])
之类的东西,但这显然无法编译。
编辑
按照@vsoftco的建议,我试过了
std::vector<Eigen::VectorXd> makeCopy2(std::vector<Eigen::VectorXd> oldV){
int n = oldV.size();
std::vector<Eigen::VectorXd> mandatoryCopy;
mandatoryCopy.resize(n);
for(int i = 0; i < n; i++){
mandatoryCopy[i] = oldV[i];
}
return mandatoryCopy;
}
但我发现它比较慢。 @vsoftco 和@ggael 都提到 return 修改后的复制参数会更快,而不是再次复制,我同意,但我怀疑这对我的实际代码是否可行。我可以稍后再问这个问题,但这将是一个单独的 question/thread.
你没有看对线。如果一份副本是强制性的,那么你就无法摆脱它。尽管如此,最好避免 for 循环和 right:
std::vector<Eigen::VectorXd> mandatoryCopy = oldV;
另一方面,您可以通过将 oldV=mandatoryCopy
替换为:
std::swap(oldV,mandatoryCopy);
这将执行便宜的指针交换。你得到:
void makeCopy(std::vector<Eigen::VectorXd> &oldV){
std::vector<Eigen::VectorXd> V = oldV;
// do something with V
std::swap(oldV,V);
}
对于函数式风格,在你的第二个例子中,你必须直接使用已经是副本的参数:
std::vector<Eigen::VectorXd> makeCopy2(std::vector<Eigen::VectorXd> V){
// do something with V
return V;
}
并用 v = makeCopy2(v);
.
不要忘记使用 -std=c++11
进行编译以获得移动语义副本。
最后,将您的 vector<VectorXd>
打包在 MatrixXd
中可能会更好。这将显着减少内存分配的数量:
void makeCopy3(MatrixXd &oldV){
int n = oldV.cols();
MatrixXd V = oldV;
for(int i = 0; i < n; i++){
V.col(i) *= 0.99;
}
oldV.swap(V); // or oldV = std::move(V); with c++11 enabled
}