我有一些矩阵运算,主要是处理像遍历矩阵的每个行和列的操作并执行乘法运算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因为:
但我想知道这些优势是否真的适用于我的矩阵特征?
注意:我本可以运行一两个样本来查找,但我相信在这里提出问题并将其记录在互联网上也会帮助其他人。
答案 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();