阅读2D矩阵的最快方法

时间:2017-10-10 06:41:07

标签: c# performance dictionary multidimensional-array profiling

我使用嵌套字典来存储在启动时具有已知值的2D矩阵,我发现它读起来太慢了。有什么更快的吗?

更新

我不知道为什么我的代码“无法正常工作”。它工作正常 - 但我想知道任何方法使它更快。以下详细信息是为了提供背景信息。

我也尝试使用自定义类作为键来展平嵌套字典,但这甚至更慢。

详细

我有一个500到7,000个对象的列表,我需要为每个可能的组合(250,000 - 49,000,000)存储一个值。

每种可能的组合都有一个默认值。此值将根据对象之间的依赖关系进行更改,每个对象平均有1个依赖项。对于每个依赖项,将有1到100个更新。平均而言,每次更新将读取5次值。

因此,对于一个例子,我有1,700个对象,2,890,000种可能的组合,有1,900个依赖,意味着9,500 - 95,000次读取。这个例子花了90多秒来计算!

这是初始化代码。我对这部分感到非常满意,因为它在不到一秒的时间内构建它。

var allCombinations = new Dictionary<int, Dictionary<int, int>>();
foreach (var thisObject in allObjects)
{
    var comboFor1Object = new Dictionary<int, int>();
    foreach (var otherObject in allObjects)
    {
        comboFor1Object.Add(otherObject.Id, (thisObject.Id == otherObject.Id ? 0 : 100));
    }
    allCombinations.Add(thisObject.Id, comboFor1Object);
}  

这是代码的简化更新部分 - 这是一个臭的缓慢部分。根据Visual Studio性能分析器 - 它特别是第9,10和11行,它读取字典。此方法占用了75%的时间,其中mscorlib.ni.dll占其中的52.9%。

foreach (var myObject in myDependency.Objects)
{
    foreach (var otherObject in myMatchingObjects)
    {
        if (myObject.Id == otherObject.Id)
        {
            continue;
        }
        var existingValue = allCombinations[myObject.Id][otherObject.Id];
        var minValue = allCombinations[myObject.Id][myDependency.FromObjectId] + allCombinations[myDependency.ToObjectId][otherObject.Id] + myDependency.MinValue;
        var maxValue = allCombinations[myObject.Id][myDependency.ToObjectId] + allCombinations[myDependency.FromObjectId][otherObject.Id] -myDependency.MaxValue;
        allCombinations[myObject.Id][otherObject.Id] = Math.Max(Math.Max(existingValue, minValue), maxValue);
    }
}

2 个答案:

答案 0 :(得分:0)

根据我对原始问题的评论,我会创建一个值类型(或者,如果你的C#/ .NET版本支持ValueTuple<int, int>,请使用它):

struct IdById
{
    public int Id1, Id2;

    public IdById(int a, int b)
    {
        Id1 = a; Id2 = b;
    }
}

这样,您的初始化代码应如下所示:

var allCombinations = new Dictionary<IdById, int>();

foreach (var thisObj in allObjects)
{
    foreach (var otherObj in allObjects)
    {
        var ids = new IdById(thisObj.Id, otherObj.Id);
        allCombinations[ids] = (ids.Id1 == ids.Id2 ? 0 : 100);
    }
}

你的“臭”很慢的部分&#39;:

foreach (var myObj in myDependency.Objects)
{
    foreach (var otherObj in myMatchingObjects)
    {
        if (myObj.Id != otherObj.Id)
        {
            var ids = new IdById(myObj.Id, otherObj.Id);
            var existingValue = allCombinations[ids];
            var minValue =
                allCombinations[new IdById(myObj.Id, myDependency.FromObjectId)] +
                allCombinations[new IdById(myDependency.ToObjectId, otherObj.Id)] +
                myDependency.MinValue;
            var maxValue =
                allCombinations[new IdById(myObj.Id, myDependency.ToObjectId)] +
                allCombinations[new IdById(myDependency.FromObjectId, otherObj.Id)] -
                myDependency.MaxValue;
            allCombinations[ids] =
                Math.Max(Math.Max(existingValue, minValue), maxValue);
        }
    }
}

最终是否会更快,你需要测试......

答案 1 :(得分:0)

在注释中使用 dumetrulo 建议的2D数组的速度是使用嵌套字典进行读取的速度的两倍。尽快开放有关任何事情的想法!

StrictModes yes
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile      %h/.ssh/authorized_keys
HostbasedAuthentication no
IgnoreRhosts yes
RhostsRSAAuthentication no

这使得慢代码像这样:

for (int i = 0; i < allObjects.Count; i++)
{
    //new property to record the index in the array
    allObjects[i].Index = i;
}

var allCombinations = new int[allObjects.Count, allObjects.Count];
foreach (var thisObj in allObjects)
{
    foreach (var otherObj in allObjects)
    {
        allCombinations[thisObj.Index, otherObj.Index] = (thisObj.Id == otherObj.Id ? 0 : 100);
    }
}