Я использую Eigen в своем приложении, и через профилирование я нашел код
похожим на следующее, чтобы быть узким местом. Проблема в том, что память
копирование по мере передачи данных на использование (см. ниже).
Как видно из кода, «данные», используемые для функции matmat, могут иметь
один из двух источников, один хранится в частном порядке в классе SMM, а другой
должен динамически генерироваться на лету. Этот раскол необходим для моего
приложение, но это затрудняет оптимизацию. Был ли источник только
из внутреннего вектора данных мне кажется, что const Eigen :: Refs
быть простым решением. Возможно, это связано с тем, как написан мой код, но
копия elision, кажется, не делает так много, как я бы надеялся. я
Рассматривается использование shared_ptr для предотвращения копирования матриц вокруг (что
может быть довольно большим), но я не уверен, что это правильное направление.
Следует отметить, что результат matmat никогда не нужно хранить, он
используется только как временная переменная в собственном выражении
Как можно эффективно передавать матрицы в этом случае?
Следующий код является упрощением используемой мной установки.
#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;
}