如果矩阵是密集且不对称的,那么特征库矩阵/向量操作比.net更快吗?

时间:2017-03-16 08:07:34

标签: c++ .net matrix eigen

我有一些矩阵运算,主要是处理像遍历矩阵的每个行和列的操作并执行乘法运算a*mat[i,j]*mat[ii,j]

public double[] MaxSumFunction()
{
   var maxSum= new double[vector.GetLength(1)];
   for (int j = 0; j < matrix.GetLength(1); j++)
   {
        for (int i = 0; i < matrix.GetLength(0); i++) 
        {
             for (int ii = 0; ii < matrix.GetLength(0); ii++)
              {
                   double wi= Math.Sqrt(vector[i]);
                   double wii= Math.Sqrt(vector[ii]);
                   maxSum[j] += SomePowerFunctions(wi, wii) * matrix[i, j]*matrix[ii, j];
              }
          }                      
     }
 }

    private double SomePowerFunctions(double wi, double wj)
    {

        var betaij = wi/ wj;
        var numerator = 8 * Math.Sqrt(wi* wj) * Math.Pow(betaij, 3.0 / 2)
            * (wi+ betaij * wj);
        var dominator = Math.Pow(1 - betaij * betaij, 2) +
            4 * wi* wj* betaij * (1 + Math.Pow(betaij, 2)) +
            4 * (wi* wi+ wj* wj) * Math.Pow(betaij, 2);


        if (wi== 0 && wj== 0)
        {
            if (Math.Abs(betaij - 1) < 1.0e-8)
                return 1;
            else
                return 0;
        }

        return numerator / dominator;
    }

如果矩阵大小很大,我发现这样的循环特别慢。

我希望速度快。所以我正在考虑使用Eigen库重新实现这些算法。

我的矩阵不是对称的,不是稀疏的,并且没有任何解算器可以可靠地利用的规律性。

我读到Eigen solver can be fast因为:

  1. 编译器优化
  2. 矢量
  3. Multi-thread support
  4. 但我想知道这些优势是否真的适用于我的矩阵特征?

    注意:我本可以运行一两个样本来查找,但我相信在这里提出问题并将其记录在互联网上也会帮助其他人。

1 个答案:

答案 0 :(得分:2)

在考虑低级优化之前,请查看代码并观察多次重新计算的数量。例如,f(wi,wii)不依赖于j,因此它们可以预先计算一次(见下文),也可以重写循环以使j上的循环成为嵌套循环。然后嵌套循环将只是矩阵的常量标量和两列之间的系数明智乘积(我不.net并假设j是索引列)。如果存储如果是column-major,那么这个操作应该由你的编译器完全矢量化(再次,我不知道.net,但任何C ++编译器都会这样做,如果你是Eigen,它将被显式矢量化)。这应该足以获得巨大的性能提升。

根据matrix的大小,您可能还会尝试通过预先计算的f(wi,wii)将优化的矩阵矩阵实现用于MatrixXd F;(使用Eigen的语言),然后观察整个计算金额为:

VectorXd v = your_vector;
MatrixXd F = MatrixXd::nullaryExpr(n,n,[&](Index i,Index j) {
                 return SomePowerFunctions(sqrt(v(i)), sqrt(v(j)));
             });
MatrixXd M = your_matrix;
MatrixXd FM = F * M;
VectorXd maxSum = (M.array() * FM.array()).colwise().sum();