我正在尝试计算colsum(N * P),其中N是稀疏的1M乘2500矩阵,P是2500 x 1.5M的密集矩阵。我正在使用Eigen C ++库和Intel的MKL库。问题是矩阵N * P实际上不能存在于内存中,它太大了(~10 TB)。我的问题是Eigen是否能够通过惰性求值和并行性的某种组合来处理这种计算?它在这里说Eigen不会不必要地制作临时矩阵:http://eigen.tuxfamily.org/dox-devel/TopicLazyEvaluation.html
但是Eigen是否知道计算出实际适合内存的分段块中的N * P? IE:它必须做类似colsum(N * P_1)++ colsum(N * P_2)++ .. ++ colsum(N * P_n)的事情,其中P按列分为n个不同的子矩阵和“+ +“是连接。
我正在使用128 GB RAM。
答案 0 :(得分:1)
我尝试了一下但最终得到了一个糟糕的malloc(我只在Win8上以8GB运行)。我设置了main()
并使用了我写的非内联colsum
函数。
int main(int argc, char *argv[])
{
Eigen::MatrixXd dense = Eigen::MatrixXd::Random(1000, 100000);
Eigen::SparseMatrix<double> sparse(100000, 1000);
typedef Triplet<int> Trip;
std::vector<Trip> trps(dense.rows());
for(int i = 0; i < dense.rows(); i++)
{
trps[i] = Trip(20*i, i, 2);
}
sparse.setFromTriplets(trps.begin(), trps.end());
VectorXd res = colsum(sparse, dense);
std::cout << res;
std::cin >> argc;
return 0;
}
尝试只是:
__declspec(noinline) VectorXd
colsum(const Eigen::SparseMatrix<double> &sparse, const Eigen::MatrixXd &dense)
{
return (sparse * dense).colwise().sum();
}
那有一个糟糕的malloc。 Sol看起来你必须自己手动拆分(除非别人有更好的解决方案)。
我稍微改进了一下这个功能,但得到了同样糟糕的malloc:
__declspec(noinline) VectorXd
colsum(const Eigen::SparseMatrix<double> &sparse, const Eigen::MatrixXd &dense)
{
return (sparse * dense).topRows(4).colwise().sum();
}
另一种选择是使稀疏矩阵密集并强制进行惰性评估。我不认为它适用于稀疏矩阵(哦,好吧)。
__declspec(noinline) VectorXd
colsum(const Eigen::SparseMatrix<double> &sparse, const Eigen::MatrixXd &dense)
{
Eigen::MatrixXd denseSparse(sparse);
return denseSparse.lazyProduct(dense).colwise().sum();
}
这并没有给我带来错误的malloc,但计算了许多毫无意义的0*x_i
表达式。
答案 1 :(得分:0)
回答你的问题:特别是,当涉及到产品时,Eigen经常会将部分表达式评估为临时表。在某些情况下,这可以进行优化但尚未实现,在某些情况下,这实际上是实现它的最有效方式。
但是,在您的情况下,您可以简单地计算N
(1 x 2500向量)的colsum并将其乘以P
。
也许 Eigen的未来版本将能够自己进行这种优化,但大多数情况下,在让计算机完成其余工作之前,最好自己进行特定于问题的优化。
sparse.colwise()
尚未实现,因此您必须手动计算。如果你很懒,你可以改为计算Eigen::RowVectorXd Nsum = Eigen::RowVectorXd::Ones(N.rows())*P;
(我没有检查它,但实际上这可能会被优化到接近最佳代码,使用最新版本的Eigen)。