1

我正在用这个构造函数构建一个相当大的矩阵:

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

N很大而且SomeRoutine很慢,所以我试图在这里和那里优化一些东西。我注意到对于任何i, jhold SomeRoutine(i, j) == SomeRoutine(j, i),即M是对称的,因此可以只定义一个上(或下)三角形,从而减少对SomeRoutinefrom N^2to的调用次数N(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循环的包装器?

4

2 回答 2

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().

于 2015-06-08T17:27:23.640 回答
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);
于 2015-06-09T16:44:14.547 回答