Eigen - 计算 2 组向量之间的距离矩阵

Eigen - Calculate the Distance Matrix between 2 Sets of Vectors

我需要创建一个特征数组,其中包含每个源和记录器位置之间的所有距离。

我有三个 Eigen::Array sx、sy 和 sz 表示源位置,三个 Eigen::Array rx、ry 和 rz 表示记录器位置。源和记录位置数组的长度不必相同。

使用for循环我可以计算距离矩阵如下

Eigen::ArrayXf  sx, sy, sz;
Eigen::ArrayXf  rx, ry, rz;
Eigen::ArrayXXf dist;

for (int s=0; s<nrSources; s++ ) {

   for (int r=0; r<nrReceivers; r++) {

      dist(h,g) = sqrt(pow(rx(h)-sx(g),2.)+
                       pow(ry(h)-sy(g),2.)+
                       pow(sz(h)-sz(g),2.));
   }
}

我需要为实验计算 dist 数组 500 x 1000 次。使用 for 循环显然可行,但它可能不是最有效的方法,因为它不使用矢量化。

将 sx、sx、sz 和 hx、hy 和 hz 重写为 sxyz 和 hxyz 数组应该是可能的。

有没有可能更有效地写出方程式!?

您可能想要放弃内部循环以支持表达式。通过这样做,我们允许将计算集中在一起,并有望实现矢量化。假设 rs 变量被声明为 Eigen::ArrayX3f sxyz(nrSources,3), rxyz(nrReceivers,3);,那么您可以将外部循环写成:

for (int s = 0; s < nrSources; s++)
{
    dist.col(s) =
        (rxyz.rowwise() - sxyz.row(s)).matrix().rowwise().norm();
}       

这里我们使用rxyz.rowwise() - sxyz.row(s)从所有r中减去第s个s。需要 matrix() 才能访问 norm()

基准测试并与您的实施进行比较。

你可以看看我的项目Calculate Distance Matrix
我实现了各种方法来计算 2 个任意向量集之间的距离矩阵。

实际上,Eigen 执行此操作的速度非常快(比使用 MSVC 的普通 C 实现慢得多)。

总之,上面的另一个方法是:

void CalcDistanceMatrixEigen(float* mD, float* mA, float* mB, int vecDim, int numRowsA, int numRowsB)
{

    EigenMatExt meA(mA, vecDim, numRowsA);
    EigenMatExt meB(mB, vecDim, numRowsB);

    EigenMatExt meD(mD, numRowsA, numRowsB);

    // meD = meA.colwise().squaredNorm().transpose() - (2 * meA.transpose() * meB) + meB.colwise().squaredNorm();
    // Not even close to be as fast as MATLAB (Intel MKL???)
    meD = ((-2 * meA.transpose() * meB).colwise() + meA.colwise().squaredNorm().transpose()).rowwise() + meB.colwise().squaredNorm();


}

看看文件就知道了。
您会看到我在 @AviGinsburg 和上述方法中比较了 Eigen,看起来我的速度更快(尽管再次使用 Vanilla C 比 Eigen 快得多)。