c++ - 如何 "move"Eigen::VectorXd s

标签 c++ c++11 move eigen

我最近发表的一篇文章中的一位评论者告诉我,我需要更好地利用 c++11 move 语义来处理代码中的瓶颈。以下是需要修复的简化版本。

#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 都提到返回修改后的复制参数会比再次复制更快,我同意,但我怀疑这对于我的实际代码是否可行。我可以稍后再问这个问题,但这将是一个单独的问题/线程。

最佳答案

您没有看对线。如果一份拷贝是强制性的,那么您就无法摆脱它。尽管如此,最好避免 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 进行编译获取 move 语义拷贝。

最后,最好打包你的 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
}

关于c++ - 如何 "move"Eigen::VectorXd s,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42442748/

相关文章:

c++ - Hinnant 的堆栈分配器与 boost rtrees : compilation failure

key - 使用 while 循环和 if 语句处理对象不会在 x 轴上 move

c++ - 安全 move 在访问其他成员的成员线程中运行 lambda 的对象

c++ - 为什么我的 C++ 到十六进制转换会导致不同的格式?

c++ - 实现复制的简单 C++ 程序中的错误输出

c++ - qtquickcontrolsapplication.h 上的 Qt 创建者错误

c++ - C++ 中的 string[length()] 可以吗?

c++ - 如何在 C++11 中将容器 std::array<type, size> 用于多维数组?

android - 如何在程序运行时更改布局参数

c++ - 在 Qt QML 中为许多文本元素指定字体