加速对称矩阵的Math.NET声明

时间:2015-06-08 16:42:28

标签: c# matrix mathnet

我正在使用this constructor构建一个相当庞大的矩阵:

var M = Matrix<double>.Build.Dense(N, N, (i, j) => SomeRoutine(i, j));

N很大而且SomeRoutine很慢,所以我试图在这里和那里优化事物。我注意到,对于任何i, j暂停SomeRoutine(i, j) == SomeRoutine(j, i),即M是对称的,因此可以只定义一个上(或下)三角形,从而减少对SomeRoutine的调用次数从N^2N(N+1)/2,这很不错。

这是我进行此优化的方法。

var arr = new double[N, N];
for (int i = 0; i < N; i++)
{
  for (int j = 0; j < N; j++)
  {
    arr[i, j] = (i <= j) ? SomeRoutine(i, j) : arr[j, i];
  }
}
var M = Matrix<double>.Build.DenseOfArray(arr);

对我来说似乎并不优雅。有什么方法可以在保留lambda样式声明的同时接近相同的优化想法吗?或者我应该写一些掩盖for循环的包装器?

2 个答案:

答案 0 :(得分:1)

我认为将它分成两部分会更好:首先,计算下三角形,然后在一个单独的循环中分配从下三角形到上三角形的值。它的表现可能更高。您也可以使用Parallel.For作为外部循环(在计算期间)来加速它。

这样的事情:

public static void Main()
{
    var test = CreateLowerMatrix(5);
    CopyLowerToUpperMatrix(test, 5);
}

public static double[,] CreateLowerMatrix(int n)
{
    var result = new double[n,n];

    Parallel.For(0, n, r => {
        for (int c = r; c < n; ++c)
            result[r, c] = calc(r, c); });

    return result;
}

public static void CopyLowerToUpperMatrix(double[,] matrix, int n)
{
    for (int r = 1; r < n; ++r)
        for (int c = r + 1; c < n; ++c)
            matrix[c, r] = matrix[r, c];
}

public static double calc(int x, int y)
{
    return x * y;
}

我怀疑并列CopyLowerToUpperMatrix()

是有用的

答案 1 :(得分:1)

如果你想要一些简短的东西,你可以使用它。只是注意它并不是真的推荐,因为它不是真的可读,而且带有副作用的lambdas通常不受欢迎。想象一下,如果矩阵构建函数决定并行执行,将会出现竞争条件。

我建议从数组中构建矩阵,如问题或其他答案,但如果你决定使用它,只需确保它的评论很好。

var cache = new double?[N, N];
Func<int, int, double> WrapAndCacheSomeRoutine = (i, j) => 
    cache[i,j] ?? cache[j,i] ?? (cache[i,j] = SomeRoutine(i, j));
var M = Matrix<double>.Build.Dense(N, N, WrapAndCacheSomeRoutine);