矩阵的特征有效传递
Eigen Efficient Passing of Matrices
我在我的应用程序中使用 Eigen,通过分析我找到了代码
类似下面是瓶颈。内存问题
在数据传递到使用时进行复制(见下文)。
如代码中可见,用于 matmat 函数的 "data" 可以有
两个来源之一,一个私人存储在 SMM class,而另一个
是动态生成的。这种分裂对我来说是必要的
应用程序,但它很难优化。仅来源
从数据的内部向量来看,在我看来 const Eigen::Refs 会
是一个简单的解决方案。也许这是由于我的代码编写方式所致,但是
复制省略似乎并没有像我希望的那样发挥作用。我
考虑使用 shared_ptr 来防止复制矩阵(
可以很大),但我不确定这是否是正确的方向。
需要注意的是,matmat的结果永远不需要存储,它是
仅在 Eigen 表达式中用作临时变量
在这种情况下如何有效地传递矩阵?
以下代码是我使用的设置的简化。
#include <Eigen/Dense>
#include <Eigen/StdVector>
#include <iostream>
using namespace Eigen;
typedef MatrixXd MMatrix;
enum class Storage {Normal, On_The_Fly };
MMatrix matrixGen(int additional_data) {
return additional_data * MMatrix::Random(5, 5);
}
class SMM {
private:
std::vector<MMatrix, Eigen::aligned_allocator<MMatrix> > data_;
//Provides controlled access to the data
MMatrix get_data(int i, Storage mem, int additional_data = 0) {
if (mem != Storage::On_The_Fly) {
return data_[i];
}
else {
return matrixGen(additional_data);
}
}
public:
// Only a placeholder constructor, in my actual program the building
// is significantly more complex, and doesn't build the data immediately
SMM(Storage mem) {
if (mem == Storage::Normal) {
for (int i = 0; i < 5; i++) {
data_.emplace_back(matrixGen(5));
}
}
}
//Similar to a matrix * matrix product
MMatrix matmat(const MMatrix& A, int index, Storage mem, int additional_data = 0) {
if (mem == Storage::On_The_Fly) {
return this->get_data(index, mem, additional_data) * A;
}
else {
return this->get_data(index, mem) * A;
}
}
};
int main() {
Storage mem1 = Storage::Normal;
Storage mem2 = Storage::On_The_Fly;
SMM smm1 = SMM(mem1);
SMM smm2 = SMM(mem2);
MMatrix A = MMatrix::Random(5, 5);
MMatrix B = MMatrix::Random(5, 5);
MMatrix C = MMatrix::Random(5, 5);
B += smm1.matmat(A, 2, mem1);
C += smm2.matmat(A, 2, mem2, 5);
std::cout << B << std::endl << std::endl;
std::cout << C << std::endl;
}
一个简单的解决方案是使用缓存成员变量:
class SMM {
...
MMatrix cache_;
const MMatrix& get_data(int i, Storage mem, int additional_data = 0) {
if (mem != Storage::On_The_Fly) { return data_[i]; }
else {
matrixGenInPlace(additional_data,cache_);
return cache_;
}
}
...
};
我在我的应用程序中使用 Eigen,通过分析我找到了代码 类似下面是瓶颈。内存问题 在数据传递到使用时进行复制(见下文)。
如代码中可见,用于 matmat 函数的 "data" 可以有 两个来源之一,一个私人存储在 SMM class,而另一个 是动态生成的。这种分裂对我来说是必要的 应用程序,但它很难优化。仅来源 从数据的内部向量来看,在我看来 const Eigen::Refs 会 是一个简单的解决方案。也许这是由于我的代码编写方式所致,但是 复制省略似乎并没有像我希望的那样发挥作用。我 考虑使用 shared_ptr 来防止复制矩阵( 可以很大),但我不确定这是否是正确的方向。
需要注意的是,matmat的结果永远不需要存储,它是 仅在 Eigen 表达式中用作临时变量
在这种情况下如何有效地传递矩阵?
以下代码是我使用的设置的简化。
#include <Eigen/Dense>
#include <Eigen/StdVector>
#include <iostream>
using namespace Eigen;
typedef MatrixXd MMatrix;
enum class Storage {Normal, On_The_Fly };
MMatrix matrixGen(int additional_data) {
return additional_data * MMatrix::Random(5, 5);
}
class SMM {
private:
std::vector<MMatrix, Eigen::aligned_allocator<MMatrix> > data_;
//Provides controlled access to the data
MMatrix get_data(int i, Storage mem, int additional_data = 0) {
if (mem != Storage::On_The_Fly) {
return data_[i];
}
else {
return matrixGen(additional_data);
}
}
public:
// Only a placeholder constructor, in my actual program the building
// is significantly more complex, and doesn't build the data immediately
SMM(Storage mem) {
if (mem == Storage::Normal) {
for (int i = 0; i < 5; i++) {
data_.emplace_back(matrixGen(5));
}
}
}
//Similar to a matrix * matrix product
MMatrix matmat(const MMatrix& A, int index, Storage mem, int additional_data = 0) {
if (mem == Storage::On_The_Fly) {
return this->get_data(index, mem, additional_data) * A;
}
else {
return this->get_data(index, mem) * A;
}
}
};
int main() {
Storage mem1 = Storage::Normal;
Storage mem2 = Storage::On_The_Fly;
SMM smm1 = SMM(mem1);
SMM smm2 = SMM(mem2);
MMatrix A = MMatrix::Random(5, 5);
MMatrix B = MMatrix::Random(5, 5);
MMatrix C = MMatrix::Random(5, 5);
B += smm1.matmat(A, 2, mem1);
C += smm2.matmat(A, 2, mem2, 5);
std::cout << B << std::endl << std::endl;
std::cout << C << std::endl;
}
一个简单的解决方案是使用缓存成员变量:
class SMM {
...
MMatrix cache_;
const MMatrix& get_data(int i, Storage mem, int additional_data = 0) {
if (mem != Storage::On_The_Fly) { return data_[i]; }
else {
matrixGenInPlace(additional_data,cache_);
return cache_;
}
}
...
};