我有一个NxN非负的Eigen::MatrixXi
称为cost_matrix
,两个Nx1非负的Eigen::VectorXi
称为rowVector
和colVector
。我想找到第一个索引(i,j),使得cost_matrix(i, j)
,rowVector(i)
和colVector(j)
都是零。
我知道有一些简单的解决方案,比如遍历所有元素,但它们花费太多时间。我想在Eigen C++中找到最有效的方法。
这是我目前的代码,它比使用Eigen::DenseBase::visit
遍历所有元素要快。
Eigen::MatrixXi cost_matrix(4,4);
cost_matrix<<1, 2, 3, 0,
5, 0, 0, 8,
9, 8, 7, 6,
0, 2, 1, 5;
Eigen::VectorXi rowCover(4);
Eigen::VectorXi colCover(4);
rowCover << 0, 0, 1, 1;
colCover << 1, 1, 0, 1;
//A data demo. Cost_matrix is a NxN nonnegative int matrix.
//RowCover and colCover are N nonnegative int vector.
int i, j;
cost_matrix.colwise() += rowCover;
cost_matrix.rowwise() += colCover.transpose();
Eigen::Index zeroRow, zeroCol;
int min = find_zero_matrix.transpose().minCoeff(&zeroCol, &zeroRow);
i = zeroRow;
j = zeroCol;
//the result should be
//i = 1
//j = 2
字符串
1条答案
按热度按时间62o28rlo1#
正如@chtz已经在评论中建议的那样,Eigen不会真正帮助你。我们仍然可以尝试找到一个更快的版本。
这是我的想法:
首先,我扩展/修复您的代码,以获得一个工作的引用实现。
字符串
遍历整个输入矩阵似乎是非常浪费的,除非覆盖向量通常为零而输入矩阵不是。如果覆盖包含许多非零元素,最好将它们转换为零索引的向量。
型
现在我们只需要检查矩阵中两个覆盖都为零的条目。
型
为了获得最佳结果,请使用
-DNDEBUG
编译,以避免在各种索引操作中进行范围检查。测试
矩阵大小N大约是20,但是它每帧会运行很多次。0的间隔大约是1/N(可能每行几个0)
我假设这个1/N不适用于覆盖向量。否则你找到一个条目的机会很低。我随意决定用4/N测试覆盖矩阵,用1/N测试成本矩阵。
完整的测试和基准测试结果如下所示。在我的系统上,我的版本在所选参数集下的速度大约是10倍,即使我将cover更改为全零,它也快了7.5倍。即使在绝对最坏的情况下-cover全零,matrix全一-它仍然快了两倍。
型
更多要点
附录:我对AVX 512的显式矢量化做了一些测试。首先,让
to_zero_indices
使用vpcompressd
。这稍微快一点,但不值得。其次,我用一些矢量化扫描优化了上面最差的情况。在这种情况下,它使性能提高了一倍,但同时支持两种模式,并决定是使用扫描还是使用常规操作有足够的开销,使常规情况的速度降低了一半。所以没什么用。