在C#中快速访问矩阵作为锯齿状数组

时间:2015-06-18 17:35:14

标签: c# performance matrix jagged-arrays

我创建了一个下三角距离矩阵(由于尺寸问题)作为锯齿状阵列 注意:对象之间的距离是对称的

var dm = new double[size][]
for (var i = 0; i < size; i++)
{
   dm[i] = new double[i+1];
   for (var j = 0; j < i+1; j++)
   {
      dm[i][j] = distance(data[i], data[j]);
   }
 }

我需要经常访问这个矩阵,所以我为它做了以下方法

private double GetValueOfDM(int row, int column, double[][] dm)
{
    return column <= row ? distanceMatrix[row][column] : distanceMatrix[column][row];
}

使用Visual Studio性能分析可以看出主要速度问题在于GetValueOfDM方法的唯一行。

有人知道如何加快速度吗?

3 个答案:

答案 0 :(得分:2)

我猜你是在紧密循环中使用它吗?由于自动边界检查,.NET中的数组不是/快/快。如果需要快速数组perf,请使用带缓冲区的指针:

sealed unsafe class DistanceData : IDisposable {
    private Double* buffer;
    private IntPtr  bufferLength; // .NET uses IntPtr as a size_t equivalent.
    private Int32   dim0Length;

    public DistanceData(Int32 size, Double[] data) {
        this.buffer       = (Double*)Marshal.AllocHGlobal( size * size );
        this.bufferLength = size * size;
        this.dim0Length   = size;

        for(int y = 0; y < size; y++) {
            for(int x = 0; x < y + 1; x++) {
                this.buffer[ y * this.dim0Length + x ] = Distance( data[y], data[x] );
            }
        }
    }

    public void Dispose() {
        Marshal.FreeHGlobal( this.buffer );
    }

    public Double GetValueOfDM(Int32 row, Int32 column) {
        // WARNING: Without validation or your own bounds-checking, invalid values of `row` and `column` will cause access-violation errors and crash your program. Ensure that code that calls `GetValueOfDM` is correct and will never submit invalid values.
        return this.buffer[ row * this.dim0Length  + column];
    }
}

答案 1 :(得分:1)

您可以删除方法中的条件并增加内存使用量以提高访问性能,如下所示:

{{1}}

既然您没有条件,编译器就可以删除分支预测。此外,您应该使用实际用例运行测试,以确保它实际上是一个问题。分析可能会发现分支条件将是代码中最慢的部分,但它并不一定意味着它实际上会使任何事情明显减慢。此外,您可以尝试在发布模式下运行它(使用编译器优化),以查看它如何影响性能。

如果你所在的系统没有可用的内存来增加数组大小,那么你所拥有的代码可能接近于访问锯齿状数组的最佳代码。

答案 2 :(得分:1)

您可以使用一维数组并像这样计算索引

i = (r * r + r) / 2 + c;

但你还是要检查r&lt; = c并进行翻转。 (r = row,c = column)

但这真的会更快吗?