我正在研究一个模拟矩阵矢量产品的代码。在此代码中,我们明确计算了向量A x
,但我们无法访问完整矩阵A
,因为dim
通常非常大,因此整个矩阵{{1无法存储在内存中。
通过做一些时间,我们已经确定以下循环大约需要4秒钟才能完成。 A
是自定义类的一个实例,基本上是string
的包装,而unsigned long
是matvec
。
Eigen::VectorXd
在尝试确定此循环的瓶颈时,我们尝试了各种各样的操作,例如优化// Off-diagonal contributions
for (size_t I = 0; I < dim; I++) {
for (size_t p = 0; p < K; p++) {
if (string.isOccupied(p)) { // p in I
for (size_t q = 0; q < p; q++) {
if (!string.isOccupied(q)) {
string.annihilate(p);
string.create(q);
size_t J = string.address();
matvec(I) += value(p,q) * x(J);
matvec(J) += value(p,q) * x(I);
string.annihilate(q);
string.create(p);
}
} // q < p loop
}
} // p loop
string.nextPermutation();
}
和annihilate
调用,但这些调用效果不大。但是,当我们对没有更新create
值的代码计时时,即
Eigen::VectorXd
循环现在只需0.2秒。 由此我们推断出瓶颈实际上是在生成的向量中添加正确的值。 参见编辑
使用C ++ Eigen库有没有更快的方式进行// Off-diagonal contributions
for (size_t I = 0; I < dim; I++) {
for (size_t p = 0; p < K; p++) {
if (string.isOccupied(p)) { // p in I
for (size_t q = 0; q < p; q++) {
if (!string.isOccupied(q)) {
string.annihilate(p);
string.create(q);
size_t J = string.address();
string.annihilate(q);
string.create(p);
}
} // q < p loop
}
} // p loop
string.nextPermutation();
}
调用?
编辑:我已经做了一些更好的时机,受到@PeterT和@ chtz评论的启发,我发现matvec(I) += value(p,q) * x(J)
语句大约 30%在+=
循环中花费的所有时间,而其他部分都占用了剩余时间的相同比例。
所以,问题仍然存在:for
和matvec(I) += value(p,q) * x(J)
如何加速?